예제 #1
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);
            }
        }
예제 #2
0
        /// <summary>
        /// Creates authentication data to send to the responder.
        /// </summary>
        /// <param name="receiverPublicKey">The responder/receiver's public key.</param>
        /// <param name="nonce">The nonce to use for the authentication data. If null, new data is generated.</param>
        /// <returns>Returns the encrypted serialized authentication data.</returns>
        public byte[] CreateAuthentiation(EthereumEcdsa receiverPublicKey, byte[] nonce = null)
        {
            // Verify this is the initiator role.
            if (Role != RLPxSessionRole.Initiator)
            {
                throw new Exception("RLPx auth data should only be created by the initiator.");
            }

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

            // If the nonce is null, generate a new one.
            nonce = nonce ?? GenerateNonce();

            // Set our initiator nonce
            InitiatorNonce = nonce;

            // Set the remote public key
            RemotePublicKey = receiverPublicKey;

            // Create a new authentication message based off of our configured setting.
            RLPxAuthBase authMessage = null;

            if (UsingEIP8Authentication)
            {
                // Create our EIP8 authentication message.
                authMessage = new RLPxAuthEIP8()
                {
                    Nonce   = InitiatorNonce,
                    Version = MAX_SUPPORTED_VERSION,
                };
            }
            else
            {
                // Create our standard authentication message.
                authMessage = new RLPxAuthStandard()
                {
                    Nonce = InitiatorNonce,
                };
            }

            // Sign the authentication message
            authMessage.Sign(LocalPrivateKey, LocalEphemeralPrivateKey, RemotePublicKey, ChainId);

            // Serialize the authentication data
            byte[] serializedData = authMessage.Serialize();

            // Encrypt the data accordingly (standard uses no shared mac data, EIP8 has 2 bytes which prefix the resulting encrypted data).
            if (UsingEIP8Authentication)
            {
                // Obtain two bytes of mac data by EIP8 standards (big endian 16-bit unsigned integer equal to the size of the resulting ECIES encrypted data).
                // We can calculate this as the amount of overhead data ECIES adds is static in size.
                byte[] sharedMacData = BigIntegerConverter.GetBytes(serializedData.Length + Ecies.ECIES_ADDITIONAL_OVERHEAD, 2);

                // Encrypt the serialized data with the shared mac data, and prefix the result with it.
                byte[] encryptedSerializedData = Ecies.Encrypt(RemotePublicKey, serializedData, sharedMacData);
                AuthData = sharedMacData.Concat(encryptedSerializedData);
            }
            else
            {
                // Encrypt it using ECIES without any shared mac data.
                AuthData = Ecies.Encrypt(RemotePublicKey, serializedData, null);
            }

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

            // Return the auth data
            return(AuthData);
        }
예제 #3
0
        /// <summary>
        /// Creates authentication acknowledgement data to send to the initiator, signalling that their authentication
        /// data was successfully verified, and providing the initiator with information that they have already provided
        /// to the responder (so they can both derive the same shared secrets).
        /// </summary>
        /// <param name="nonce">The nonce to use for the authentication data. If null, new data is generated.</param>
        /// <returns>Returns the encrypted serialized authentication acknowledgement data.</returns>
        public byte[] CreateAuthenticationAcknowledgement(byte[] nonce = null)
        {
            // Verify this is the responder role.
            if (Role != RLPxSessionRole.Responder)
            {
                throw new Exception("RLPx auth-ack data should only be created by the responder.");
            }

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

            // If the nonce is null, generate a new one.
            if (nonce == null)
            {
                nonce = new byte[NONCE_SIZE];
                _randomNumberGenerator.GetBytes(nonce);
            }

            // Set the responder nonce
            ResponderNonce = nonce ?? GenerateNonce();

            // If we are using EIP8
            RLPxAuthAckBase authAckMessage = null;

            if (UsingEIP8Authentication)
            {
                // We use EIP8 authentication acknowledgement
                authAckMessage = new RLPxAuthAckEIP8()
                {
                    EphemeralPublicKey = LocalEphemeralPrivateKey.ToPublicKeyArray(false, true),
                    Nonce   = ResponderNonce,
                    Version = MAX_SUPPORTED_VERSION,
                };
            }
            else
            {
                // We use standard authentication acknowledgement
                authAckMessage = new RLPxAuthAckStandard()
                {
                    EphemeralPublicKey = LocalEphemeralPrivateKey.ToPublicKeyArray(false, true),
                    Nonce      = ResponderNonce,
                    TokenFound = false, // TODO: Check for a saved session key from before, and set this accordingly.
                };
            }

            // Serialize the authentication-acknowledgement data
            byte[] serializedData = authAckMessage.Serialize();

            // Encrypt the data accordingly (standard uses no shared mac data, EIP8 has 2 bytes which prefix the resulting encrypted data).
            if (UsingEIP8Authentication)
            {
                // Obtain two bytes of mac data by EIP8 standards (big endian 16-bit unsigned integer equal to the size of the resulting ECIES encrypted data).
                // We can calculate this as the amount of overhead data ECIES adds is static in size.
                byte[] sharedMacData = BigIntegerConverter.GetBytes(serializedData.Length + Ecies.ECIES_ADDITIONAL_OVERHEAD, 2);

                // Encrypt the serialized data with the shared mac data, prefix the result with it.
                byte[] encryptedSerializedData = Ecies.Encrypt(RemotePublicKey, serializedData, sharedMacData);
                AuthAckData = sharedMacData.Concat(encryptedSerializedData);
            }
            else
            {
                // Encrypt it using ECIES without any shared mac data.
                AuthAckData = Ecies.Encrypt(RemotePublicKey, serializedData, null);
            }

            // Set the session state
            SessionState = RLPxSessionState.AcknowledgementCompleted;

            // Return the auth-ack data
            return(AuthAckData);
        }
