Example #1
0
        public void Built_digest_short()
        {
            byte[] bytes = new byte[32];
            new Random(42).NextBytes(bytes);

            string result = Keccak.Compute(bytes).ToString();

            KeccakHash keccakHash = KeccakHash.Create();

            keccakHash.Reset();

            for (int i = 0; i < 1024 / 32; i += 32)
            {
                keccakHash.Update(bytes, i, 32);
            }

            Assert.AreEqual(result, keccakHash.Hash.ToHexString(true));
        }
Example #2
0
        public void DeriveEncryptionParameters()
        {
            // Verify the session state is correct.
            if (SessionState != RLPxSessionState.AcknowledgementCompleted)
            {
                throw new Exception("RLPx encryption parameter deriviation should only occur after authentication and acknowledgement was processed.");
            }

            // Verify we have all required information
            if (AuthData == null || AuthAckData == null || RemoteEphermalPublicKey == null || InitiatorNonce == null || ResponderNonce == null)
            {
                throw new Exception("RLPx deriving encryption information failed: Insufficient data collected from handshake.");
            }

            // Generate the ecdh key with both ephemeral keys
            byte[] ecdhEphemeralKey = LocalEphemeralPrivateKey.ComputeECDHKey(RemoteEphermalPublicKey);

            // Generate a shared secret: Keccak256(ecdhEphemeralKey || Keccak256(ResponderNonce || InitiatorNonce))
            byte[] combinedNonceHash = KeccakHash.ComputeHashBytes(ResponderNonce.Concat(InitiatorNonce));
            byte[] sharedSecret      = KeccakHash.ComputeHashBytes(ecdhEphemeralKey.Concat(combinedNonceHash));

            // Derive the token as a hash of the shared secret.
            Token = KeccakHash.ComputeHashBytes(sharedSecret);

            // Derive AES secret: Keccak256(ecdhEphemeralKey || sharedSecret)
            AesSecret = KeccakHash.ComputeHashBytes(ecdhEphemeralKey.Concat(sharedSecret));

            // Derive Mac secret: Keccak256(ecdhEphemeralKey || AesSecret)
            MacSecret = KeccakHash.ComputeHashBytes(ecdhEphemeralKey.Concat(AesSecret));

            // Create our AES providers for incoming and outgoing traffic/frames.
            // Counter is 0, so it doesn't need to be provided, default value will handle this.
            IngressAes = new AesCtr(AesSecret);
            EgressAes  = new AesCtr(AesSecret);

            // Next we'll want to derive our incoming (ingress) and outgoing (egress) traffic message authentication code ("MAC")
            // The initial state is based off of keccak((MacSecret ^ nonce) || auth/auth-ack). Later states update data from packet frames.

            // We begin by calculating the xor'd nonces
            byte[] initiatorTranformedNonce  = (byte[])InitiatorNonce.Clone();
            byte[] responderTransformedNonce = (byte[])ResponderNonce.Clone();
            int    loopSize = Math.Min(initiatorTranformedNonce.Length, MacSecret.Length);

            for (int i = 0; i < loopSize; i++)
            {
                initiatorTranformedNonce[i]  ^= MacSecret[i];
                responderTransformedNonce[i] ^= MacSecret[i];
            }

            // Next we'll want to hash the data with our hash providers.
            KeccakHash initiatorOutgoing = KeccakHash.Create();

            initiatorOutgoing.Update(responderTransformedNonce, 0, responderTransformedNonce.Length);
            initiatorOutgoing.Update(AuthData, 0, AuthData.Length);
            KeccakHash responderOutgoing = KeccakHash.Create();

            responderOutgoing.Update(initiatorTranformedNonce, 0, initiatorTranformedNonce.Length);
            responderOutgoing.Update(AuthAckData, 0, AuthAckData.Length);

            // Assign the correct hash providers based off of role
            if (Role == RLPxSessionRole.Initiator)
            {
                EgressMac  = initiatorOutgoing;
                IngressMac = responderOutgoing;
            }
            else
            {
                EgressMac  = responderOutgoing;
                IngressMac = initiatorOutgoing;
            }
        }
 public override void Write(Span <byte> bytesToWrite)
 {
     _keccakHash.Update(bytesToWrite, 0, bytesToWrite.Length);
 }
Example #4
0
        public void TestKeccakUpdate()
        {
            // Create our random provider.
            Random random = new Random();

            // Loop for a few test rounds.
            for (int i = 0; i < 5; i++)
            {
                // Generate random data
                byte[]      bufferArray = new byte[random.Next(3, 1024 * 20)];
                Span <byte> buffer      = bufferArray;
                random.NextBytes(buffer);

                // Split threshold
                int splitThreshold = random.Next(33, 1024);

                // Compute the overall hash on the data
                byte[] singleStepHash = KeccakHash.ComputeHashBytes(buffer);

                // Create our keccak hash provider for multi step hash calculation.
                KeccakHash keccak = KeccakHash.Create();
                keccak.Update(bufferArray, 0, buffer.Length);

                // Assert the hashes are equal
                Assert.Equal(singleStepHash.ToHexString(), keccak.Hash.ToHexString());

                // Recompute on the same keccak instance to check if it's reusable.
                keccak.Reset();
                keccak.Update(bufferArray, 0, buffer.Length);
                Assert.Equal(singleStepHash.ToHexString(), keccak.Hash.ToHexString());

                // Recompute the hash but add empty array hashing.
                keccak.Reset();
                keccak.Update(bufferArray, 0, bufferArray.Length);
                keccak.Update(Array.Empty <byte>(), 0, 0);
                keccak.Update(Array.Empty <byte>(), 0, 0);

                // Assert the hashes are equal
                Assert.Equal(singleStepHash.ToHexString(), keccak.Hash.ToHexString());

                // Assert blank hashes
                keccak.Reset();
                keccak.Update(Array.Empty <byte>(), 0, 0);
                keccak.Update(Array.Empty <byte>(), 0, 0);
                byte[] blankHash = KeccakHash.ComputeHashBytes(Array.Empty <byte>());
                Assert.Equal(blankHash.ToHexString(), keccak.Hash.ToHexString());

                // Refresh our new keccak instance
                keccak.Reset();

                while (buffer.Length > 0)
                {
                    // Check if this is the last round
                    bool lastRound = buffer.Length <= splitThreshold;

                    // Obtain the data for this round.
                    byte[] roundData = buffer.Slice(0, lastRound ? buffer.Length : splitThreshold).ToArray();

                    if (lastRound)
                    {
                        // Obtain the final multistep hash.
                        keccak.Update(roundData, 0, roundData.Length);

                        // Assert the hashes are equal
                        Assert.Equal(singleStepHash.ToHexString(), keccak.Hash.ToHexString());

                        // Reset
                        keccak.Reset();
                        break;
                    }
                    else
                    {
                        keccak.Update(roundData, 0, roundData.Length);
                    }

                    // Advance our pointer.
                    buffer = buffer.Slice(roundData.Length);
                }
            }
        }