예제 #1
0
        public void EciesDecryptStaticTest(string receiverPrivateKey, string expectedResult, string encryptedData)
        {
            // Generate a keypair
            EthereumEcdsa keypair = EthereumEcdsa.Create(receiverPrivateKey.HexToBytes(), EthereumEcdsaKeyType.Private);

            // Decrypt the encrypted data with the given key.
            byte[] decrypted = Ecies.Decrypt(keypair, encryptedData.HexToBytes(), null);

            // Verify the decrypted result was as expected.
            Assert.Equal(expectedResult.HexToBytes(), decrypted);
        }
예제 #2
0
        public void EciesEncryptDecryptTest()
        {
            string[] testDataSets = new string[] { "okayAESstrTest", "test2", "and another \x00 test. but this one is a sentence with \x11 weird characters." };

            for (int i = 0; i < testDataSets.Length; i++)
            {
                // Generate a keypair
                EthereumEcdsa keypair = EthereumEcdsa.Generate();

                byte[] testData = Encoding.UTF8.GetBytes(testDataSets[i]);

                byte[] encrypted = Ecies.Encrypt(keypair, testData, null);
                byte[] decrypted = Ecies.Decrypt(keypair, encrypted, null);

                string result = Encoding.UTF8.GetString(decrypted);

                Assert.Equal(testDataSets[i], result);
            }
        }
예제 #3
0
        /// <summary>
        /// Verifies the provided encrypted serialized authentication acknowledgement data received from the initiator.
        /// If verification fails, an appropriate exception will be thrown. If no exception is thrown, the verification
        /// has succeeded.
        /// </summary>
        /// <param name="authAckData">The encrypted serialized authentication acknowledgement data to verify.</param>
        public void VerifyAuthenticationAcknowledgement(byte[] authAckData)
        {
            // Verify this is the initiator role.
            if (Role != RLPxSessionRole.Initiator)
            {
                throw new Exception("RLPx auth-ack data should only be verified by the initiator.");
            }

            // Verify the session state is correct.
            if (SessionState != RLPxSessionState.AuthenticationCompleted)
            {
                throw new Exception("RLPx auth-ack verification should only be performed after auth was created/sent.");
            }

            // Try to deserialize the data as a standard authentication packet.
            // The data is currently encrypted serialized data, so it will also need to be decrypted.
            RLPxAuthAckBase authAckMessage = null;

            try
            {
                // Set the auth-ack data
                AuthAckData = authAckData.Slice(0, AUTH_ACK_STANDARD_ENCRYPTED_SIZE);

                // The authentication data can simply be decrypted without any shared mac.
                byte[] decryptedAuthData = Ecies.Decrypt(LocalPrivateKey, AuthAckData, null);

                // Try to parse the decrypted authentication data.
                authAckMessage          = new RLPxAuthAckStandard(decryptedAuthData);
                UsingEIP8Authentication = false;

                // Set the remote version
                RemoteVersion = MAX_SUPPORTED_VERSION;
            }
            catch (Exception authAckStandardEx)
            {
                try
                {
                    // EIP8 has a uint16 denoting encrypted data size, and the data to decrypt follows.
                    Memory <byte> authAckDataMem   = authAckData;
                    Memory <byte> sharedMacDataMem = authAckDataMem.Slice(0, 2);
                    ushort        encryptedSize    = (ushort)BigIntegerConverter.GetBigInteger(sharedMacDataMem.Span, false, sharedMacDataMem.Length);
                    Memory <byte> encryptedData    = authAckDataMem.Slice(2, encryptedSize);

                    // Set our auth-ack data
                    AuthAckData = authAckDataMem.Slice(0, sharedMacDataMem.Length + encryptedSize).ToArray();

                    // Split the shared mac from the authentication data
                    byte[] decryptedAuthData = Ecies.Decrypt(LocalPrivateKey, encryptedData, sharedMacDataMem);

                    // Try to parse the decrypted EIP8 authentication data.
                    RLPxAuthAckEIP8 authEip8Message = new RLPxAuthAckEIP8(decryptedAuthData);
                    UsingEIP8Authentication = true;

                    // Set the generic authentication data object.
                    authAckMessage = authEip8Message;

                    // Set the remote version
                    RemoteVersion = authEip8Message.Version;
                }
                catch (Exception authAckEip8Ex)
                {
                    string exceptionMessage = "Could not deserialize RLPx auth-ack data in either standard or EIP8 format.\r\n";
                    exceptionMessage += $"Standard Auth-Ack Error: {authAckStandardEx.Message}\r\n";
                    exceptionMessage += $"EIP8 Auth-Ack Error: {authAckEip8Ex.Message}";
                    throw new Exception(exceptionMessage);
                }
            }

            // Set the responder nonce
            ResponderNonce = authAckMessage.Nonce;

            // Set the remote public key.
            RemoteEphermalPublicKey = EthereumEcdsa.Create(authAckMessage.EphemeralPublicKey, EthereumEcdsaKeyType.Public);

            // Set the session state
            SessionState = RLPxSessionState.AcknowledgementCompleted;
        }
