Search in sources :

Example 6 with ECPoint

use of org.spongycastle.math.ec.ECPoint in project rskj by rsksmart.

the class HandshakeHandler method initiate.

public void initiate(ChannelHandlerContext ctx) throws Exception {
    loggerNet.trace("RLPX protocol activated");
    nodeId = myKey.getNodeId();
    byte[] remotePublicBytes = new byte[remoteId.length + 1];
    System.arraycopy(remoteId, 0, remotePublicBytes, 1, remoteId.length);
    // uncompressed
    remotePublicBytes[0] = 0x04;
    ECPoint remotePublic = ECKey.fromPublicOnly(remotePublicBytes).getPubKeyPoint();
    handshake = new EncryptionHandshake(remotePublic);
    Object msg;
    if (config.eip8()) {
        AuthInitiateMessageV4 initiateMessage = handshake.createAuthInitiateV4(myKey);
        initiatePacket = handshake.encryptAuthInitiateV4(initiateMessage);
        msg = initiateMessage;
    } else {
        AuthInitiateMessage initiateMessage = handshake.createAuthInitiate(null, myKey);
        initiatePacket = handshake.encryptAuthMessage(initiateMessage);
        msg = initiateMessage;
    }
    final ByteBuf byteBufMsg = ctx.alloc().buffer(initiatePacket.length);
    byteBufMsg.writeBytes(initiatePacket);
    ctx.writeAndFlush(byteBufMsg).sync();
    channel.getNodeStatistics().rlpxAuthMessagesSent.add();
    loggerNet.trace("To: \t{} \tSend: \t{}", ctx.channel().remoteAddress(), msg);
}
Also used : ECPoint(org.spongycastle.math.ec.ECPoint) ByteBuf(io.netty.buffer.ByteBuf)

Example 7 with ECPoint

use of org.spongycastle.math.ec.ECPoint in project rskj by rsksmart.

the class HandshakeHandler method decodeHandshake.

