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);
}
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();
}
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);
}
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));
}
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;
}
Aggregations