diff options
-rw-r--r-- | crypto/src/crypto/engines/SEEDEngine.cs | 237 |
1 files changed, 110 insertions, 127 deletions
diff --git a/crypto/src/crypto/engines/SEEDEngine.cs b/crypto/src/crypto/engines/SEEDEngine.cs index 07ffe06bb..c3d364f95 100644 --- a/crypto/src/crypto/engines/SEEDEngine.cs +++ b/crypto/src/crypto/engines/SEEDEngine.cs @@ -1,14 +1,17 @@ using System; +#if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER +using System.Runtime.CompilerServices; +#endif using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Utilities; namespace Org.BouncyCastle.Crypto.Engines { - /** + /** * Implementation of the SEED algorithm as described in RFC 4009 */ - public class SeedEngine + public class SeedEngine : IBlockCipher { private const int BlockSize = 16; @@ -173,48 +176,51 @@ namespace Org.BouncyCastle.Crypto.Engines public virtual void Init(bool forEncryption, ICipherParameters parameters) { this.forEncryption = forEncryption; - wKey = CreateWorkingKey(((KeyParameter)parameters).GetKey()); + wKey = CreateWorkingKey((KeyParameter)parameters); } - public virtual string AlgorithmName - { - get { return "SEED"; } - } + public virtual string AlgorithmName => "SEED"; - public virtual int GetBlockSize() - { - return BlockSize; - } + public virtual int GetBlockSize() => BlockSize; public virtual int ProcessBlock(byte[] inBuf, int inOff, byte[] outBuf, int outOff) { - if (wKey == null) - throw new InvalidOperationException("SEED engine not initialised"); - Check.DataLength(inBuf, inOff, BlockSize, "input buffer too short"); Check.OutputLength(outBuf, outOff, BlockSize, "output buffer too short"); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return ProcessBlock(inBuf.AsSpan(inOff), outBuf.AsSpan(outOff)); +#else + if (wKey == null) + throw new InvalidOperationException("SEED engine not initialised"); + long l = (long)Pack.BE_To_UInt64(inBuf, inOff + 0); long r = (long)Pack.BE_To_UInt64(inBuf, inOff + 8); if (forEncryption) { - for (int i = 0; i < 16; i++) + for (int i = 0; i < 32; i += 4) { - long nl = r; - - r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r); - l = nl; - } - } + int w0 = wKey[i + 0]; + int w1 = wKey[i + 1]; + int w2 = wKey[i + 2]; + int w3 = wKey[i + 3]; + + l ^= F(w0, w1, r); + r ^= F(w2, w3, l); + } + } else { - for (int i = 15; i >= 0; i--) + for (int i = 28; i >= 0; i -= 4) { - long nl = r; + int w0 = wKey[i + 0]; + int w1 = wKey[i + 1]; + int w2 = wKey[i + 2]; + int w3 = wKey[i + 3]; - r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r); - l = nl; + l ^= F(w2, w3, r); + r ^= F(w0, w1, l); } } @@ -222,6 +228,7 @@ namespace Org.BouncyCastle.Crypto.Engines Pack.UInt64_To_BE((ulong)l, outBuf, outOff + 8); return BlockSize; +#endif } #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER @@ -236,129 +243,105 @@ namespace Org.BouncyCastle.Crypto.Engines long l = (long)Pack.BE_To_UInt64(input); long r = (long)Pack.BE_To_UInt64(input[8..]); - if (forEncryption) - { - for (int i = 0; i < 16; i++) - { - long nl = r; - - r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r); - l = nl; - } - } - else - { - for (int i = 15; i >= 0; i--) - { - long nl = r; - - r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r); - l = nl; - } - } - - Pack.UInt64_To_BE((ulong)r, output); + if (forEncryption) + { + for (int i = 0; i < 32; i += 4) + { + int w0 = wKey[i + 0]; + int w1 = wKey[i + 1]; + int w2 = wKey[i + 2]; + int w3 = wKey[i + 3]; + + l ^= F(w0, w1, r); + r ^= F(w2, w3, l); + } + } + else + { + for (int i = 28; i >= 0; i -= 4) + { + int w0 = wKey[i + 0]; + int w1 = wKey[i + 1]; + int w2 = wKey[i + 2]; + int w3 = wKey[i + 3]; + + l ^= F(w2, w3, r); + r ^= F(w0, w1, l); + } + } + + Pack.UInt64_To_BE((ulong)r, output); Pack.UInt64_To_BE((ulong)l, output[8..]); return BlockSize; } #endif - private int[] CreateWorkingKey(byte[] inKey) + private static int[] CreateWorkingKey(KeyParameter keyParameter) { - if (inKey.Length != 16) + if (keyParameter.KeyLength != 16) throw new ArgumentException("key size must be 128 bits"); - int[] key = new int[32]; - long lower = (long)Pack.BE_To_UInt64(inKey, 0); - long upper = (long)Pack.BE_To_UInt64(inKey, 8); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + var inKey = keyParameter.Key; +#else + byte[] inKey = keyParameter.GetKey(); +#endif - int key0 = extractW0(lower); - int key1 = extractW1(lower); - int key2 = extractW0(upper); - int key3 = extractW1(upper); + int[] key = new int[32]; - for (int i = 0; i < 16; i++) - { - key[2 * i] = G(key0 + key2 - (int)KC[i]); - key[2 * i + 1] = G(key1 - key3 + (int)KC[i]); + uint key0 = Pack.BE_To_UInt32(inKey, 0); + uint key1 = Pack.BE_To_UInt32(inKey, 4); + uint key2 = Pack.BE_To_UInt32(inKey, 8); + uint key3 = Pack.BE_To_UInt32(inKey, 12); - if (i % 2 == 0) - { - lower = rotateRight8(lower); - key0 = extractW0(lower); - key1 = extractW1(lower); - } - else - { - upper = rotateLeft8(upper); - key2 = extractW0(upper); - key3 = extractW1(upper); - } - } + for (int i = 0; i < 16; i += 2) + { + uint KC_i, keyt; - return key; - } + KC_i = KC[i]; + key[2 * i + 0] = G((int)(key0 + key2 - KC_i)); + key[2 * i + 1] = G((int)(key1 - key3 + KC_i)); - private int extractW1( - long lVal) - { - return (int)lVal; - } + keyt = key0 >> 8 | key1 << 24; + key1 = key1 >> 8 | key0 << 24; + key0 = keyt; - private int extractW0( - long lVal) - { - return (int)(lVal >> 32); - } + KC_i = KC[i + 1]; + key[2 * i + 2] = G((int)(key0 + key2 - KC_i)); + key[2 * i + 3] = G((int)(key1 - key3 + KC_i)); - private long rotateLeft8( - long x) - { - return (x << 8) | ((long)((ulong) x >> 56)); - } + keyt = key2 << 8 | key3 >> 24; + key3 = key3 << 8 | key2 >> 24; + key2 = keyt; + } - private long rotateRight8( - long x) - { - return ((long)((ulong) x >> 8)) | (x << 56); + return key; } - private int G( - int x) - { - return (int)(SS0[x & 0xff] ^ SS1[(x >> 8) & 0xff] ^ SS2[(x >> 16) & 0xff] ^ SS3[(x >> 24) & 0xff]); - } +#if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + private static long F(int ki0, int ki1, long r) + { + int r0 = ki0 ^ (int)(r >> 32); + int r1 = ki1 ^ (int)r; - private long F( - int ki0, - int ki1, - long r) - { - int r0 = (int)(r >> 32); - int r1 = (int)r; - int rd1 = phaseCalc2(r0, ki0, r1, ki1); - int rd0 = rd1 + phaseCalc1(r0, ki0, r1, ki1); + int t0 = G(r0 ^ r1); + int t1 = G(r0 + t0); - return ((long)rd0 << 32) | (rd1 & 0xffffffffL); - } + int rd1 = G(t1 + t0); + int rd0 = rd1 + t1; - private int phaseCalc1( - int r0, - int ki0, - int r1, - int ki1) - { - return G(G((r0 ^ ki0) ^ (r1 ^ ki1)) + (r0 ^ ki0)); - } + return (long)rd0 << 32 | rd1 & 0xFFFFFFFFL; + } - private int phaseCalc2( - int r0, - int ki0, - int r1, - int ki1) - { - return G(phaseCalc1(r0, ki0, r1, ki1) + G((r0 ^ ki0) ^ (r1 ^ ki1))); - } - } +#if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + private static int G(int x) + { + return (int)(SS0[x & 0xff] ^ SS1[(x >> 8) & 0xff] ^ SS2[(x >> 16) & 0xff] ^ SS3[(x >> 24) & 0xff]); + } + } } |