// consume handshake, producing no resulting message to upper layers
private void decodeHandshake(final ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
    if (handshake.isInitiator()) {
        if (frameCodec == null) {
            byte[] responsePacket = new byte[AuthResponseMessage.getLength() + ECIESCoder.getOverhead()];
            if (!buffer.isReadable(responsePacket.length)) {
                return;
            }
            buffer.readBytes(responsePacket);
            try {
                // trying to decode as pre-EIP-8
                AuthResponseMessage response = handshake.handleAuthResponse(myKey, initiatePacket, responsePacket);
                loggerNet.trace("From: \t{} \tRecv: \t{}", ctx.channel().remoteAddress(), response);
            } catch (Throwable t) {
                // it must be format defined by EIP-8 then
                responsePacket = readEIP8Packet(buffer, responsePacket);
                if (responsePacket == null) {
                    return;
                }
                AuthResponseMessageV4 response = handshake.handleAuthResponseV4(myKey, initiatePacket, responsePacket);
                loggerNet.trace("From: \t{} \tRecv: \t{}", ctx.channel().remoteAddress(), response);
            }
            EncryptionHandshake.Secrets secrets = this.handshake.getSecrets();
            this.frameCodec = new FrameCodec(secrets);
            loggerNet.trace("auth exchange done");
            channel.sendHelloMessage(ctx, frameCodec, Hex.toHexString(nodeId), null);
        } else {
            loggerWire.debug("MessageCodec: Buffer bytes: " + buffer.readableBytes());
            List<Frame> frames = frameCodec.readFrames(buffer);
            if (frames == null || frames.isEmpty()) {
                return;
            }
            Frame frame = frames.get(0);
            byte[] payload = ByteStreams.toByteArray(frame.getStream());
            if (frame.getType() == P2pMessageCodes.HELLO.asByte()) {
                HelloMessage helloMessage = new HelloMessage(payload);
                loggerNet.trace("From: \t{} \tRecv: \t{}", ctx.channel().remoteAddress(), helloMessage);
                isHandshakeDone = true;
                this.channel.publicRLPxHandshakeFinished(ctx, frameCodec, helloMessage);
                recordSuccessfulHandshake(ctx);
            } else {
                DisconnectMessage message = new DisconnectMessage(payload);
                loggerNet.trace("From: \t{} \tRecv: \t{}", channel, message);
                channel.getNodeStatistics().nodeDisconnectedRemote(message.getReason());
            }
        }
    } else {
        loggerWire.debug("Not initiator.");
        if (frameCodec == null) {
            loggerWire.debug("FrameCodec == null");
            byte[] authInitPacket = new byte[AuthInitiateMessage.getLength() + ECIESCoder.getOverhead()];
            if (!buffer.isReadable(authInitPacket.length)) {
                return;
            }
            buffer.readBytes(authInitPacket);
            this.handshake = new EncryptionHandshake();
            byte[] responsePacket;
            try {
                // trying to decode as pre-EIP-8
                AuthInitiateMessage initiateMessage = handshake.decryptAuthInitiate(authInitPacket, myKey);
                loggerNet.trace("From: \t{} \tRecv: \t{}", ctx.channel().remoteAddress(), initiateMessage);
                AuthResponseMessage response = handshake.makeAuthInitiate(initiateMessage, myKey);
                loggerNet.trace("To: \t{} \tSend: \t{}", ctx.channel().remoteAddress(), response);
                responsePacket = handshake.encryptAuthResponse(response);
            } catch (Throwable t) {
                // it must be format defined by EIP-8 then
                try {
                    authInitPacket = readEIP8Packet(buffer, authInitPacket);
                    if (authInitPacket == null) {
                        return;
                    }
                    AuthInitiateMessageV4 initiateMessage = handshake.decryptAuthInitiateV4(authInitPacket, myKey);
                    loggerNet.trace("From: \t{} \tRecv: \t{}", ctx.channel().remoteAddress(), initiateMessage);
                    AuthResponseMessageV4 response = handshake.makeAuthInitiateV4(initiateMessage, myKey);
                    loggerNet.trace("To: \t{} \tSend: \t{}", ctx.channel().remoteAddress(), response);
                    responsePacket = handshake.encryptAuthResponseV4(response);
                } catch (InvalidCipherTextException ce) {
                    loggerNet.warn("Can't decrypt AuthInitiateMessage from " + ctx.channel().remoteAddress() + ". Most likely the remote peer used wrong public key (NodeID) to encrypt message.");
                    return;
                }
            }
            handshake.agreeSecret(authInitPacket, responsePacket);
            EncryptionHandshake.Secrets secrets = this.handshake.getSecrets();
            this.frameCodec = new FrameCodec(secrets);
            ECPoint remotePubKey = this.handshake.getRemotePublicKey();
            byte[] compressed = remotePubKey.getEncoded(false);
            this.remoteId = new byte[compressed.length - 1];
            System.arraycopy(compressed, 1, this.remoteId, 0, this.remoteId.length);
            channel.setNode(remoteId);
            final ByteBuf byteBufMsg = ctx.alloc().buffer(responsePacket.length);
            byteBufMsg.writeBytes(responsePacket);
            ctx.writeAndFlush(byteBufMsg).sync();
        } else {
            List<Frame> frames = frameCodec.readFrames(buffer);
            if (frames == null || frames.isEmpty()) {
                return;
            }
            Frame frame = frames.get(0);
            Message message = new P2pMessageFactory().create((byte) frame.getType(), ByteStreams.toByteArray(frame.getStream()));
            loggerNet.trace("From: \t{} \tRecv: \t{}", ctx.channel().remoteAddress(), message);
            if (frame.getType() == P2pMessageCodes.DISCONNECT.asByte()) {
                loggerNet.info("Active remote peer disconnected right after handshake.");
                return;
            }
            if (frame.getType() != P2pMessageCodes.HELLO.asByte()) {
                throw new RuntimeException("The message type is not HELLO or DISCONNECT: " + message);
            }
            HelloMessage inboundHelloMessage = (HelloMessage) message;
            // Secret authentication finish here
            channel.sendHelloMessage(ctx, frameCodec, Hex.toHexString(nodeId), inboundHelloMessage);
            isHandshakeDone = true;
            this.channel.publicRLPxHandshakeFinished(ctx, frameCodec, inboundHelloMessage);
            recordSuccessfulHandshake(ctx);
        }
    }
    channel.getNodeStatistics().rlpxInHello.add();
}
Also used : Frame(org.ethereum.net.rlpx.FrameCodec.Frame) InvalidCipherTextException(org.spongycastle.crypto.InvalidCipherTextException) HelloMessage(org.ethereum.net.p2p.HelloMessage) DisconnectMessage(org.ethereum.net.p2p.DisconnectMessage) Message(org.ethereum.net.message.Message) HelloMessage(org.ethereum.net.p2p.HelloMessage) DisconnectMessage(org.ethereum.net.p2p.DisconnectMessage) P2pMessageFactory(org.ethereum.net.p2p.P2pMessageFactory) ECPoint(org.spongycastle.math.ec.ECPoint) ByteBuf(io.netty.buffer.ByteBuf)

