diff --git a/src/Nethermind/Directory.Packages.props b/src/Nethermind/Directory.Packages.props
index ca7530d8f66..cb88a1ae0d9 100644
--- a/src/Nethermind/Directory.Packages.props
+++ b/src/Nethermind/Directory.Packages.props
@@ -8,6 +8,7 @@
+
@@ -58,7 +59,6 @@
-
@@ -76,4 +76,4 @@
-
\ No newline at end of file
+
diff --git a/src/Nethermind/Nethermind.Crypto/AesEngineX86Intrinsic.cs b/src/Nethermind/Nethermind.Crypto/AesEngineX86Intrinsic.cs
deleted file mode 100644
index 1f5751eaf3e..00000000000
--- a/src/Nethermind/Nethermind.Crypto/AesEngineX86Intrinsic.cs
+++ /dev/null
@@ -1,425 +0,0 @@
-// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited
-// SPDX-License-Identifier: LGPL-3.0-only
-// Modified from BouncyCastle MIT
-
-#pragma warning disable CA1857 // A constant is expected for the parameter
-
-using System;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Runtime.Intrinsics;
-
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Parameters;
-
-using Aes = System.Runtime.Intrinsics.X86.Aes;
-using Sse2 = System.Runtime.Intrinsics.X86.Sse2;
-
-namespace Nethermind.Crypto;
-
-public sealed class AesEngineX86Intrinsic : IBlockCipher
-{
- public static bool IsSupported => Aes.IsSupported;
- public bool IsPartialBlockOkay => false;
- public void Reset() { }
-
- public AesEngineX86Intrinsic()
- {
- if (!IsSupported)
- throw new PlatformNotSupportedException(nameof(AesEngineX86Intrinsic));
- }
-
- public string AlgorithmName => "AES";
-
- public int GetBlockSize() => 16;
-
- private AesEncoderDecoder _implementation;
-
- public void Init(bool forEncryption, ICipherParameters parameters)
- {
- if (parameters is not KeyParameter keyParameter)
- {
- ArgumentNullException.ThrowIfNull(parameters, nameof(parameters));
- throw new ArgumentException("invalid type: " + parameters.GetType(), nameof(parameters));
- }
-
- Vector128[] roundKeys = CreateRoundKeys(keyParameter.GetKey(), forEncryption);
- _implementation = AesEncoderDecoder.Init(forEncryption, roundKeys);
- }
-
- public int ProcessBlock(byte[] inBuf, int inOff, byte[] outBuf, int outOff)
- {
- Check.DataLength(inBuf, inOff, 16);
- Check.OutputLength(outBuf, outOff, 16);
-
- Vector128 state = Unsafe.As>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(inBuf), inOff));
-
- _implementation.ProcessRounds(ref state);
-
- Unsafe.As>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(outBuf), outOff)) = state;
-
- return 16;
- }
-
- private static Vector128[] CreateRoundKeys(byte[] key, bool forEncryption)
- {
- Vector128[] K = key.Length switch
- {
- 16 => KeyLength16(key),
- 24 => KeyLength24(key),
- 32 => KeyLength32(key),
- _ => throw new ArgumentException("Key length not 128/192/256 bits.")
- };
-
- if (!forEncryption)
- {
- for (int i = 1, last = K.Length - 1; i < last; ++i)
- {
- K[i] = Aes.InverseMixColumns(K[i]);
- }
-
- Array.Reverse(K);
- }
-
- return K;
-
- [SkipLocalsInit]
- static Vector128[] KeyLength16(byte[] key)
- {
- ReadOnlySpan rcon = stackalloc byte[] { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
-
- Vector128 s = MemoryMarshal.Read>(key.AsSpan(0, 16));
- Vector128[] K = new Vector128[11];
- K[0] = s;
-
- for (int round = 0; round < 10;)
- {
- Vector128 t = Aes.KeygenAssist(s, rcon[round++]);
- t = Sse2.Shuffle(t.AsInt32(), 0xFF).AsByte();
- s = Sse2.Xor(s, Sse2.ShiftLeftLogical128BitLane(s, 8));
- s = Sse2.Xor(s, Sse2.ShiftLeftLogical128BitLane(s, 4));
- s = Sse2.Xor(s, t);
- K[round] = s;
- }
-
- return K;
- }
-
- static Vector128[] KeyLength24(byte[] key)
- {
- Vector128 s1 = MemoryMarshal.Read>(key.AsSpan(0, 16));
- Vector128 s2 = MemoryMarshal.Read>(key.AsSpan(16, 8)).ToVector128();
- Vector128[] K = new Vector128[13];
- K[0] = s1;
-
- byte rcon = 0x01;
- for (int round = 0; ;)
- {
- Vector128 t1 = Aes.KeygenAssist(s2, rcon); rcon <<= 1;
- t1 = Sse2.Shuffle(t1.AsInt32(), 0x55).AsByte();
-
- s1 = Sse2.Xor(s1, Sse2.ShiftLeftLogical128BitLane(s1, 8));
- s1 = Sse2.Xor(s1, Sse2.ShiftLeftLogical128BitLane(s1, 4));
- s1 = Sse2.Xor(s1, t1);
-
- K[++round] = Sse2.Xor(s2, Sse2.ShiftLeftLogical128BitLane(s1, 8));
-
- Vector128 s3 = Sse2.Xor(s2, Sse2.ShiftRightLogical128BitLane(s1, 12));
- s3 = Sse2.Xor(s3, Sse2.ShiftLeftLogical128BitLane(s3, 4));
-
- K[++round] = Sse2.Xor(
- Sse2.ShiftRightLogical128BitLane(s1, 8),
- Sse2.ShiftLeftLogical128BitLane(s3, 8));
-
- Vector128 t2 = Aes.KeygenAssist(s3, rcon); rcon <<= 1;
- t2 = Sse2.Shuffle(t2.AsInt32(), 0x55).AsByte();
-
- s1 = Sse2.Xor(s1, Sse2.ShiftLeftLogical128BitLane(s1, 8));
- s1 = Sse2.Xor(s1, Sse2.ShiftLeftLogical128BitLane(s1, 4));
- s1 = Sse2.Xor(s1, t2);
-
- K[++round] = s1;
-
- if (round == 12)
- break;
-
- s2 = Sse2.Xor(s3, Sse2.ShiftRightLogical128BitLane(s1, 12));
- s2 = Sse2.Xor(s2, Sse2.ShiftLeftLogical128BitLane(s2, 4));
- s2 = s2.WithUpper(Vector64.Zero);
- }
-
- return K;
- }
-
- static Vector128[] KeyLength32(byte[] key)
- {
- Vector128 s1 = MemoryMarshal.Read>(key.AsSpan(0, 16));
- Vector128 s2 = MemoryMarshal.Read>(key.AsSpan(16, 16));
- Vector128[] K = new Vector128[15];
- K[0] = s1;
- K[1] = s2;
-
- byte rcon = 0x01;
- for (int round = 1; ;)
- {
- Vector128 t1 = Aes.KeygenAssist(s2, rcon); rcon <<= 1;
- t1 = Sse2.Shuffle(t1.AsInt32(), 0xFF).AsByte();
- s1 = Sse2.Xor(s1, Sse2.ShiftLeftLogical128BitLane(s1, 8));
- s1 = Sse2.Xor(s1, Sse2.ShiftLeftLogical128BitLane(s1, 4));
- s1 = Sse2.Xor(s1, t1);
- K[++round] = s1;
-
- if (round == 14)
- break;
-
- Vector128 t2 = Aes.KeygenAssist(s1, 0x00);
- t2 = Sse2.Shuffle(t2.AsInt32(), 0xAA).AsByte();
- s2 = Sse2.Xor(s2, Sse2.ShiftLeftLogical128BitLane(s2, 8));
- s2 = Sse2.Xor(s2, Sse2.ShiftLeftLogical128BitLane(s2, 4));
- s2 = Sse2.Xor(s2, t2);
- K[++round] = s2;
- }
-
- return K;
- }
- }
-
- private abstract class AesEncoderDecoder
- {
- protected readonly Vector128[] _roundKeys;
-
- public AesEncoderDecoder(Vector128[] roundKeys)
- {
- _roundKeys = roundKeys;
- }
-
- public static AesEncoderDecoder Init(bool forEncryption, Vector128[] roundKeys)
- {
- if (roundKeys.Length == 11)
- {
- return forEncryption ? new Encode128(roundKeys) : new Decode128(roundKeys);
- }
- else if (roundKeys.Length == 13)
- {
- return forEncryption ? new Encode192(roundKeys) : new Decode192(roundKeys);
- }
- else
- {
- return forEncryption ? new Encode256(roundKeys) : new Decode256(roundKeys);
- }
- }
-
- public abstract void ProcessRounds(ref Vector128 state);
-
- private sealed class Encode128 : AesEncoderDecoder
- {
- public Encode128(Vector128[] roundKeys) : base(roundKeys) { }
-
- public override void ProcessRounds(ref Vector128 state)
- {
- // Take local reference to array so Jit can reason length doesn't change in method
- Vector128[] roundKeys = _roundKeys;
- {
- // Get the Jit to bounds check once rather than each increasing array access
- Vector128 temp = roundKeys[10];
- }
-
- // Operate on non-ref local so it remains in register rather than operating on memory
- Vector128 state2 = Sse2.Xor(state, roundKeys[0]);
- state2 = Aes.Encrypt(state2, roundKeys[1]);
- state2 = Aes.Encrypt(state2, roundKeys[2]);
- state2 = Aes.Encrypt(state2, roundKeys[3]);
- state2 = Aes.Encrypt(state2, roundKeys[4]);
- state2 = Aes.Encrypt(state2, roundKeys[5]);
- state2 = Aes.Encrypt(state2, roundKeys[6]);
- state2 = Aes.Encrypt(state2, roundKeys[7]);
- state2 = Aes.Encrypt(state2, roundKeys[8]);
- state2 = Aes.Encrypt(state2, roundKeys[9]);
- state2 = Aes.EncryptLast(state2, roundKeys[10]);
- // Copy back to ref
- state = state2;
- }
- }
-
- private sealed class Decode128 : AesEncoderDecoder
- {
- public Decode128(Vector128[] roundKeys) : base(roundKeys) { }
-
- public override void ProcessRounds(ref Vector128 state)
- {
- // Take local reference to array so Jit can reason length doesn't change in method
- Vector128[] roundKeys = _roundKeys;
- {
- // Get the Jit to bounds check once rather than each increasing array access
- Vector128 temp = roundKeys[10];
- }
-
- // Operate on non-ref local so it remains in register rather than operating on memory
- Vector128 state2 = Sse2.Xor(state, roundKeys[0]);
- state2 = Aes.Decrypt(state2, roundKeys[1]);
- state2 = Aes.Decrypt(state2, roundKeys[2]);
- state2 = Aes.Decrypt(state2, roundKeys[3]);
- state2 = Aes.Decrypt(state2, roundKeys[4]);
- state2 = Aes.Decrypt(state2, roundKeys[5]);
- state2 = Aes.Decrypt(state2, roundKeys[6]);
- state2 = Aes.Decrypt(state2, roundKeys[7]);
- state2 = Aes.Decrypt(state2, roundKeys[8]);
- state2 = Aes.Decrypt(state2, roundKeys[9]);
- state2 = Aes.DecryptLast(state2, roundKeys[10]);
- // Copy back to ref
- state = state2;
- }
- }
-
- private sealed class Encode192 : AesEncoderDecoder
- {
- public Encode192(Vector128[] roundKeys) : base(roundKeys) { }
-
- public override void ProcessRounds(ref Vector128 state)
- {
- // Take local reference to array so Jit can reason length doesn't change in method
- Vector128[] roundKeys = _roundKeys;
- {
- // Get the Jit to bounds check once rather than each increasing array access
- Vector128 temp = roundKeys[12];
- }
-
- // Operate on non-ref local so it remains in register rather than operating on memory
- Vector128 state2 = Sse2.Xor(state, roundKeys[0]);
- state2 = Aes.Encrypt(state2, roundKeys[1]);
- state2 = Aes.Encrypt(state2, roundKeys[2]);
- state2 = Aes.Encrypt(state2, roundKeys[3]);
- state2 = Aes.Encrypt(state2, roundKeys[4]);
- state2 = Aes.Encrypt(state2, roundKeys[5]);
- state2 = Aes.Encrypt(state2, roundKeys[6]);
- state2 = Aes.Encrypt(state2, roundKeys[7]);
- state2 = Aes.Encrypt(state2, roundKeys[8]);
- state2 = Aes.Encrypt(state2, roundKeys[9]);
- state2 = Aes.Encrypt(state2, roundKeys[10]);
- state2 = Aes.Encrypt(state2, roundKeys[11]);
- state2 = Aes.EncryptLast(state2, roundKeys[12]);
- // Copy back to ref
- state = state2;
- }
- }
-
- private sealed class Decode192 : AesEncoderDecoder
- {
- public Decode192(Vector128[] roundKeys) : base(roundKeys) { }
-
- public override void ProcessRounds(ref Vector128 state)
- {
- // Take local reference to array so Jit can reason length doesn't change in method
- Vector128[] roundKeys = _roundKeys;
- {
- // Get the Jit to bounds check once rather than each increasing array access
- Vector128 temp = roundKeys[12];
- }
-
- // Operate on non-ref local so it remains in register rather than operating on memory
- Vector128 state2 = Sse2.Xor(state, roundKeys[0]);
- state2 = Aes.Decrypt(state2, roundKeys[1]);
- state2 = Aes.Decrypt(state2, roundKeys[2]);
- state2 = Aes.Decrypt(state2, roundKeys[3]);
- state2 = Aes.Decrypt(state2, roundKeys[4]);
- state2 = Aes.Decrypt(state2, roundKeys[5]);
- state2 = Aes.Decrypt(state2, roundKeys[6]);
- state2 = Aes.Decrypt(state2, roundKeys[7]);
- state2 = Aes.Decrypt(state2, roundKeys[8]);
- state2 = Aes.Decrypt(state2, roundKeys[9]);
- state2 = Aes.Decrypt(state2, roundKeys[10]);
- state2 = Aes.Decrypt(state2, roundKeys[11]);
- state2 = Aes.DecryptLast(state2, roundKeys[12]);
- // Copy back to ref
- state = state2;
- }
- }
-
- private sealed class Encode256 : AesEncoderDecoder
- {
- public Encode256(Vector128[] roundKeys) : base(roundKeys) { }
-
- public override void ProcessRounds(ref Vector128 state)
- {
- // Take local reference to array so Jit can reason length doesn't change in method
- Vector128[] roundKeys = _roundKeys;
- {
- // Get the Jit to bounds check once rather than each increasing array access
- Vector128 temp = roundKeys[14];
- }
-
- // Operate on non-ref local so it remains in register rather than operating on memory
- Vector128 state2 = Sse2.Xor(state, roundKeys[0]);
- state2 = Aes.Encrypt(state2, roundKeys[1]);
- state2 = Aes.Encrypt(state2, roundKeys[2]);
- state2 = Aes.Encrypt(state2, roundKeys[3]);
- state2 = Aes.Encrypt(state2, roundKeys[4]);
- state2 = Aes.Encrypt(state2, roundKeys[5]);
- state2 = Aes.Encrypt(state2, roundKeys[6]);
- state2 = Aes.Encrypt(state2, roundKeys[7]);
- state2 = Aes.Encrypt(state2, roundKeys[8]);
- state2 = Aes.Encrypt(state2, roundKeys[9]);
- state2 = Aes.Encrypt(state2, roundKeys[10]);
- state2 = Aes.Encrypt(state2, roundKeys[11]);
- state2 = Aes.Encrypt(state2, roundKeys[12]);
- state2 = Aes.Encrypt(state2, roundKeys[13]);
- state2 = Aes.EncryptLast(state2, roundKeys[14]);
- // Copy back to ref
- state = state2;
- }
- }
-
- private sealed class Decode256 : AesEncoderDecoder
- {
- public Decode256(Vector128[] roundKeys) : base(roundKeys) { }
-
- public override void ProcessRounds(ref Vector128 state)
- {
- // Take local reference to array so Jit can reason length doesn't change in method
- Vector128[] roundKeys = _roundKeys;
- {
- // Get the Jit to bounds check once rather than each increasing array access
- Vector128 temp = roundKeys[14];
- }
-
- // Operate on non-ref local so it remains in register rather than operating on memory
- Vector128 state2 = Sse2.Xor(state, roundKeys[0]);
- state2 = Aes.Decrypt(state2, roundKeys[1]);
- state2 = Aes.Decrypt(state2, roundKeys[2]);
- state2 = Aes.Decrypt(state2, roundKeys[3]);
- state2 = Aes.Decrypt(state2, roundKeys[4]);
- state2 = Aes.Decrypt(state2, roundKeys[5]);
- state2 = Aes.Decrypt(state2, roundKeys[6]);
- state2 = Aes.Decrypt(state2, roundKeys[7]);
- state2 = Aes.Decrypt(state2, roundKeys[8]);
- state2 = Aes.Decrypt(state2, roundKeys[9]);
- state2 = Aes.Decrypt(state2, roundKeys[10]);
- state2 = Aes.Decrypt(state2, roundKeys[11]);
- state2 = Aes.Decrypt(state2, roundKeys[12]);
- state2 = Aes.Decrypt(state2, roundKeys[13]);
- state2 = Aes.DecryptLast(state2, roundKeys[14]);
- // Copy back to ref
- state = state2;
- }
- }
- }
-
- private static class Check
- {
- public static void DataLength(byte[] buf, int off, int len)
- {
- if (off > (buf.Length - len)) ThrowDataLengthException();
-
- static void ThrowDataLengthException() => throw new DataLengthException("input buffer too short");
- }
-
- public static void OutputLength(byte[] buf, int off, int len)
- {
- if (off > (buf.Length - len)) ThrowOutputLengthException();
-
- static void ThrowOutputLengthException() => throw new OutputLengthException("output buffer too short");
- }
- }
-}
-
-#pragma warning restore CA1857 // A constant is expected for the parameter
diff --git a/src/Nethermind/Nethermind.Crypto/EciesCipher.cs b/src/Nethermind/Nethermind.Crypto/EciesCipher.cs
index 078ccd9666b..7e9f1d89409 100644
--- a/src/Nethermind/Nethermind.Crypto/EciesCipher.cs
+++ b/src/Nethermind/Nethermind.Crypto/EciesCipher.cs
@@ -6,91 +6,89 @@
using Nethermind.Core.Extensions;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
-using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Macs;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
-namespace Nethermind.Crypto
+namespace Nethermind.Crypto;
+
+///
+/// Code adapted from ethereumJ (https://github.com/ethereum/ethereumj)
+///
+public class EciesCipher : IEciesCipher
{
- ///
- /// Code adapted from ethereumJ (https://github.com/ethereum/ethereumj)
- ///
- public class EciesCipher : IEciesCipher
- {
- private const int KeySize = 128;
- private readonly ICryptoRandom _cryptoRandom;
- private readonly PrivateKeyGenerator _keyGenerator;
+ private const int KeySize = 128;
+ private readonly ICryptoRandom _cryptoRandom;
+ private readonly PrivateKeyGenerator _keyGenerator;
- public EciesCipher(ICryptoRandom cryptoRandom)
- {
- _cryptoRandom = cryptoRandom;
- _keyGenerator = new PrivateKeyGenerator(cryptoRandom);
- }
+ public EciesCipher(ICryptoRandom cryptoRandom)
+ {
+ _cryptoRandom = cryptoRandom;
+ _keyGenerator = new PrivateKeyGenerator(cryptoRandom);
+ }
- private static readonly int ephemBytesLength = 2 * ((BouncyCrypto.DomainParameters.Curve.FieldSize + 7) / 8) + 1;
+ private static readonly int ephemBytesLength = 2 * ((BouncyCrypto.DomainParameters.Curve.FieldSize + 7) / 8) + 1;
- public (bool, byte[]) Decrypt(PrivateKey privateKey, byte[] cipherText, byte[]? macData = null)
+ public (bool, byte[]) Decrypt(PrivateKey privateKey, byte[] cipherText, byte[]? macData = null)
+ {
+ if (cipherText[0] != 4) // if not a compressed public key then probably we need to use EIP8
{
- if (cipherText[0] != 4) // if not a compressed public key then probably we need to use EIP8
- {
- return (false, null);
- }
+ return (false, null);
+ }
- Span ephemBytes = cipherText.AsSpan(0, ephemBytesLength);
- byte[] iv = cipherText.Slice(ephemBytesLength, KeySize / 8);
- byte[] cipherBody = cipherText.Slice(ephemBytesLength + KeySize / 8);
+ Span ephemBytes = cipherText.AsSpan(0, ephemBytesLength);
+ byte[] iv = cipherText.Slice(ephemBytesLength, KeySize / 8);
+ byte[] cipherBody = cipherText.Slice(ephemBytesLength + KeySize / 8);
- byte[] plaintext = Decrypt(new PublicKey(ephemBytes), privateKey, iv, cipherBody, macData);
- return (true, plaintext);
- }
+ byte[] plaintext = Decrypt(new PublicKey(ephemBytes), privateKey, iv, cipherBody, macData);
+ return (true, plaintext);
+ }
- public byte[] Encrypt(PublicKey recipientPublicKey, byte[] plainText, byte[] macData)
- {
- byte[] iv = _cryptoRandom.GenerateRandomBytes(KeySize / 8);
- PrivateKey ephemeralPrivateKey = _keyGenerator.Generate();
- IIesEngine iesEngine = MakeIesEngine(true, recipientPublicKey, ephemeralPrivateKey, iv);
- byte[] cipher = iesEngine.ProcessBlock(plainText, 0, plainText.Length, macData);
+ public byte[] Encrypt(PublicKey recipientPublicKey, byte[] plainText, byte[] macData)
+ {
+ byte[] iv = _cryptoRandom.GenerateRandomBytes(KeySize / 8);
+ PrivateKey ephemeralPrivateKey = _keyGenerator.Generate();
+ IIesEngine iesEngine = MakeIesEngine(true, recipientPublicKey, ephemeralPrivateKey, iv);
+ byte[] cipher = iesEngine.ProcessBlock(plainText, 0, plainText.Length, macData);
- byte[] prefixedBytes = ephemeralPrivateKey.PublicKey.PrefixedBytes;
+ byte[] prefixedBytes = ephemeralPrivateKey.PublicKey.PrefixedBytes;
- byte[] outputArray = new byte[prefixedBytes.Length + iv.Length + cipher.Length];
- Span outputSpan = outputArray;
+ byte[] outputArray = new byte[prefixedBytes.Length + iv.Length + cipher.Length];
+ Span outputSpan = outputArray;
- prefixedBytes.AsSpan().CopyTo(outputSpan);
- outputSpan = outputSpan[prefixedBytes.Length..];
+ prefixedBytes.AsSpan().CopyTo(outputSpan);
+ outputSpan = outputSpan[prefixedBytes.Length..];
- iv.AsSpan().CopyTo(outputSpan);
- outputSpan = outputSpan[iv.Length..];
+ iv.AsSpan().CopyTo(outputSpan);
+ outputSpan = outputSpan[iv.Length..];
- cipher.AsSpan().CopyTo(outputSpan);
+ cipher.AsSpan().CopyTo(outputSpan);
- return outputArray;
- }
+ return outputArray;
+ }
- private readonly OptimizedKdf _optimizedKdf = new();
+ private readonly OptimizedKdf _optimizedKdf = new();
- private static byte[] Decrypt(PublicKey ephemeralPublicKey, PrivateKey privateKey, byte[] iv, byte[] ciphertextBody, byte[] macData)
- {
- IIesEngine iesEngine = MakeIesEngine(false, ephemeralPublicKey, privateKey, iv);
- return iesEngine.ProcessBlock(ciphertextBody, 0, ciphertextBody.Length, macData);
- }
+ private static byte[] Decrypt(PublicKey ephemeralPublicKey, PrivateKey privateKey, byte[] iv, byte[] ciphertextBody, byte[] macData)
+ {
+ IIesEngine iesEngine = MakeIesEngine(false, ephemeralPublicKey, privateKey, iv);
+ return iesEngine.ProcessBlock(ciphertextBody, 0, ciphertextBody.Length, macData);
+ }
- private static readonly IesParameters _iesParameters = new IesWithCipherParameters(Array.Empty(), Array.Empty(), KeySize, KeySize);
+ private static readonly IesParameters _iesParameters = new IesWithCipherParameters(Array.Empty(), Array.Empty(), KeySize, KeySize);
- private static IIesEngine MakeIesEngine(bool isEncrypt, PublicKey publicKey, PrivateKey privateKey, byte[] iv)
- {
- IBlockCipher aesFastEngine = AesEngineX86Intrinsic.IsSupported ? new AesEngineX86Intrinsic() : new AesEngine();
+ private static IIesEngine MakeIesEngine(bool isEncrypt, PublicKey publicKey, PrivateKey privateKey, byte[] iv)
+ {
+ IBlockCipher aesFastEngine = AesUtilities.CreateEngine();
- EthereumIesEngine iesEngine = new(
- new HMac(new Sha256Digest()),
- new Sha256Digest(),
- new BufferedBlockCipher(new SicBlockCipher(aesFastEngine)));
+ EthereumIesEngine iesEngine = new(
+ new HMac(new Sha256Digest()),
+ new Sha256Digest(),
+ new BufferedBlockCipher(new SicBlockCipher(aesFastEngine)));
- ParametersWithIV parametersWithIV = new(_iesParameters, iv);
- byte[] secret = SecP256k1.EcdhSerialized(publicKey.Bytes, privateKey.KeyBytes);
- iesEngine.Init(isEncrypt, OptimizedKdf.Derive(secret), parametersWithIV);
- return iesEngine;
- }
+ ParametersWithIV parametersWithIV = new(_iesParameters, iv);
+ byte[] secret = SecP256k1.EcdhSerialized(publicKey.Bytes, privateKey.KeyBytes);
+ iesEngine.Init(isEncrypt, OptimizedKdf.Derive(secret), parametersWithIV);
+ return iesEngine;
}
}
diff --git a/src/Nethermind/Nethermind.Crypto/EthereumIesEngine.cs b/src/Nethermind/Nethermind.Crypto/EthereumIesEngine.cs
index 5520deab0fc..d50a2631c97 100644
--- a/src/Nethermind/Nethermind.Crypto/EthereumIesEngine.cs
+++ b/src/Nethermind/Nethermind.Crypto/EthereumIesEngine.cs
@@ -158,7 +158,7 @@ private byte[] DecryptBlock(byte[] inEnc, int inOff, int inLen, byte[]? macData)
_mac.DoFinal(t2, 0);
- if (!Arrays.ConstantTimeAreEqual(t1, t2))
+ if (!Arrays.FixedTimeEquals(t1, t2))
{
throw new InvalidCipherTextException("Invalid MAC.");
}
diff --git a/src/Nethermind/Nethermind.Crypto/Nethermind.Crypto.csproj b/src/Nethermind/Nethermind.Crypto/Nethermind.Crypto.csproj
index 0c5702026d5..cbd9d76af1a 100644
--- a/src/Nethermind/Nethermind.Crypto/Nethermind.Crypto.csproj
+++ b/src/Nethermind/Nethermind.Crypto/Nethermind.Crypto.csproj
@@ -11,10 +11,10 @@
+
-
diff --git a/src/Nethermind/Nethermind.Network/Rlpx/FrameCipher.cs b/src/Nethermind/Nethermind.Network/Rlpx/FrameCipher.cs
index 7d5822f8d75..10cb64da1a9 100644
--- a/src/Nethermind/Nethermind.Network/Rlpx/FrameCipher.cs
+++ b/src/Nethermind/Nethermind.Network/Rlpx/FrameCipher.cs
@@ -2,46 +2,41 @@
// SPDX-License-Identifier: LGPL-3.0-only
using System.Diagnostics;
-
-using Nethermind.Crypto;
-
using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
-namespace Nethermind.Network.Rlpx
+namespace Nethermind.Network.Rlpx;
+
+public class FrameCipher : IFrameCipher
{
- public class FrameCipher : IFrameCipher
- {
- private const int BlockSize = 16;
- private const int KeySize = 32;
+ private const int BlockSize = 16;
+ private const int KeySize = 32;
- private readonly IBufferedCipher _decryptionCipher;
- private readonly IBufferedCipher _encryptionCipher;
+ private readonly IBufferedCipher _decryptionCipher;
+ private readonly IBufferedCipher _encryptionCipher;
- public FrameCipher(byte[] aesKey)
- {
- IBlockCipher aes = AesEngineX86Intrinsic.IsSupported ? new AesEngineX86Intrinsic() : new AesEngine();
+ public FrameCipher(byte[] aesKey)
+ {
+ IBlockCipher aes = AesUtilities.CreateEngine();
- Debug.Assert(aesKey.Length == KeySize, $"AES key expected to be {KeySize} bytes long");
+ Debug.Assert(aesKey.Length == KeySize, $"AES key expected to be {KeySize} bytes long");
- _encryptionCipher = new BufferedBlockCipher(new SicBlockCipher(aes));
- _encryptionCipher.Init(true, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", aesKey), new byte[BlockSize]));
+ _encryptionCipher = new BufferedBlockCipher(new SicBlockCipher(aes));
+ _encryptionCipher.Init(true, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", aesKey), new byte[BlockSize]));
- _decryptionCipher = new BufferedBlockCipher(new SicBlockCipher(aes));
- _decryptionCipher.Init(false, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", aesKey), new byte[BlockSize]));
- }
+ _decryptionCipher = new BufferedBlockCipher(new SicBlockCipher(aes));
+ _decryptionCipher.Init(false, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", aesKey), new byte[BlockSize]));
+ }
- public void Encrypt(byte[] input, int offset, int length, byte[] output, int outputOffset)
- {
- _encryptionCipher.ProcessBytes(input, offset, length, output, outputOffset);
- }
+ public void Encrypt(byte[] input, int offset, int length, byte[] output, int outputOffset)
+ {
+ _encryptionCipher.ProcessBytes(input, offset, length, output, outputOffset);
+ }
- public void Decrypt(byte[] input, int offset, int length, byte[] output, int outputOffset)
- {
- _decryptionCipher.ProcessBytes(input, offset, length, output, outputOffset);
- }
+ public void Decrypt(byte[] input, int offset, int length, byte[] output, int outputOffset)
+ {
+ _decryptionCipher.ProcessBytes(input, offset, length, output, outputOffset);
}
}
diff --git a/src/Nethermind/Nethermind.Network/Rlpx/FrameMacProcessor.cs b/src/Nethermind/Nethermind.Network/Rlpx/FrameMacProcessor.cs
index 990637126e2..f4d9ef42f57 100644
--- a/src/Nethermind/Nethermind.Network/Rlpx/FrameMacProcessor.cs
+++ b/src/Nethermind/Nethermind.Network/Rlpx/FrameMacProcessor.cs
@@ -4,219 +4,215 @@
using System;
using System.IO;
using Nethermind.Core.Crypto;
-using Nethermind.Crypto;
-
using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
-namespace Nethermind.Network.Rlpx
+namespace Nethermind.Network.Rlpx;
+
+///
+/// partially adapted from ethereumJ
+///
+public sealed class FrameMacProcessor : IFrameMacProcessor
{
- ///
- /// partially adapted from ethereumJ
- ///
- public sealed class FrameMacProcessor : IFrameMacProcessor
+ private readonly PublicKey _remoteNodeId;
+ private readonly KeccakHash _egressMac;
+ private readonly KeccakHash _ingressMac;
+ private readonly KeccakHash _egressMacCopy;
+ private readonly KeccakHash _ingressMacCopy;
+ private readonly IBlockCipher _aesEngine;
+ private readonly byte[] _macSecret;
+
+ public FrameMacProcessor(PublicKey remoteNodeId, EncryptionSecrets secrets)
{
- private readonly PublicKey _remoteNodeId;
- private readonly KeccakHash _egressMac;
- private readonly KeccakHash _ingressMac;
- private readonly KeccakHash _egressMacCopy;
- private readonly KeccakHash _ingressMacCopy;
- private readonly IBlockCipher _aesEngine;
- private readonly byte[] _macSecret;
-
- public FrameMacProcessor(PublicKey remoteNodeId, EncryptionSecrets secrets)
- {
- _remoteNodeId = remoteNodeId;
- _macSecret = secrets.MacSecret;
- _egressMac = secrets.EgressMac;
- _egressMacCopy = _egressMac.Copy();
- _ingressMac = secrets.IngressMac;
- _ingressMacCopy = _ingressMac.Copy();
- _aesEngine = MakeMacCipher();
- _checkMacBuffer = new byte[_ingressMac.HashSize];
- _addMacBuffer = new byte[_ingressMac.HashSize];
- _ingressAesBlockBuffer = new byte[_ingressMac.HashSize];
- _egressAesBlockBuffer = new byte[_ingressMac.HashSize];
- }
+ _remoteNodeId = remoteNodeId;
+ _macSecret = secrets.MacSecret;
+ _egressMac = secrets.EgressMac;
+ _egressMacCopy = _egressMac.Copy();
+ _ingressMac = secrets.IngressMac;
+ _ingressMacCopy = _ingressMac.Copy();
+ _aesEngine = MakeMacCipher();
+ _checkMacBuffer = new byte[_ingressMac.HashSize];
+ _addMacBuffer = new byte[_ingressMac.HashSize];
+ _ingressAesBlockBuffer = new byte[_ingressMac.HashSize];
+ _egressAesBlockBuffer = new byte[_ingressMac.HashSize];
+ }
- private IBlockCipher MakeMacCipher()
+ private IBlockCipher MakeMacCipher()
+ {
+ IBlockCipher aesFastEngine = AesUtilities.CreateEngine();
+ aesFastEngine.Init(true, new KeyParameter(_macSecret));
+ return aesFastEngine;
+ }
+
+ public void AddMac(byte[] input, int offset, int length, bool isHeader)
+ {
+ if (isHeader)
{
- IBlockCipher aesFastEngine = AesEngineX86Intrinsic.IsSupported ? new AesEngineX86Intrinsic() : new AesEngine();
- aesFastEngine.Init(true, new KeyParameter(_macSecret));
- return aesFastEngine;
+ input.AsSpan(0, 32).CopyTo(_addMacBuffer);
+ UpdateMac(_egressMac, _egressMacCopy, _addMacBuffer, offset, input, offset + length, true); // TODO: confirm header is seed
}
-
- public void AddMac(byte[] input, int offset, int length, bool isHeader)
+ else
{
- if (isHeader)
- {
- input.AsSpan(0, 32).CopyTo(_addMacBuffer);
- UpdateMac(_egressMac, _egressMacCopy, _addMacBuffer, offset, input, offset + length, true); // TODO: confirm header is seed
- }
- else
- {
- _egressMac.Update(input.AsSpan(offset, length));
+ _egressMac.Update(input.AsSpan(offset, length));
- // frame-mac: right128 of egress-mac.update(aes(mac-secret,egress-mac) ^ right128(egress-mac.update(frame-ciphertext).digest))
- DoFinalNoReset(_egressMac, _egressMacCopy, _addMacBuffer); // frame MAC seed
- UpdateMac(_egressMac, _egressMacCopy, _addMacBuffer, 0, input, offset + length, true);
- }
+ // frame-mac: right128 of egress-mac.update(aes(mac-secret,egress-mac) ^ right128(egress-mac.update(frame-ciphertext).digest))
+ DoFinalNoReset(_egressMac, _egressMacCopy, _addMacBuffer); // frame MAC seed
+ UpdateMac(_egressMac, _egressMacCopy, _addMacBuffer, 0, input, offset + length, true);
}
+ }
+
+ public void UpdateEgressMac(byte[] input)
+ {
+ _egressMac.Update(input);
+ }
- public void UpdateEgressMac(byte[] input)
+ public void UpdateIngressMac(byte[] input, bool isHeader)
+ {
+ if (isHeader)
{
- _egressMac.Update(input);
+ input.AsSpan().CopyTo(_checkMacBuffer.AsSpan(0, 16));
}
-
- public void UpdateIngressMac(byte[] input, bool isHeader)
+ else
{
- if (isHeader)
- {
- input.AsSpan().CopyTo(_checkMacBuffer.AsSpan(0, 16));
- }
- else
- {
- _ingressMac.Update(input);
- }
+ _ingressMac.Update(input);
}
+ }
+
+ public void CalculateMac(byte[] output)
+ {
+ DoFinalNoReset(_egressMac, _egressMacCopy, _addMacBuffer); // frame MAC seed
+ UpdateMac(_egressMac, _egressMacCopy, _addMacBuffer, 0, output, 0, true);
+ }
- public void CalculateMac(byte[] output)
+ public void AddMac(byte[] input, int offset, int length, byte[] output, int outputOffset, bool isHeader)
+ {
+ if (isHeader)
{
- DoFinalNoReset(_egressMac, _egressMacCopy, _addMacBuffer); // frame MAC seed
- UpdateMac(_egressMac, _egressMacCopy, _addMacBuffer, 0, output, 0, true);
+ input.AsSpan(0, 16).CopyTo(_addMacBuffer);
+ UpdateMac(_egressMac, _egressMacCopy, _addMacBuffer, offset, output, outputOffset, true); // TODO: confirm header is seed
}
-
- public void AddMac(byte[] input, int offset, int length, byte[] output, int outputOffset, bool isHeader)
+ else
{
- if (isHeader)
- {
- input.AsSpan(0, 16).CopyTo(_addMacBuffer);
- UpdateMac(_egressMac, _egressMacCopy, _addMacBuffer, offset, output, outputOffset, true); // TODO: confirm header is seed
- }
- else
- {
- _egressMac.Update(input.AsSpan(offset, length));
+ _egressMac.Update(input.AsSpan(offset, length));
- // frame-mac: right128 of egress-mac.update(aes(mac-secret,egress-mac) ^ right128(egress-mac.update(frame-ciphertext).digest))
- DoFinalNoReset(_egressMac, _egressMacCopy, _addMacBuffer); // frame MAC seed
- UpdateMac(_egressMac, _egressMacCopy, _addMacBuffer, 0, output, outputOffset, true);
- }
+ // frame-mac: right128 of egress-mac.update(aes(mac-secret,egress-mac) ^ right128(egress-mac.update(frame-ciphertext).digest))
+ DoFinalNoReset(_egressMac, _egressMacCopy, _addMacBuffer); // frame MAC seed
+ UpdateMac(_egressMac, _egressMacCopy, _addMacBuffer, 0, output, outputOffset, true);
}
+ }
- private readonly byte[] _addMacBuffer;
- private readonly byte[] _checkMacBuffer;
- private readonly byte[] _ingressAesBlockBuffer;
- private readonly byte[] _egressAesBlockBuffer;
+ private readonly byte[] _addMacBuffer;
+ private readonly byte[] _checkMacBuffer;
+ private readonly byte[] _ingressAesBlockBuffer;
+ private readonly byte[] _egressAesBlockBuffer;
- public bool CheckMac(byte[] mac, bool isHeader)
+ public bool CheckMac(byte[] mac, bool isHeader)
+ {
+ if (!isHeader)
{
- if (!isHeader)
- {
- DoFinalNoReset(_ingressMac, _ingressMacCopy, _checkMacBuffer); // frame MAC seed
- }
+ DoFinalNoReset(_ingressMac, _ingressMacCopy, _checkMacBuffer); // frame MAC seed
+ }
- byte[] aesBlock = _ingressAesBlockBuffer;
- DoFinalNoReset(_ingressMac, _ingressMacCopy, aesBlock);
+ byte[] aesBlock = _ingressAesBlockBuffer;
+ DoFinalNoReset(_ingressMac, _ingressMacCopy, aesBlock);
- _aesEngine.ProcessBlock(aesBlock, 0, aesBlock, 0);
+ _aesEngine.ProcessBlock(aesBlock, 0, aesBlock, 0);
- // Note that although the mac digest size is 32 bytes, we only use 16 bytes in the computation
- int length = 16;
- for (int i = 0; i < length; i++)
- {
- aesBlock[i] ^= _checkMacBuffer[i];
- }
+ // Note that although the mac digest size is 32 bytes, we only use 16 bytes in the computation
+ int length = 16;
+ for (int i = 0; i < length; i++)
+ {
+ aesBlock[i] ^= _checkMacBuffer[i];
+ }
- _ingressMac.Update(aesBlock.AsSpan(0, length));
- byte[] result = _checkMacBuffer;
- DoFinalNoReset(_ingressMac, _ingressMacCopy, result);
+ _ingressMac.Update(aesBlock.AsSpan(0, length));
+ byte[] result = _checkMacBuffer;
+ DoFinalNoReset(_ingressMac, _ingressMacCopy, result);
- bool isMacSame = true;
- for (int i = 0; i < length; i++)
+ bool isMacSame = true;
+ for (int i = 0; i < length; i++)
+ {
+ if (mac[i] != result[i])
{
- if (mac[i] != result[i])
- {
- isMacSame = false;
- break;
- }
+ isMacSame = false;
+ break;
}
-
- return isMacSame;
}
- public void CheckMac(byte[] input, int offset, int length, bool isHeader)
+ return isMacSame;
+ }
+
+ public void CheckMac(byte[] input, int offset, int length, bool isHeader)
+ {
+ if (isHeader)
{
- if (isHeader)
- {
- input.AsSpan(0, 32).CopyTo(_checkMacBuffer);
- UpdateMac(_ingressMac, _ingressMacCopy, _checkMacBuffer, offset, input, offset + length, false);
- }
- else
- {
- _ingressMac.Update(input.AsSpan(offset, length));
+ input.AsSpan(0, 32).CopyTo(_checkMacBuffer);
+ UpdateMac(_ingressMac, _ingressMacCopy, _checkMacBuffer, offset, input, offset + length, false);
+ }
+ else
+ {
+ _ingressMac.Update(input.AsSpan(offset, length));
- // frame-mac: right128 of egress-mac.update(aes(mac-secret,egress-mac) ^ right128(egress-mac.update(frame-ciphertext).digest))
- DoFinalNoReset(_ingressMac, _ingressMacCopy, _checkMacBuffer); // frame MAC seed
- UpdateMac(_ingressMac, _ingressMacCopy, _checkMacBuffer, 0, input, offset + length, false);
- }
+ // frame-mac: right128 of egress-mac.update(aes(mac-secret,egress-mac) ^ right128(egress-mac.update(frame-ciphertext).digest))
+ DoFinalNoReset(_ingressMac, _ingressMacCopy, _checkMacBuffer); // frame MAC seed
+ UpdateMac(_ingressMac, _ingressMacCopy, _checkMacBuffer, 0, input, offset + length, false);
}
+ }
- ///
- /// adapted from ethereumJ
- ///
- private void UpdateMac(KeccakHash mac, KeccakHash macCopy, byte[] seed, int offset, byte[] output, int outOffset, bool egress)
- {
- byte[] aesBlock = egress ? _egressAesBlockBuffer : _ingressAesBlockBuffer;
- DoFinalNoReset(mac, macCopy, aesBlock);
+ ///
+ /// adapted from ethereumJ
+ ///
+ private void UpdateMac(KeccakHash mac, KeccakHash macCopy, byte[] seed, int offset, byte[] output, int outOffset, bool egress)
+ {
+ byte[] aesBlock = egress ? _egressAesBlockBuffer : _ingressAesBlockBuffer;
+ DoFinalNoReset(mac, macCopy, aesBlock);
- _aesEngine.ProcessBlock(aesBlock, 0, aesBlock, 0);
+ _aesEngine.ProcessBlock(aesBlock, 0, aesBlock, 0);
- // Note that although the mac digest size is 32 bytes, we only use 16 bytes in the computation
- int length = 16;
- for (int i = 0; i < length; i++)
- {
- aesBlock[i] ^= seed[i + offset];
- }
+ // Note that although the mac digest size is 32 bytes, we only use 16 bytes in the computation
+ int length = 16;
+ for (int i = 0; i < length; i++)
+ {
+ aesBlock[i] ^= seed[i + offset];
+ }
- mac.Update(aesBlock.AsSpan(0, length));
- byte[] result = seed;
- DoFinalNoReset(mac, macCopy, result);
+ mac.Update(aesBlock.AsSpan(0, length));
+ byte[] result = seed;
+ DoFinalNoReset(mac, macCopy, result);
- if (egress)
- {
- Array.Copy(result, 0, output, outOffset, length);
- }
- else
+ if (egress)
+ {
+ Array.Copy(result, 0, output, outOffset, length);
+ }
+ else
+ {
+ bool isMacSame = true;
+ for (int i = 0; i < length; i++)
{
- bool isMacSame = true;
- for (int i = 0; i < length; i++)
+ if (output[i + outOffset] != result[i])
{
- if (output[i + outOffset] != result[i])
- {
- isMacSame = false;
- break;
- }
+ isMacSame = false;
+ break;
}
+ }
- if (!isMacSame)
- {
- throw new IOException($"MAC mismatch from {_remoteNodeId}");
- }
+ if (!isMacSame)
+ {
+ throw new IOException($"MAC mismatch from {_remoteNodeId}");
}
}
+ }
- private static void DoFinalNoReset(KeccakHash mac, KeccakHash macCopy, byte[] output)
- {
- macCopy.ResetTo(mac);
- macCopy.UpdateFinalTo(output);
- }
+ private static void DoFinalNoReset(KeccakHash mac, KeccakHash macCopy, byte[] output)
+ {
+ macCopy.ResetTo(mac);
+ macCopy.UpdateFinalTo(output);
+ }
- public void Dispose()
- {
- _egressMacCopy.Reset();
- _ingressMacCopy.Reset();
- }
+ public void Dispose()
+ {
+ _egressMacCopy.Reset();
+ _ingressMacCopy.Reset();
}
}