public Packet Auth(NodeId remoteNodeId, EncryptionHandshake handshake) { handshake.RemoteNodeId = remoteNodeId; handshake.InitiatorNonce = _cryptoRandom.GenerateRandomBytes(32); handshake.EphemeralPrivateKey = new PrivateKey(_cryptoRandom.GenerateRandomBytes(32)); byte[] staticSharedSecret = BouncyCrypto.Agree(_privateKey, remoteNodeId.PublicKey); byte[] forSigning = staticSharedSecret.Xor(handshake.InitiatorNonce); AuthEip8Message authMessage = new AuthEip8Message(); authMessage.Nonce = handshake.InitiatorNonce; authMessage.PublicKey = _privateKey.PublicKey; authMessage.Signature = _signer.Sign(handshake.EphemeralPrivateKey, new Keccak(forSigning)); byte[] authData = _messageSerializationService.Serialize(authMessage); int size = authData.Length + 32 + 16 + 65; // data + MAC + IV + pub byte[] sizeBytes = size.ToBigEndianByteArray().Slice(2, 2); byte[] packetData = _eciesCipher.Encrypt( remoteNodeId.PublicKey, authData, sizeBytes); handshake.AuthPacket = new Packet(Bytes.Concat(sizeBytes, packetData)); return(handshake.AuthPacket); }
public void Can_calculate_agreement() { PrivateKey privateKey1 = TestObject.PrivateKeyA; PrivateKey privateKey2 = TestObject.PrivateKeyB; byte[] sharedSecret1 = BouncyCrypto.Agree(privateKey1, privateKey2.PublicKey); byte[] sharedSecret2 = BouncyCrypto.Agree(privateKey2, privateKey1.PublicKey); Assert.AreEqual(sharedSecret1, sharedSecret2); }
public void Can_calculate_agreement() { CryptoRandom random = new CryptoRandom(); PrivateKey privateKey1 = new PrivateKey(random.GenerateRandomBytes(32)); PrivateKey privateKey2 = new PrivateKey(random.GenerateRandomBytes(32)); byte[] sharedSecret1 = BouncyCrypto.Agree(privateKey1, privateKey2.PublicKey); byte[] sharedSecret2 = BouncyCrypto.Agree(privateKey2, privateKey1.PublicKey); Assert.AreEqual(sharedSecret1, sharedSecret2); }
private void SetSecrets(EncryptionHandshake handshake, HandshakeRole handshakeRole) { byte[] ephemeralSharedSecret = BouncyCrypto.Agree(handshake.EphemeralPrivateKey, handshake.RemoteEphemeralPublicKey); byte[] nonceHash = Keccak.Compute(Bytes.Concat(handshake.RecipientNonce, handshake.InitiatorNonce)).Bytes; byte[] sharedSecret = Keccak.Compute(Bytes.Concat(ephemeralSharedSecret, nonceHash)).Bytes; byte[] token = Keccak.Compute(sharedSecret).Bytes; byte[] aesSecret = Keccak.Compute(Bytes.Concat(ephemeralSharedSecret, sharedSecret)).Bytes; Array.Clear(sharedSecret, 0, sharedSecret.Length); // TODO: it was passed in the concat for Keccak so not good enough byte[] macSecret = Keccak.Compute(Bytes.Concat(ephemeralSharedSecret, aesSecret)).Bytes; Array.Clear(ephemeralSharedSecret, 0, ephemeralSharedSecret.Length); // TODO: it was passed in the concat for Keccak so not good enough handshake.Secrets = new EncryptionSecrets(); handshake.Secrets.Token = token; handshake.Secrets.AesSecret = aesSecret; handshake.Secrets.MacSecret = macSecret; KeccakDigest mac1 = new KeccakDigest(MacBitsSize); mac1.BlockUpdate(macSecret.Xor(handshake.RecipientNonce), 0, macSecret.Length); mac1.BlockUpdate(handshake.AuthPacket.Data, 0, handshake.AuthPacket.Data.Length); KeccakDigest mac2 = new KeccakDigest(MacBitsSize); mac2.BlockUpdate(macSecret.Xor(handshake.InitiatorNonce), 0, macSecret.Length); mac2.BlockUpdate(handshake.AckPacket.Data, 0, handshake.AckPacket.Data.Length); if (handshakeRole == HandshakeRole.Initiator) { handshake.Secrets.EgressMac = mac1; handshake.Secrets.IngressMac = mac2; } else { handshake.Secrets.EgressMac = mac2; handshake.Secrets.IngressMac = mac1; } if (_logger.IsTrace) { _logger.Trace($"Agreed secrets with {handshake.RemoteNodeId}"); } #if DEBUG if (_logger.IsTrace) { _logger.Trace($"{handshake.RemoteNodeId} ephemeral private key {handshake.EphemeralPrivateKey}"); _logger.Trace($"{handshake.RemoteNodeId} initiator nonce {handshake.InitiatorNonce.ToHexString()}"); _logger.Trace($"{handshake.RemoteNodeId} recipient nonce {handshake.RecipientNonce.ToHexString()}"); _logger.Trace($"{handshake.RemoteNodeId} remote ephemeral public key {handshake.RemoteEphemeralPublicKey}"); _logger.Trace($"{handshake.RemoteNodeId} remote public key {handshake.RemoteNodeId}"); _logger.Trace($"{handshake.RemoteNodeId} auth packet {handshake.AuthPacket.Data.ToHexString()}"); _logger.Trace($"{handshake.RemoteNodeId} ack packet {handshake.AckPacket.Data.ToHexString()}"); } #endif }
public Packet Ack(EncryptionHandshake handshake, Packet auth) { handshake.AuthPacket = auth; AuthMessageBase authMessage; bool isOld = false; try { _logger.Info($"Trying to decrypt an old version of {nameof(AuthMessage)}"); byte[] plaintextOld = _eciesCipher.Decrypt(_privateKey, auth.Data); authMessage = _messageSerializationService.Deserialize <AuthMessage>(plaintextOld); isOld = true; } catch (Exception) { _logger.Info($"Trying to decrypt version 4 of {nameof(AuthEip8Message)}"); byte[] sizeData = auth.Data.Slice(0, 2); byte[] plaintext = _eciesCipher.Decrypt(_privateKey, auth.Data.Slice(2), sizeData); authMessage = _messageSerializationService.Deserialize <AuthEip8Message>(plaintext); } var nodeId = new NodeId(authMessage.PublicKey); _logger.Debug($"Received AUTH v{authMessage.Version} from {nodeId}"); handshake.RemoteNodeId = nodeId; handshake.RecipientNonce = _cryptoRandom.GenerateRandomBytes(32); handshake.EphemeralPrivateKey = new PrivateKey(_cryptoRandom.GenerateRandomBytes(32)); handshake.InitiatorNonce = authMessage.Nonce; byte[] staticSharedSecret = BouncyCrypto.Agree(_privateKey, handshake.RemoteNodeId.PublicKey); byte[] forSigning = staticSharedSecret.Xor(handshake.InitiatorNonce); handshake.RemoteEphemeralPublicKey = _signer.RecoverPublicKey(authMessage.Signature, new Keccak(forSigning)); byte[] ackData; if (isOld) // what was the difference? shall I really include ephemeral public key in v4? { _logger.Debug($"Building an {nameof(AckMessage)}"); AckMessage ackMessage = new AckMessage(); ackMessage.EphemeralPublicKey = handshake.EphemeralPrivateKey.PublicKey; ackMessage.Nonce = handshake.RecipientNonce; ackData = _messageSerializationService.Serialize(ackMessage); } else { _logger.Debug($"Building an {nameof(AckEip8Message)}"); AckEip8Message ackMessage = new AckEip8Message(); ackMessage.EphemeralPublicKey = handshake.EphemeralPrivateKey.PublicKey; ackMessage.Nonce = handshake.RecipientNonce; ackData = _messageSerializationService.Serialize(ackMessage); } int size = ackData.Length + 32 + 16 + 65; // data + MAC + IV + pub byte[] sizeBytes = size.ToBigEndianByteArray().Slice(2, 2); byte[] packetData = _eciesCipher.Encrypt(handshake.RemoteNodeId.PublicKey, ackData, sizeBytes); handshake.AckPacket = new Packet(Bytes.Concat(sizeBytes, packetData)); SetSecrets(handshake, EncryptionHandshakeRole.Recipient); return(handshake.AckPacket); }