diff --git a/crypto/src/crypto/BufferedAeadBlockCipher.cs b/crypto/src/crypto/BufferedAeadBlockCipher.cs
index 92eab9dd4..bf453feea 100644
--- a/crypto/src/crypto/BufferedAeadBlockCipher.cs
+++ b/crypto/src/crypto/BufferedAeadBlockCipher.cs
@@ -97,12 +97,9 @@ namespace Org.BouncyCastle.Crypto
* @exception DataLengthException if there isn't enough space in out.
* @exception InvalidOperationException if the cipher isn't initialised.
*/
- public override int ProcessByte(
- byte input,
- byte[] output,
- int outOff)
- {
- return cipher.ProcessByte(input, output, outOff);
+ public override int ProcessByte(byte input, byte[] output, int outOff)
+ {
+ return cipher.ProcessByte(input, output, outOff);
}
public override byte[] ProcessByte(
@@ -124,7 +121,14 @@ namespace Org.BouncyCastle.Crypto
return outBytes;
}
- public override byte[] ProcessBytes(
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int ProcessByte(byte input, Span<byte> output)
+ {
+ return cipher.ProcessByte(input, output);
+ }
+#endif
+
+ public override byte[] ProcessBytes(
byte[] input,
int inOff,
int length)
diff --git a/crypto/src/crypto/BufferedAeadCipher.cs b/crypto/src/crypto/BufferedAeadCipher.cs
index aba64f0f4..fb3408e12 100644
--- a/crypto/src/crypto/BufferedAeadCipher.cs
+++ b/crypto/src/crypto/BufferedAeadCipher.cs
@@ -96,10 +96,7 @@ namespace Org.BouncyCastle.Crypto
* @exception DataLengthException if there isn't enough space in out.
* @exception InvalidOperationException if the cipher isn't initialised.
*/
- public override int ProcessByte(
- byte input,
- byte[] output,
- int outOff)
+ public override int ProcessByte(byte input, byte[] output, int outOff)
{
return cipher.ProcessByte(input, output, outOff);
}
@@ -123,6 +120,13 @@ namespace Org.BouncyCastle.Crypto
return outBytes;
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int ProcessByte(byte input, Span<byte> output)
+ {
+ return cipher.ProcessByte(input, output);
+ }
+#endif
+
public override byte[] ProcessBytes(
byte[] input,
int inOff,
diff --git a/crypto/src/crypto/BufferedAsymmetricBlockCipher.cs b/crypto/src/crypto/BufferedAsymmetricBlockCipher.cs
index 83c2fe70c..be933a028 100644
--- a/crypto/src/crypto/BufferedAsymmetricBlockCipher.cs
+++ b/crypto/src/crypto/BufferedAsymmetricBlockCipher.cs
@@ -90,7 +90,27 @@ namespace Org.BouncyCastle.Crypto
return null;
}
- public override byte[] ProcessBytes(
+ public override int ProcessByte(byte input, byte[] output, int outOff)
+ {
+ if (bufOff >= buffer.Length)
+ throw new DataLengthException("attempt to process message too long for cipher");
+
+ buffer[bufOff++] = input;
+ return 0;
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int ProcessByte(byte input, Span<byte> output)
+ {
+ if (bufOff >= buffer.Length)
+ throw new DataLengthException("attempt to process message too long for cipher");
+
+ buffer[bufOff++] = input;
+ return 0;
+ }
+#endif
+
+ public override byte[] ProcessBytes(
byte[] input,
int inOff,
int length)
diff --git a/crypto/src/crypto/BufferedBlockCipher.cs b/crypto/src/crypto/BufferedBlockCipher.cs
index 3b000ed59..eaaae255e 100644
--- a/crypto/src/crypto/BufferedBlockCipher.cs
+++ b/crypto/src/crypto/BufferedBlockCipher.cs
@@ -126,10 +126,7 @@ namespace Org.BouncyCastle.Crypto
* @exception DataLengthException if there isn't enough space in out.
* @exception InvalidOperationException if the cipher isn't initialised.
*/
- public override int ProcessByte(
- byte input,
- byte[] output,
- int outOff)
+ public override int ProcessByte(byte input, byte[] output, int outOff)
{
buf[bufOff++] = input;
@@ -164,7 +161,24 @@ namespace Org.BouncyCastle.Crypto
return outBytes;
}
- public override byte[] ProcessBytes(
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int ProcessByte(byte input, Span<byte> output)
+ {
+ buf[bufOff++] = input;
+
+ if (bufOff == buf.Length)
+ {
+ Check.OutputLength(output, buf.Length, "output buffer too short");
+
+ bufOff = 0;
+ return cipher.ProcessBlock(buf, output);
+ }
+
+ return 0;
+ }
+#endif
+
+ public override byte[] ProcessBytes(
byte[] input,
int inOff,
int length)
@@ -230,7 +244,7 @@ namespace Org.BouncyCastle.Crypto
if (length >= gapLen)
{
Array.Copy(input, inOff, buf, bufOff, gapLen);
- resultLen += cipher.ProcessBlock(buf, 0, output, outOff);
+ resultLen = cipher.ProcessBlock(buf, 0, output, outOff);
bufOff = 0;
length -= gapLen;
inOff += gapLen;
@@ -265,7 +279,7 @@ namespace Org.BouncyCastle.Crypto
if (input.Length >= gapLen)
{
input[..gapLen].CopyTo(buf.AsSpan(bufOff));
- resultLen += cipher.ProcessBlock(buf, output);
+ resultLen = cipher.ProcessBlock(buf, output);
bufOff = 0;
input = input[gapLen..];
while (input.Length >= buf.Length)
diff --git a/crypto/src/crypto/BufferedCipherBase.cs b/crypto/src/crypto/BufferedCipherBase.cs
index 4b3069d0d..2e9026b14 100644
--- a/crypto/src/crypto/BufferedCipherBase.cs
+++ b/crypto/src/crypto/BufferedCipherBase.cs
@@ -32,7 +32,11 @@ namespace Org.BouncyCastle.Crypto
return outBytes.Length;
}
- public virtual byte[] ProcessBytes(
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public abstract int ProcessByte(byte input, Span<byte> output);
+#endif
+
+ public virtual byte[] ProcessBytes(
byte[] input)
{
return ProcessBytes(input, 0, input.Length);
diff --git a/crypto/src/crypto/BufferedIesCipher.cs b/crypto/src/crypto/BufferedIesCipher.cs
index 1aff47ab4..6497f7204 100644
--- a/crypto/src/crypto/BufferedIesCipher.cs
+++ b/crypto/src/crypto/BufferedIesCipher.cs
@@ -60,14 +60,27 @@ namespace Org.BouncyCastle.Crypto
return 0;
}
- public override byte[] ProcessByte(
- byte input)
+ public override byte[] ProcessByte(byte input)
{
buffer.WriteByte(input);
return null;
}
- public override byte[] ProcessBytes(
+ public override int ProcessByte(byte input, byte[] output, int outOff)
+ {
+ buffer.WriteByte(input);
+ return 0;
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int ProcessByte(byte input, Span<byte> output)
+ {
+ buffer.WriteByte(input);
+ return 0;
+ }
+#endif
+
+ public override byte[] ProcessBytes(
byte[] input,
int inOff,
int length)
diff --git a/crypto/src/crypto/BufferedStreamCipher.cs b/crypto/src/crypto/BufferedStreamCipher.cs
index 8307429cb..8ee41c1e5 100644
--- a/crypto/src/crypto/BufferedStreamCipher.cs
+++ b/crypto/src/crypto/BufferedStreamCipher.cs
@@ -7,32 +7,29 @@ namespace Org.BouncyCastle.Crypto
public class BufferedStreamCipher
: BufferedCipherBase
{
- private readonly IStreamCipher cipher;
+ private readonly IStreamCipher m_cipher;
- public BufferedStreamCipher(
- IStreamCipher cipher)
+ public BufferedStreamCipher(IStreamCipher cipher)
{
if (cipher == null)
throw new ArgumentNullException("cipher");
- this.cipher = cipher;
+ this.m_cipher = cipher;
}
public override string AlgorithmName
{
- get { return cipher.AlgorithmName; }
+ get { return m_cipher.AlgorithmName; }
}
- public override void Init(
- bool forEncryption,
- ICipherParameters parameters)
- {
- if (parameters is ParametersWithRandom)
+ public override void Init(bool forEncryption, ICipherParameters parameters)
+ {
+ if (parameters is ParametersWithRandom withRandom)
{
- parameters = ((ParametersWithRandom) parameters).Parameters;
+ parameters = withRandom.Parameters;
}
- cipher.Init(forEncryption, parameters);
+ m_cipher.Init(forEncryption, parameters);
}
public override int GetBlockSize()
@@ -40,115 +37,101 @@ namespace Org.BouncyCastle.Crypto
return 0;
}
- public override int GetOutputSize(
- int inputLen)
+ public override int GetOutputSize(int inputLen)
{
return inputLen;
}
- public override int GetUpdateOutputSize(
- int inputLen)
+ public override int GetUpdateOutputSize(int inputLen)
{
return inputLen;
}
- public override byte[] ProcessByte(
- byte input)
+ public override byte[] ProcessByte(byte input)
{
- return new byte[]{ cipher.ReturnByte(input) };
+ return new byte[]{ m_cipher.ReturnByte(input) };
}
- public override int ProcessByte(
- byte input,
- byte[] output,
- int outOff)
- {
- if (outOff >= output.Length)
+ public override int ProcessByte(byte input, byte[] output, int outOff)
+ {
+ if (outOff >= output.Length)
throw new DataLengthException("output buffer too short");
- output[outOff] = cipher.ReturnByte(input);
+ output[outOff] = m_cipher.ReturnByte(input);
return 1;
}
- public override byte[] ProcessBytes(
- byte[] input,
- int inOff,
- int length)
- {
- if (length < 1)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int ProcessByte(byte input, Span<byte> output)
+ {
+ output[0] = m_cipher.ReturnByte(input);
+ return 1;
+ }
+#endif
+
+ public override byte[] ProcessBytes(byte[] input, int inOff, int length)
+ {
+ if (length < 1)
return null;
byte[] output = new byte[length];
- cipher.ProcessBytes(input, inOff, length, output, 0);
+ m_cipher.ProcessBytes(input, inOff, length, output, 0);
return output;
}
- public override int ProcessBytes(
- byte[] input,
- int inOff,
- int length,
- byte[] output,
- int outOff)
- {
- if (length < 1)
+ public override int ProcessBytes(byte[] input, int inOff, int length, byte[] output, int outOff)
+ {
+ if (length < 1)
return 0;
- if (length > 0)
- {
- cipher.ProcessBytes(input, inOff, length, output, outOff);
- }
-
+ m_cipher.ProcessBytes(input, inOff, length, output, outOff);
return length;
}
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
public override int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
{
- cipher.ProcessBytes(input, output);
+ m_cipher.ProcessBytes(input, output);
return input.Length;
}
#endif
public override byte[] DoFinal()
{
- Reset();
+ m_cipher.Reset();
return EmptyBuffer;
}
- public override byte[] DoFinal(
- byte[] input,
- int inOff,
- int length)
+ public override byte[] DoFinal(byte[] input, int inOff, int length)
{
if (length < 1)
return EmptyBuffer;
- byte[] output = ProcessBytes(input, inOff, length);
-
- Reset();
-
- return output;
+ byte[] output = new byte[length];
+ m_cipher.ProcessBytes(input, inOff, length, output, 0);
+ m_cipher.Reset();
+ return output;
}
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
public override int DoFinal(Span<byte> output)
{
- Reset();
+ m_cipher.Reset();
return 0;
}
- public virtual int DoFinal(ReadOnlySpan<byte> input, Span<byte> output)
+ public override int DoFinal(ReadOnlySpan<byte> input, Span<byte> output)
{
- int len = ProcessBytes(input, output);
- Reset();
- return len;
+ m_cipher.ProcessBytes(input, output);
+ m_cipher.Reset();
+ return input.Length;
}
#endif
public override void Reset()
{
- cipher.Reset();
+ m_cipher.Reset();
}
}
}
diff --git a/crypto/src/crypto/IBufferedCipher.cs b/crypto/src/crypto/IBufferedCipher.cs
index ddfb524c9..4471c42c9 100644
--- a/crypto/src/crypto/IBufferedCipher.cs
+++ b/crypto/src/crypto/IBufferedCipher.cs
@@ -23,7 +23,11 @@ namespace Org.BouncyCastle.Crypto
byte[] ProcessByte(byte input);
int ProcessByte(byte input, byte[] output, int outOff);
- byte[] ProcessBytes(byte[] input);
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ int ProcessByte(byte input, Span<byte> output);
+#endif
+
+ byte[] ProcessBytes(byte[] input);
byte[] ProcessBytes(byte[] input, int inOff, int length);
int ProcessBytes(byte[] input, byte[] output, int outOff);
int ProcessBytes(byte[] input, int inOff, int length, byte[] output, int outOff);
diff --git a/crypto/src/crypto/modes/CtsBlockCipher.cs b/crypto/src/crypto/modes/CtsBlockCipher.cs
index b1b00c5fa..5a1682568 100644
--- a/crypto/src/crypto/modes/CtsBlockCipher.cs
+++ b/crypto/src/crypto/modes/CtsBlockCipher.cs
@@ -1,9 +1,6 @@
using System;
using System.Diagnostics;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Parameters;
-
namespace Org.BouncyCastle.Crypto.Modes
{
/**
@@ -80,10 +77,7 @@ namespace Org.BouncyCastle.Crypto.Modes
* @exception DataLengthException if there isn't enough space in out.
* @exception InvalidOperationException if the cipher isn't initialised.
*/
- public override int ProcessByte(
- byte input,
- byte[] output,
- int outOff)
+ public override int ProcessByte(byte input, byte[] output, int outOff)
{
int resultLen = 0;
@@ -101,7 +95,27 @@ namespace Org.BouncyCastle.Crypto.Modes
return resultLen;
}
- /**
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int ProcessByte(byte input, Span<byte> output)
+ {
+ int resultLen = 0;
+
+ if (bufOff == buf.Length)
+ {
+ resultLen = cipher.ProcessBlock(buf, output);
+ Debug.Assert(resultLen == blockSize);
+
+ Array.Copy(buf, blockSize, buf, 0, blockSize);
+ bufOff = blockSize;
+ }
+
+ buf[bufOff++] = input;
+
+ return resultLen;
+ }
+#endif
+
+ /**
* process an array of bytes, producing output if necessary.
*
* @param in the input byte array.
@@ -113,12 +127,7 @@ namespace Org.BouncyCastle.Crypto.Modes
* @exception DataLengthException if there isn't enough space in out.
* @exception InvalidOperationException if the cipher isn't initialised.
*/
- public override int ProcessBytes(
- byte[] input,
- int inOff,
- int length,
- byte[] output,
- int outOff)
+ public override int ProcessBytes(byte[] input, int inOff, int length, byte[] output, int outOff)
{
if (length < 0)
throw new ArgumentException("Can't have a negative input length!");
@@ -138,7 +147,7 @@ namespace Org.BouncyCastle.Crypto.Modes
{
Array.Copy(input, inOff, buf, bufOff, gapLen);
- resultLen += cipher.ProcessBlock(buf, 0, output, outOff);
+ resultLen = cipher.ProcessBlock(buf, 0, output, outOff);
Array.Copy(buf, blockSize, buf, 0, blockSize);
bufOff = blockSize;
@@ -164,6 +173,49 @@ namespace Org.BouncyCastle.Crypto.Modes
return resultLen;
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
+ {
+ int blockSize = GetBlockSize();
+ int outLength = GetUpdateOutputSize(input.Length);
+
+ if (outLength > 0)
+ {
+ Check.OutputLength(output, outLength, "output buffer too short");
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.Length - bufOff;
+
+ if (input.Length > gapLen)
+ {
+ input[..gapLen].CopyTo(buf.AsSpan(bufOff));
+
+ resultLen = cipher.ProcessBlock(buf, output);
+ Array.Copy(buf, blockSize, buf, 0, blockSize);
+
+ bufOff = blockSize;
+
+ input = input[gapLen..];
+
+ while (input.Length > blockSize)
+ {
+ input[..blockSize].CopyTo(buf.AsSpan(bufOff));
+ resultLen += cipher.ProcessBlock(buf, output[resultLen..]);
+ Array.Copy(buf, blockSize, buf, 0, blockSize);
+
+ input = input[blockSize..];
+ }
+ }
+
+ input.CopyTo(buf.AsSpan(bufOff));
+
+ bufOff += input.Length;
+
+ return resultLen;
+ }
+#endif
+
/**
* Process the last block in the buffer.
*
@@ -177,14 +229,10 @@ namespace Org.BouncyCastle.Crypto.Modes
* @exception InvalidCipherTextException if cipher text decrypts wrongly (in
* case the exception will never Get thrown).
*/
- public override int DoFinal(
- byte[] output,
- int outOff)
+ public override int DoFinal(byte[] output, int outOff)
{
if (bufOff + outOff > output.Length)
- {
- throw new DataLengthException("output buffer too small in doFinal");
- }
+ throw new DataLengthException("output buffer too small in DoFinal");
int blockSize = cipher.GetBlockSize();
int length = bufOff - blockSize;
@@ -195,9 +243,7 @@ namespace Org.BouncyCastle.Crypto.Modes
cipher.ProcessBlock(buf, 0, block, 0);
if (bufOff < blockSize)
- {
throw new DataLengthException("need at least one block of input for CTS");
- }
for (int i = bufOff; i != buf.Length; i++)
{
@@ -244,5 +290,69 @@ namespace Org.BouncyCastle.Crypto.Modes
return offset;
}
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int DoFinal(Span<byte> output)
+ {
+ if (bufOff > output.Length)
+ throw new DataLengthException("output buffer too small in DoFinal");
+
+ int blockSize = cipher.GetBlockSize();
+ int length = bufOff - blockSize;
+ Span<byte> block = stackalloc byte[blockSize];
+
+ if (forEncryption)
+ {
+ cipher.ProcessBlock(buf, block);
+
+ if (bufOff < blockSize)
+ throw new DataLengthException("need at least one block of input for CTS");
+
+ for (int i = bufOff; i != buf.Length; i++)
+ {
+ buf[i] = block[i - blockSize];
+ }
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ buf[i] ^= block[i - blockSize];
+ }
+
+ IBlockCipher c = (cipher is CbcBlockCipher)
+ ? ((CbcBlockCipher)cipher).GetUnderlyingCipher()
+ : cipher;
+
+ c.ProcessBlock(buf.AsSpan(blockSize), output);
+
+ block[..length].CopyTo(output[blockSize..]);
+ }
+ else
+ {
+ Span<byte> lastBlock = stackalloc byte[blockSize];
+
+ IBlockCipher c = (cipher is CbcBlockCipher)
+ ? ((CbcBlockCipher)cipher).GetUnderlyingCipher()
+ : cipher;
+
+ c.ProcessBlock(buf, block);
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ lastBlock[i - blockSize] = (byte)(block[i - blockSize] ^ buf[i]);
+ }
+
+ buf.AsSpan(blockSize, length).CopyTo(block);
+
+ cipher.ProcessBlock(block, output);
+ lastBlock[..length].CopyTo(output[blockSize..]);
+ }
+
+ int offset = bufOff;
+
+ Reset();
+
+ return offset;
+ }
+#endif
}
}
diff --git a/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs b/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs
index 5d2f8cf15..a2d4dcc32 100644
--- a/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs
+++ b/crypto/src/crypto/paddings/PaddedBufferedBlockCipher.cs
@@ -1,6 +1,5 @@
using System;
-using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
@@ -25,8 +24,8 @@ namespace Org.BouncyCastle.Crypto.Paddings
* @param padding the padding type.
*/
public PaddedBufferedBlockCipher(
- IBlockCipher cipher,
- IBlockCipherPadding padding)
+ IBlockCipher cipher,
+ IBlockCipherPadding padding)
{
this.cipher = cipher;
this.padding = padding;
@@ -42,7 +41,9 @@ namespace Org.BouncyCastle.Crypto.Paddings
*/
public PaddedBufferedBlockCipher(
IBlockCipher cipher)
- : this(cipher, new Pkcs7Padding()) { }
+ : this(cipher, new Pkcs7Padding())
+ {
+ }
/**
* initialise the cipher.
@@ -54,8 +55,8 @@ namespace Org.BouncyCastle.Crypto.Paddings
* inappropriate.
*/
public override void Init(
- bool forEncryption,
- ICipherParameters parameters)
+ bool forEncryption,
+ ICipherParameters parameters)
{
this.forEncryption = forEncryption;
@@ -110,8 +111,8 @@ namespace Org.BouncyCastle.Crypto.Paddings
public override int GetUpdateOutputSize(
int length)
{
- int total = length + bufOff;
- int leftOver = total % buf.Length;
+ int total = length + bufOff;
+ int leftOver = total % buf.Length;
if (leftOver == 0)
{
@@ -131,10 +132,7 @@ namespace Org.BouncyCastle.Crypto.Paddings
* @exception DataLengthException if there isn't enough space in out.
* @exception InvalidOperationException if the cipher isn't initialised.
*/
- public override int ProcessByte(
- byte input,
- byte[] output,
- int outOff)
+ public override int ProcessByte(byte input, byte[] output, int outOff)
{
int resultLen = 0;
@@ -149,6 +147,23 @@ namespace Org.BouncyCastle.Crypto.Paddings
return resultLen;
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int ProcessByte(byte input, Span<byte> output)
+ {
+ int resultLen = 0;
+
+ if (bufOff == buf.Length)
+ {
+ resultLen = cipher.ProcessBlock(buf, output);
+ bufOff = 0;
+ }
+
+ buf[bufOff++] = input;
+
+ return resultLen;
+ }
+#endif
+
/**
* process an array of bytes, producing output if necessary.
*
@@ -161,24 +176,17 @@ namespace Org.BouncyCastle.Crypto.Paddings
* @exception DataLengthException if there isn't enough space in out.
* @exception InvalidOperationException if the cipher isn't initialised.
*/
- public override int ProcessBytes(
- byte[] input,
- int inOff,
- int length,
- byte[] output,
- int outOff)
+ public override int ProcessBytes(byte[] input, int inOff, int length, byte[] output, int outOff)
{
if (length < 0)
- {
throw new ArgumentException("Can't have a negative input length!");
- }
int blockSize = GetBlockSize();
int outLength = GetUpdateOutputSize(length);
if (outLength > 0)
{
- Check.OutputLength(output, outOff, outLength, "output buffer too short");
+ Check.OutputLength(output, outOff, outLength, "output buffer too short");
}
int resultLen = 0;
@@ -188,7 +196,7 @@ namespace Org.BouncyCastle.Crypto.Paddings
{
Array.Copy(input, inOff, buf, bufOff, gapLen);
- resultLen += cipher.ProcessBlock(buf, 0, output, outOff);
+ resultLen = cipher.ProcessBlock(buf, 0, output, outOff);
bufOff = 0;
length -= gapLen;
@@ -210,7 +218,46 @@ namespace Org.BouncyCastle.Crypto.Paddings
return resultLen;
}
- /**
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
+ {
+ int blockSize = GetBlockSize();
+ int outLength = GetUpdateOutputSize(input.Length);
+
+ if (outLength > 0)
+ {
+ Check.OutputLength(output, outLength, "output buffer too short");
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.Length - bufOff;
+
+ if (input.Length > gapLen)
+ {
+ input[..gapLen].CopyTo(buf.AsSpan(bufOff));
+
+ resultLen = cipher.ProcessBlock(buf, output);
+
+ bufOff = 0;
+ input = input[gapLen..];
+
+ while (input.Length > buf.Length)
+ {
+ resultLen += cipher.ProcessBlock(input, output[resultLen..]);
+
+ input = input[blockSize..];
+ }
+ }
+
+ input.CopyTo(buf.AsSpan(bufOff));
+
+ bufOff += input.Length;
+
+ return resultLen;
+ }
+#endif
+
+ /**
* Process the last block in the buffer. If the buffer is currently
* full and padding needs to be added a call to doFinal will produce
* 2 * GetBlockSize() bytes.
@@ -224,11 +271,9 @@ namespace Org.BouncyCastle.Crypto.Paddings
* initialised.
* @exception InvalidCipherTextException if padding is expected and not found.
*/
- public override int DoFinal(
- byte[] output,
- int outOff)
- {
- int blockSize = cipher.GetBlockSize();
+ public override int DoFinal(byte[] output, int outOff)
+ {
+ int blockSize = cipher.GetBlockSize();
int resultLen = 0;
if (forEncryption)
@@ -280,6 +325,60 @@ namespace Org.BouncyCastle.Crypto.Paddings
return resultLen;
}
- }
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int DoFinal(Span<byte> output)
+ {
+ int blockSize = cipher.GetBlockSize();
+ int resultLen = 0;
+
+ if (forEncryption)
+ {
+ if (bufOff == blockSize)
+ {
+ if ((2 * blockSize) > output.Length)
+ {
+ Reset();
+
+ throw new OutputLengthException("output buffer too short");
+ }
+
+ resultLen = cipher.ProcessBlock(buf, output);
+ bufOff = 0;
+ }
+
+ padding.AddPadding(buf, bufOff);
+
+ resultLen += cipher.ProcessBlock(buf, output[resultLen..]);
+
+ Reset();
+ }
+ else
+ {
+ if (bufOff != blockSize)
+ {
+ Reset();
+
+ throw new DataLengthException("last block incomplete in decryption");
+ }
+
+ resultLen = cipher.ProcessBlock(buf, buf);
+ bufOff = 0;
+
+ try
+ {
+ resultLen -= padding.PadCount(buf);
+
+ buf.AsSpan(0, resultLen).CopyTo(output);
+ }
+ finally
+ {
+ Reset();
+ }
+ }
+
+ return resultLen;
+ }
+#endif
+ }
}
|