Example 8 with ECPoint

use of org.spongycastle.math.ec.ECPoint in project java-tron by tronprotocol.

the class ECKey method recoverPubBytesFromSignature.

/**
 * <p>Given the components of a signature and a selector value, recover and return the public key
 * that generated the signature according to the algorithm in SEC1v2 section 4.1.6.</p>
 *
 * <p> <p>The recId is an index from 0 to 3 which indicates which of the 4 possible allKeys is the
 * correct one. Because the key recovery operation yields multiple potential allKeys, the correct
 * key must either be stored alongside the signature, or you must be willing to try each recId in
 * turn until you find one that outputs the key you are expecting.</p>
 *
 * <p> <p>If this method returns null it means recovery was not possible and recId should be
 * iterated.</p>
 *
 * <p> <p>Given the above two points, a correct usage of this method is inside a for loop from 0
 * to 3, and if the output is null OR a key that is not the one you expect, you try again with the
 * next recId.</p>
 *
 * @param recId Which possible key to recover.
 * @param sig the R and S components of the signature, wrapped.
 * @param messageHash Hash of the data that was signed.
 * @return 65-byte encoded public key
 */
@Nullable
public static byte[] recoverPubBytesFromSignature(int recId, ECDSASignature sig, byte[] messageHash) {
    check(recId >= 0, "recId must be positive");
    check(sig.r.signum() >= 0, "r must be positive");
    check(sig.s.signum() >= 0, "s must be positive");
    check(messageHash != null, "messageHash must not be null");
    // 1.0 For j from 0 to h   (h == recId here and the loop is outside
    // this function)
    // 1.1 Let x = r + jn
    // Curve order.
    BigInteger n = CURVE.getN();
    BigInteger i = BigInteger.valueOf((long) recId / 2);
    BigInteger x = sig.r.add(i.multiply(n));
    // 1.2. Convert the integer x to an octet string X of length mlen
    // using the conversion routine
    // specified in Section 2.3.7, where mlen = ⌈(log2 p)/8⌉ or
    // mlen = ⌈m/8⌉.
    // 1.3. Convert the octet string (16 set binary digits)||X to an
    // elliptic curve point R using the
    // conversion routine specified in Section 2.3.4. If this
    // conversion routine outputs “invalid”, then
    // do another iteration of Step 1.
    // 
    // More concisely, what these points mean is to use X as a compressed
    // public key.
    ECCurve.Fp curve = (ECCurve.Fp) CURVE.getCurve();
    // Bouncy Castle is not consistent
    BigInteger prime = curve.getQ();
    // about the letter it uses for the prime.
    if (x.compareTo(prime) >= 0) {
        // takes place modulo Q.
        return null;
    }
    // Compressed allKeys require you to know an extra bit of data about the
    // y-coord as there are two possibilities.
    // So it's encoded in the recId.
    ECPoint R = decompressKey(x, (recId & 1) == 1);
    // Step 1 (callers responsibility).
    if (!R.multiply(n).isInfinity()) {
        return null;
    }
    // 1.5. Compute e from M using Steps 2 and 3 of ECDSA signature
    // verification.
    BigInteger e = new BigInteger(1, messageHash);
    // 1.6. For k from 1 to 2 do the following.   (loop is outside this
    // function via iterating recId)
    // 1.6.1. Compute a candidate public key as:
    // Q = mi(r) * (sR - eG)
    // 
    // Where mi(x) is the modular multiplicative inverse. We transform
    // this into the following:
    // Q = (mi(r) * s ** R) + (mi(r) * -e ** G)
    // Where -e is the modular additive inverse of e, that is z such that
    // z + e = 0 (mod n). In the above equation
    // ** is point multiplication and + is point addition (the EC group
    // operator).
    // 
    // We can find the additive inverse by subtracting e from zero then
    // taking the mod. For example the additive
    // inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and -3 mod
    // 11 = 8.
    BigInteger eInv = BigInteger.ZERO.subtract(e).mod(n);
    BigInteger rInv = sig.r.modInverse(n);
    BigInteger srInv = rInv.multiply(sig.s).mod(n);
    BigInteger eInvrInv = rInv.multiply(eInv).mod(n);
    ECPoint.Fp q = (ECPoint.Fp) ECAlgorithms.sumOfTwoMultiplies(CURVE.getG(), eInvrInv, R, srInv);
    return q.getEncoded(/* compressed */
    false);
}
Also used : ECCurve(org.spongycastle.math.ec.ECCurve) BigInteger(java.math.BigInteger) ECPoint(org.spongycastle.math.ec.ECPoint) Nullable(javax.annotation.Nullable)

