diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-08-30 13:21:28 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-08-30 13:21:28 +0700 |
commit | 198d760145c81f944ff9e3579d07bed14c58f7b7 (patch) | |
tree | 090876fffef9932c47ede311e602c56455b37ea7 | |
parent | Span-based variant for ISP80090Drbg.Generate (diff) | |
download | BouncyCastle.NET-ed25519-198d760145c81f944ff9e3579d07bed14c58f7b7.tar.xz |
Span-based variant for IStreamCipher.ProcessBytes
-rw-r--r-- | crypto/src/crypto/IStreamCipher.cs | 45 | ||||
-rw-r--r-- | crypto/src/crypto/StreamBlockCipher.cs | 22 | ||||
-rw-r--r-- | crypto/src/crypto/engines/HC128Engine.cs | 15 | ||||
-rw-r--r-- | crypto/src/crypto/engines/HC256Engine.cs | 15 | ||||
-rw-r--r-- | crypto/src/crypto/engines/ISAACEngine.cs | 21 | ||||
-rw-r--r-- | crypto/src/crypto/engines/RC4Engine.cs | 34 | ||||
-rw-r--r-- | crypto/src/crypto/engines/Salsa20Engine.cs | 24 | ||||
-rw-r--r-- | crypto/src/crypto/engines/VMPCEngine.cs | 21 |
8 files changed, 169 insertions, 28 deletions
diff --git a/crypto/src/crypto/IStreamCipher.cs b/crypto/src/crypto/IStreamCipher.cs index 8e575a7e5..0408b33c9 100644 --- a/crypto/src/crypto/IStreamCipher.cs +++ b/crypto/src/crypto/IStreamCipher.cs @@ -22,24 +22,35 @@ namespace Org.BouncyCastle.Crypto /// <returns>the result of processing the input byte.</returns> byte ReturnByte(byte input); - /// <summary> - /// Process a block of bytes from <c>input</c> putting the result into <c>output</c>. - /// </summary> - /// <param name="input">The input byte array.</param> - /// <param name="inOff"> - /// The offset into <c>input</c> where the data to be processed starts. - /// </param> - /// <param name="length">The number of bytes to be processed.</param> - /// <param name="output">The output buffer the processed bytes go into.</param> - /// <param name="outOff"> - /// The offset into <c>output</c> the processed data starts at. - /// </param> - /// <exception cref="DataLengthException">If the output buffer is too small.</exception> + /// <summary> + /// Process a block of bytes from <paramref name="input"/>, putting the result into <paramref name="output"/>. + /// </summary> + /// <param name="input">The input byte array.</param> + /// <param name="inOff"> + /// The offset into <c>input</c> where the data to be processed starts. + /// </param> + /// <param name="length">The number of bytes to be processed.</param> + /// <param name="output">The output buffer the processed bytes go into.</param> + /// <param name="outOff"> + /// The offset into <c>output</c> the processed data starts at. + /// </param> + /// <exception cref="DataLengthException">If the input buffer is too small.</exception> + /// <exception cref="OutputLengthException">If the output buffer is too small.</exception> void ProcessBytes(byte[] input, int inOff, int length, byte[] output, int outOff); - /// <summary> - /// Reset the cipher to the same state as it was after the last init (if there was one). - /// </summary> - void Reset(); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + /// <summary> + /// Process a block of bytes from <paramref name="input"/>, putting the result into <paramref name="output"/>. + /// </summary> + /// <param name="input">The input span.</param> + /// <param name="output">The output span.</param> + /// <exception cref="OutputLengthException">If the output span is too small.</exception> + void ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output); +#endif + + /// <summary> + /// Reset the cipher to the same state as it was after the last init (if there was one). + /// </summary> + void Reset(); } } diff --git a/crypto/src/crypto/StreamBlockCipher.cs b/crypto/src/crypto/StreamBlockCipher.cs index ef2a8b68a..0cd9d110a 100644 --- a/crypto/src/crypto/StreamBlockCipher.cs +++ b/crypto/src/crypto/StreamBlockCipher.cs @@ -1,7 +1,5 @@ using System; -using Org.BouncyCastle.Crypto.Parameters; - namespace Org.BouncyCastle.Crypto { /** @@ -88,8 +86,8 @@ namespace Org.BouncyCastle.Crypto byte[] output, int outOff) { - if (outOff + length > output.Length) - throw new DataLengthException("output buffer too small in ProcessBytes()"); + Check.DataLength(input, inOff, length, "input buffer too short"); + Check.OutputLength(output, outOff, length, "output buffer too short"); for (int i = 0; i != length; i++) { @@ -97,11 +95,23 @@ namespace Org.BouncyCastle.Crypto } } - /** +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output) + { + Check.OutputLength(output, input.Length, "output buffer too short"); + + for (int i = 0; i != input.Length; i++) + { + cipher.ProcessBlock(input[i..], output[i..]); + } + } +#endif + + /** * reset the underlying cipher. This leaves it in the same state * it was at after the last init (if there was one). */ - public void Reset() + public void Reset() { cipher.Reset(); } diff --git a/crypto/src/crypto/engines/HC128Engine.cs b/crypto/src/crypto/engines/HC128Engine.cs index b83eb7083..6971361dd 100644 --- a/crypto/src/crypto/engines/HC128Engine.cs +++ b/crypto/src/crypto/engines/HC128Engine.cs @@ -222,6 +222,21 @@ namespace Org.BouncyCastle.Crypto.Engines } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output) + { + if (!initialised) + throw new InvalidOperationException(AlgorithmName + " not initialised"); + + Check.OutputLength(output, input.Length, "output buffer too short"); + + for (int i = 0; i < input.Length; i++) + { + output[i] = (byte)(input[i] ^ GetByte()); + } + } +#endif + public virtual void Reset() { Init(); diff --git a/crypto/src/crypto/engines/HC256Engine.cs b/crypto/src/crypto/engines/HC256Engine.cs index d8d83a634..8a17af433 100644 --- a/crypto/src/crypto/engines/HC256Engine.cs +++ b/crypto/src/crypto/engines/HC256Engine.cs @@ -206,6 +206,21 @@ namespace Org.BouncyCastle.Crypto.Engines } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output) + { + if (!initialised) + throw new InvalidOperationException(AlgorithmName + " not initialised"); + + Check.OutputLength(output, input.Length, "output buffer too short"); + + for (int i = 0; i < input.Length; i++) + { + output[i] = (byte)(input[i] ^ GetByte()); + } + } +#endif + public virtual void Reset() { Init(); diff --git a/crypto/src/crypto/engines/ISAACEngine.cs b/crypto/src/crypto/engines/ISAACEngine.cs index b94ee6ed9..b0ab30263 100644 --- a/crypto/src/crypto/engines/ISAACEngine.cs +++ b/crypto/src/crypto/engines/ISAACEngine.cs @@ -94,6 +94,27 @@ namespace Org.BouncyCastle.Crypto.Engines } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output) + { + if (!initialised) + throw new InvalidOperationException(AlgorithmName + " not initialised"); + + Check.OutputLength(output, input.Length, "output buffer too short"); + + for (int i = 0; i < input.Length; i++) + { + if (index == 0) + { + isaac(); + keyStream = Pack.UInt32_To_BE(results); + } + output[i] = (byte)(keyStream[index++] ^ input[i]); + index &= 1023; + } + } +#endif + public virtual string AlgorithmName { get { return "ISAAC"; } diff --git a/crypto/src/crypto/engines/RC4Engine.cs b/crypto/src/crypto/engines/RC4Engine.cs index a515bb04e..5ee07c766 100644 --- a/crypto/src/crypto/engines/RC4Engine.cs +++ b/crypto/src/crypto/engines/RC4Engine.cs @@ -83,16 +83,40 @@ namespace Org.BouncyCastle.Crypto.Engines x = (x + 1) & 0xff; y = (engineState[x] + y) & 0xff; + byte sx = engineState[x]; + byte sy = engineState[y]; + + // swap + engineState[x] = sy; + engineState[y] = sx; + + // xor + output[i+outOff] = (byte)(input[i + inOff] ^ engineState[(sx + sy) & 0xff]); + } + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output) + { + Check.OutputLength(output, input.Length, "output buffer too short"); + + for (int i = 0; i < input.Length; i++) + { + x = (x + 1) & 0xff; + y = (engineState[x] + y) & 0xff; + + byte sx = engineState[x]; + byte sy = engineState[y]; + // swap - byte tmp = engineState[x]; - engineState[x] = engineState[y]; - engineState[y] = tmp; + engineState[x] = sy; + engineState[y] = sx; // xor - output[i+outOff] = (byte)(input[i + inOff] - ^ engineState[(engineState[x] + engineState[y]) & 0xff]); + output[i] = (byte)(input[i] ^ engineState[(sx + sy) & 0xff]); } } +#endif public virtual void Reset() { diff --git a/crypto/src/crypto/engines/Salsa20Engine.cs b/crypto/src/crypto/engines/Salsa20Engine.cs index 77b08f9fc..c3e44f645 100644 --- a/crypto/src/crypto/engines/Salsa20Engine.cs +++ b/crypto/src/crypto/engines/Salsa20Engine.cs @@ -181,6 +181,30 @@ namespace Org.BouncyCastle.Crypto.Engines } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output) + { + if (!initialised) + throw new InvalidOperationException(AlgorithmName + " not initialised"); + + Check.OutputLength(output, input.Length, "output buffer too short"); + + if (LimitExceeded((uint)input.Length)) + throw new MaxBytesExceededException("2^70 byte limit per IV would be exceeded; Change IV"); + + for (int i = 0; i < input.Length; i++) + { + if (index == 0) + { + GenerateKeyStream(keyStream); + AdvanceCounter(); + } + output[i] = (byte)(keyStream[index++] ^ input[i]); + index &= 63; + } + } +#endif + public virtual void Reset() { index = 0; diff --git a/crypto/src/crypto/engines/VMPCEngine.cs b/crypto/src/crypto/engines/VMPCEngine.cs index 852901e36..d8974b6ce 100644 --- a/crypto/src/crypto/engines/VMPCEngine.cs +++ b/crypto/src/crypto/engines/VMPCEngine.cs @@ -110,6 +110,27 @@ namespace Org.BouncyCastle.Crypto.Engines } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public virtual void ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output) + { + Check.OutputLength(output, input.Length, "output buffer too short"); + + for (int i = 0; i < input.Length; i++) + { + s = P[(s + P[n & 0xff]) & 0xff]; + byte z = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff]; + // encryption + byte temp = P[n & 0xff]; + P[n & 0xff] = P[s & 0xff]; + P[s & 0xff] = temp; + n = (byte)((n + 1) & 0xff); + + // xor + output[i] = (byte)(input[i] ^ z); + } + } +#endif + public virtual void Reset() { InitKey(this.workingKey, this.workingIV); |