예제 #4
0
        /// <summary>
        /// Verifies the provided encrypted serialized authentication data received from the initiator.
        /// If verification fails, an appropriate exception will be thrown. If no exception is thrown,
        /// the verification has succeeded.
        /// </summary>
        /// <param name="authData">The encrypted serialized authentication data to verify.</param>
        public void VerifyAuthentication(byte[] authData)
        {
            // Verify this is the responder role.
            if (Role != RLPxSessionRole.Responder)
            {
                throw new Exception("RLPx auth data should only be verified by the responder.");
            }

            // Verify the session state is correct.
            if (SessionState != RLPxSessionState.Initial)
            {
                throw new Exception("RLPx auth verification should only be performed on a new session.");
            }

            // Try to deserialize the data as a standard authentication packet.
            // The data is currently encrypted serialized data, so it will also need to be decrypted.
            RLPxAuthBase authenticationMessage = null;

            try
            {
                // Set the auth data
                AuthData = authData.Slice(0, AUTH_STANDARD_ENCRYPTED_SIZE);

                // The authentication data can simply be decrypted without any shared mac.
                byte[] decryptedAuthData = Ecies.Decrypt(LocalPrivateKey, AuthData, null);

                // Try to parse the decrypted authentication data.
                authenticationMessage   = new RLPxAuthStandard(decryptedAuthData);
                UsingEIP8Authentication = false;

                // Set the remote version
                RemoteVersion = MAX_SUPPORTED_VERSION;
            }
            catch (Exception authStandardEx)
            {
                try
                {
                    // EIP8 has a uint16 denoting encrypted data size, and the data to decrypt follows.
                    Memory <byte> authDataMem      = authData;
                    Memory <byte> sharedMacDataMem = authDataMem.Slice(0, 2);
                    ushort        encryptedSize    = (ushort)BigIntegerConverter.GetBigInteger(sharedMacDataMem.Span, false, sharedMacDataMem.Length);
                    Memory <byte> encryptedData    = authDataMem.Slice(2, encryptedSize);

                    // Set our auth data
                    AuthData = authDataMem.Slice(0, sharedMacDataMem.Length + encryptedSize).ToArray();

                    // Split the shared mac from the authentication data
                    byte[] decryptedAuthData = Ecies.Decrypt(LocalPrivateKey, encryptedData, sharedMacDataMem);

                    // Try to parse the decrypted EIP8 authentication data.
                    RLPxAuthEIP8 authEip8Message = new RLPxAuthEIP8(decryptedAuthData);
                    UsingEIP8Authentication = true;

                    // Set the generic authentication data object.
                    authenticationMessage = authEip8Message;

                    // Set the remote version
                    RemoteVersion = authEip8Message.Version;
                }
                catch (Exception authEip8Ex)
                {
                    string exceptionMessage = "Could not deserialize RLPx auth data in either standard or EIP8 format.\r\n";
                    exceptionMessage += $"Standard Auth Error: {authStandardEx.Message}\r\n";
                    exceptionMessage += $"EIP8 Auth Error: {authEip8Ex.Message}";
                    throw new Exception(exceptionMessage);
                }
            }

            // Set the initiator nonce
            InitiatorNonce = authenticationMessage.Nonce;

            // Set the remote public key.
            RemotePublicKey = EthereumEcdsa.Create(authenticationMessage.PublicKey, EthereumEcdsaKeyType.Public);

            // Try to recover the public key (with the "receiver" private key, which in this case is our local private key, since our role is responder).
            // If this fails, it will throw an exception as we expect this method to if any failure occurs.
            (EthereumEcdsa remoteEphermalPublicKey, uint?chainId) = authenticationMessage.RecoverDataFromSignature(LocalPrivateKey);
            RemoteEphermalPublicKey = remoteEphermalPublicKey;

            // TODO: Verify the chain id.

            // Set the session state
            SessionState = RLPxSessionState.AuthenticationCompleted;
        }