Example 9 with ECPoint

use of org.spongycastle.math.ec.ECPoint in project SmartMesh_Android by SmartMeshFoundation.

the class Sign2 method recoverFromSignature.

/**
 * <p>Given the components of a signature and a selector value, recover and return the public
 * key that generated the signature according to the algorithm in SEC1v2 section 4.1.6.</p>
 *
 * <p>The recId is an index from 0 to 3 which indicates which of the 4 possible keys is the
 * correct one. Because the key recovery operation yields multiple potential keys, the correct
 * key must either be stored alongside the
 * signature, or you must be willing to try each recId in turn until you find one that outputs
 * the key you are expecting.</p>
 *
 * <p>If this method returns null it means recovery was not possible and recId should be
 * iterated.</p>
 *
 * <p>Given the above two points, a correct usage of this method is inside a for loop from
 * 0 to 3, and if the output is null OR a key that is not the one you expect, you try again
 * with the next recId.</p>
 *
 * @param recId Which possible key to recover.
 * @param sig the R and S components of the signature, wrapped.
 * @param message Hash of the data that was signed.
 * @return An ECKey containing only the public part, or null if recovery wasn't possible.
 */
private static BigInteger recoverFromSignature(int recId, ECDSASignature sig, byte[] message) {
    verifyPrecondition(recId >= 0, "recId must be positive");
    verifyPrecondition(sig.r.signum() >= 0, "r must be positive");
    verifyPrecondition(sig.s.signum() >= 0, "s must be positive");
    verifyPrecondition(message != null, "message cannot be null");
    // 1.0 For j from 0 to h   (h == recId here and the loop is outside this function)
    // 1.1 Let x = r + jn
    // Curve order.
    BigInteger n = CURVE.getN();
    BigInteger i = BigInteger.valueOf((long) recId / 2);
    BigInteger x = sig.r.add(i.multiply(n));
    // 1.2. Convert the integer x to an octet string X of length mlen using the conversion
    // routine specified in Section 2.3.7, where mlen = ⌈(log2 p)/8⌉ or mlen = ⌈m/8⌉.
    // 1.3. Convert the octet string (16 set binary digits)||X to an elliptic curve point R
    // using the conversion routine specified in Section 2.3.4. If this conversion
    // routine outputs “invalid”, then do another iteration of Step 1.
    // 
    // More concisely, what these points mean is to use X as a compressed public key.
    BigInteger prime = SecP256K1Curve.q;
    if (x.compareTo(prime) >= 0) {
        // Cannot have point co-ordinates larger than this as everything takes place modulo Q.
        return null;
    }
    // Compressed keys require you to know an extra bit of data about the y-coord as there are
    // two possibilities. So it's encoded in the recId.
    ECPoint R = decompressKey(x, (recId & 1) == 1);
    // responsibility).
    if (!R.multiply(n).isInfinity()) {
        return null;
    }
    // 1.5. Compute e from M using Steps 2 and 3 of ECDSA signature verification.
    BigInteger e = new BigInteger(1, message);
    // 1.6. For k from 1 to 2 do the following.   (loop is outside this function via
    // iterating recId)
    // 1.6.1. Compute a candidate public key as:
    // Q = mi(r) * (sR - eG)
    // 
    // Where mi(x) is the modular multiplicative inverse. We transform this into the following:
    // Q = (mi(r) * s ** R) + (mi(r) * -e ** G)
    // Where -e is the modular additive inverse of e, that is z such that z + e = 0 (mod n).
    // In the above equation ** is point multiplication and + is point addition (the EC group
    // operator).
    // 
    // We can find the additive inverse by subtracting e from zero then taking the mod. For
    // example the additive inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and
    // -3 mod 11 = 8.
    BigInteger eInv = BigInteger.ZERO.subtract(e).mod(n);
    BigInteger rInv = sig.r.modInverse(n);
    BigInteger srInv = rInv.multiply(sig.s).mod(n);
    BigInteger eInvrInv = rInv.multiply(eInv).mod(n);
    ECPoint q = ECAlgorithms.sumOfTwoMultiplies(CURVE.getG(), eInvrInv, R, srInv);
    byte[] qBytes = q.getEncoded(false);
    // We remove the prefix
    return new BigInteger(1, Arrays.copyOfRange(qBytes, 1, qBytes.length));
}
Also used : BigInteger(java.math.BigInteger) ECPoint(org.spongycastle.math.ec.ECPoint)

