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);
        }
示例#2
0
        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);
        }
示例#3
0
        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);
        }
示例#4
0
        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);
        }