예제 #4
0
        public void TestCases()
        {
            const string message = "attack at dawn";

            var aliceKey = PrivateKey.FromWif("L1Ejc5dAigm5XrM3mNptMEsNnHzS7s51YxU7J61ewGshZTKkbmzJ");
            var bobKey   = PrivateKey.FromWif("KxfxrUXSMjJQcb3JgnaaA6MqsrKQ1nBSxvhuigdKRyFiEm6BZDgG");

            {
                var encrypted = "0339e504d6492b082da96e11e8f039796b06cd4855c101e2492a6f10f3e056a9e712c732611c6917ab5c57a1926973bc44a1586e94a783f81d05ce72518d9b0a80e2e13c7ff7d1306583f9cc7a48def5b37fbf2d5f294f128472a6e9c78dede5f5";
                // encrypted broken down:
                // priv.pubkey 0339e504d6492b082da96e11e8f039796b06cd4855c101e2492a6f10f3e056a9e7
                // ivbuf       12c732611c6917ab5c57a1926973bc44
                // encrypted   a1586e94a783f81d05ce72518d9b0a80
                // sig         e2e13c7ff7d1306583f9cc7a48def5b37fbf2d5f294f128472a6e9c78dede5f5

                var alice = new Ecies {
                    PrivateKey = aliceKey, PublicKey = bobKey.CreatePublicKey()
                };
                var bob = new Ecies {
                    PrivateKey = bobKey
                };

                var ciphertext = alice.Encrypt(message);
                Assert.Equal(encrypted, ciphertext.ToHex());

                var decryptedtext = bob.DecryptToUtf8(ciphertext);
                Assert.Equal(message, decryptedtext);
            }

            {
                var encrypted = "0339e504d6492b082da96e11e8f039796b06cd4855c101e2492a6f10f3e056a9e712c732611c6917ab5c57a1926973bc44a1586e94a783f81d05ce72518d9b0a80e2e13c7f";
                // encrypted broken down:
                // priv.pubkey 0339e504d6492b082da96e11e8f039796b06cd4855c101e2492a6f10f3e056a9e7
                // ivbuf       12c732611c6917ab5c57a1926973bc44
                // encrypted   a1586e94a783f81d05ce72518d9b0a80
                // sig         e2e13c7f

                var alice = new Ecies {
                    PrivateKey = aliceKey, PublicKey = bobKey.CreatePublicKey(), ShortTag = true
                };
                var bob = new Ecies {
                    PrivateKey = bobKey, ShortTag = true
                };

                var ciphertext = alice.Encrypt(message);
                Assert.Equal(encrypted, ciphertext.ToHex());

                var decryptedtext = bob.DecryptToUtf8(ciphertext);
                Assert.Equal(message, decryptedtext);
            }

            {
                var encrypted = "12c732611c6917ab5c57a1926973bc44a1586e94a783f81d05ce72518d9b0a80e2e13c7ff7d1306583f9cc7a48def5b37fbf2d5f294f128472a6e9c78dede5f5";
                // encrypted broken down:
                // priv.pubkey
                // ivbuf       12c732611c6917ab5c57a1926973bc44
                // encrypted   a1586e94a783f81d05ce72518d9b0a80
                // sig         e2e13c7ff7d1306583f9cc7a48def5b37fbf2d5f294f128472a6e9c78dede5f5

                var alice = new Ecies {
                    PrivateKey = aliceKey, PublicKey = bobKey.CreatePublicKey(), NoKey = true
                };
                var bob = new Ecies {
                    PrivateKey = bobKey, PublicKey = aliceKey.CreatePublicKey(), NoKey = true
                };

                var ciphertext = alice.Encrypt(message);
                Assert.Equal(encrypted, ciphertext.ToHex());

                var decryptedtext = bob.DecryptToUtf8(ciphertext);
                Assert.Equal(message, decryptedtext);
            }

            {
                var encrypted = "12c732611c6917ab5c57a1926973bc44a1586e94a783f81d05ce72518d9b0a80e2e13c7f";
                // encrypted broken down:
                // priv.pubkey
                // ivbuf       12c732611c6917ab5c57a1926973bc44
                // encrypted   a1586e94a783f81d05ce72518d9b0a80
                // sig         e2e13c7f

                var alice = new Ecies {
                    PrivateKey = aliceKey, PublicKey = bobKey.CreatePublicKey(), NoKey = true, ShortTag = true
                };
                var bob = new Ecies {
                    PrivateKey = bobKey, PublicKey = aliceKey.CreatePublicKey(), NoKey = true, ShortTag = true
                };

                var ciphertext = alice.Encrypt(message);
                Assert.Equal(encrypted, ciphertext.ToHex());

                var decryptedtext = bob.DecryptToUtf8(ciphertext);
                Assert.Equal(message, decryptedtext);
            }
        }