Example 10 with ECPoint

use of org.spongycastle.math.ec.ECPoint in project jmulticard by ctt-gob-es.

the class PaceChannelHelper method byteArrayToECPoint.

private static ECPoint byteArrayToECPoint(final byte[] value, final ECCurve.Fp curve) throws IllegalArgumentException {
    final byte[] x = new byte[(value.length - 1) / 2];
    final byte[] y = new byte[(value.length - 1) / 2];
    if (value[0] != (byte) 0x04) {
        // $NON-NLS-1$
        throw new IllegalArgumentException("No se ha encontrado un punto no comprimido");
    }
    System.arraycopy(value, 1, x, 0, (value.length - 1) / 2);
    System.arraycopy(value, 1 + (value.length - 1) / 2, y, 0, (value.length - 1) / 2);
    final ECFieldElement.Fp xE = (org.spongycastle.math.ec.ECFieldElement.Fp) curve.fromBigInteger(new BigInteger(1, x));
    final ECFieldElement.Fp yE = (org.spongycastle.math.ec.ECFieldElement.Fp) curve.fromBigInteger(new BigInteger(1, y));
    final ECPoint point = curve.createPoint(xE.toBigInteger(), yE.toBigInteger());
    return point;
}
Also used : BigInteger(java.math.BigInteger) Fp(org.spongycastle.math.ec.ECCurve.Fp) ECFieldElement(org.spongycastle.math.ec.ECFieldElement) ECPoint(org.spongycastle.math.ec.ECPoint)

Aggregations

ECPoint (org.spongycastle.math.ec.ECPoint)18 BigInteger (java.math.BigInteger)12 ECCurve (org.spongycastle.math.ec.ECCurve)5 Test (org.junit.Test)3 Nullable (android.support.annotation.Nullable)2 ByteBuf (io.netty.buffer.ByteBuf)2 ByteArrayInputStream (java.io.ByteArrayInputStream)2 ByteArrayOutputStream (java.io.ByteArrayOutputStream)2 IOException (java.io.IOException)2 SecureRandom (java.security.SecureRandom)2 Nullable (javax.annotation.Nullable)2 InvalidCipherTextException (org.spongycastle.crypto.InvalidCipherTextException)2 ECKeyPairGenerator (org.spongycastle.crypto.generators.ECKeyPairGenerator)2 Fp (org.spongycastle.math.ec.ECCurve.Fp)2 CommandApdu (es.gob.jmulticard.apdu.CommandApdu)1 ResponseApdu (es.gob.jmulticard.apdu.ResponseApdu)1 ApduConnectionException (es.gob.jmulticard.apdu.connection.ApduConnectionException)1 GeneralAuthenticateApduCommand (es.gob.jmulticard.apdu.iso7816four.GeneralAuthenticateApduCommand)1 MseSetPaceAlgorithmApduCommand (es.gob.jmulticard.apdu.iso7816four.pace.MseSetPaceAlgorithmApduCommand)1 Tlv (es.gob.jmulticard.asn1.Tlv)1