diff --git a/crypto/src/crypto/paddings/BlockCipherPadding.cs b/crypto/src/crypto/paddings/BlockCipherPadding.cs
index 33a5f9f0f..235b61886 100644
--- a/crypto/src/crypto/paddings/BlockCipherPadding.cs
+++ b/crypto/src/crypto/paddings/BlockCipherPadding.cs
@@ -1,43 +1,43 @@
using System;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Paddings
{
- /**
- * Block cipher padders are expected to conform to this interface
- */
+ /// <summary>Block cipher padders are expected to conform to this interface.</summary>
public interface IBlockCipherPadding
{
- /**
- * Initialise the padder.
- *
- * @param param parameters, if any required.
- */
+ /// <summary>Initialise the padder.</summary>
+ /// <param name="random">A source of randomness, if any required.</param>
void Init(SecureRandom random);
- //throws ArgumentException;
- /**
- * Return the name of the algorithm the cipher implements.
- *
- * @return the name of the algorithm the cipher implements.
- */
+ /// <summary>The name of the algorithm this padder implements.</summary>
string PaddingName { get; }
- /**
- * add the pad bytes to the passed in block, returning the
- * number of bytes added.
- */
+ /// <summary>Add padding to the passed in block.</summary>
+ /// <param name="input">the block to add padding to.</param>
+ /// <param name="inOff">the offset into the block the padding is to start at.</param>
+ /// <returns>the number of bytes of padding added.</returns>
int AddPadding(byte[] input, int inOff);
- /**
- * return the number of pad bytes present in the block.
- * @exception InvalidCipherTextException if the padding is badly formed
- * or invalid.
- */
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ /// <summary>Add padding to the passed in block.</summary>
+ /// <param name="block">the block to add padding to.</param>
+ /// <param name="position">the offset into the block the padding is to start at.</param>
+ /// <returns>the number of bytes of padding added.</returns>
+ int AddPadding(Span<byte> block, int position);
+#endif
+
+ /// <summary>Determine the length of padding present in the passed in block.</summary>
+ /// <param name="input">the block to check padding for.</param>
+ /// <returns>the number of bytes of padding present.</returns>
int PadCount(byte[] input);
- //throws InvalidCipherTextException;
- }
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ /// <summary>Determine the length of padding present in the passed in block.</summary>
+ /// <param name="block">the block to check padding for.</param>
+ /// <returns>the number of bytes of padding present.</returns>
+ int PadCount(ReadOnlySpan<byte> block);
+#endif
+ }
}
diff --git a/crypto/src/crypto/paddings/ISO10126d2Padding.cs b/crypto/src/crypto/paddings/ISO10126d2Padding.cs
index 92845f165..317b5db8c 100644
--- a/crypto/src/crypto/paddings/ISO10126d2Padding.cs
+++ b/crypto/src/crypto/paddings/ISO10126d2Padding.cs
@@ -1,7 +1,6 @@
using System;
-using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Paddings
{
@@ -35,42 +34,56 @@ namespace Org.BouncyCastle.Crypto.Paddings
get { return "ISO10126-2"; }
}
- /**
- * add the pad bytes to the passed in block, returning the
- * number of bytes added.
- */
- public int AddPadding(
- byte[] input,
- int inOff)
+ public int AddPadding(byte[] input, int inOff)
{
- byte code = (byte)(input.Length - inOff);
-
- while (inOff < (input.Length - 1))
+ int count = input.Length - inOff;
+ if (count > 1)
{
- input[inOff] = (byte)random.NextInt();
- inOff++;
+ random.NextBytes(input, inOff, count - 1);
}
+ input[input.Length - 1] = (byte)count;
- input[inOff] = code;
+ return count;
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int AddPadding(Span<byte> block, int position)
+ {
+ int count = block.Length - position;
+ if (count > 1)
+ {
+ random.NextBytes(block[position..(block.Length - 1)]);
+ }
+ block[block.Length - 1] = (byte)count;
- return code;
+ return count;
}
+#endif
- /**
- * return the number of pad bytes present in the block.
- */
public int PadCount(byte[] input)
{
int count = input[input.Length -1];
int position = input.Length - count;
- // constant time version
int failed = (position | (count - 1)) >> 31;
+ if (failed != 0)
+ throw new InvalidCipherTextException("pad block corrupted");
+ return count;
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int PadCount(ReadOnlySpan<byte> block)
+ {
+ int count = block[block.Length - 1];
+ int position = block.Length - count;
+
+ int failed = (position | (count - 1)) >> 31;
if (failed != 0)
throw new InvalidCipherTextException("pad block corrupted");
return count;
}
+#endif
}
}
diff --git a/crypto/src/crypto/paddings/ISO7816d4Padding.cs b/crypto/src/crypto/paddings/ISO7816d4Padding.cs
index 533b9d421..7b1834626 100644
--- a/crypto/src/crypto/paddings/ISO7816d4Padding.cs
+++ b/crypto/src/crypto/paddings/ISO7816d4Padding.cs
@@ -33,32 +33,30 @@ namespace Org.BouncyCastle.Crypto.Paddings
get { return "ISO7816-4"; }
}
- /**
- * add the pad bytes to the passed in block, returning the
- * number of bytes added.
- */
- public int AddPadding(
- byte[] input,
- int inOff)
+ public int AddPadding(byte[] input, int inOff)
{
- int added = (input.Length - inOff);
-
- input[inOff]= (byte) 0x80;
- inOff ++;
+ int count = input.Length - inOff;
- while (inOff < input.Length)
+ input[inOff]= 0x80;
+ while (++inOff < input.Length)
{
- input[inOff] = (byte) 0;
- inOff++;
+ input[inOff] = 0x00;
}
- return added;
+ return count;
}
- /**
- * return the number of pad bytes present in the block.
- */
- public int PadCount(byte[] input)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int AddPadding(Span<byte> block, int position)
+ {
+ int count = block.Length - position;
+ block[position++] = 0x80;
+ block[position..].Fill(0x00);
+ return count;
+ }
+#endif
+
+ public int PadCount(byte[] input)
{
int position = -1, still00Mask = -1;
int i = input.Length;
@@ -67,7 +65,7 @@ namespace Org.BouncyCastle.Crypto.Paddings
int next = input[i];
int match00Mask = ((next ^ 0x00) - 1) >> 31;
int match80Mask = ((next ^ 0x80) - 1) >> 31;
- position ^= (i ^ position) & (still00Mask & match80Mask);
+ position ^= (i ^ position) & still00Mask & match80Mask;
still00Mask &= match00Mask;
}
if (position < 0)
@@ -75,5 +73,25 @@ namespace Org.BouncyCastle.Crypto.Paddings
return input.Length - position;
}
- }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int PadCount(ReadOnlySpan<byte> block)
+ {
+ int position = -1, still00Mask = -1;
+ int i = block.Length;
+ while (--i >= 0)
+ {
+ int next = block[i];
+ int match00Mask = ((next ^ 0x00) - 1) >> 31;
+ int match80Mask = ((next ^ 0x80) - 1) >> 31;
+ position ^= (i ^ position) & still00Mask & match80Mask;
+ still00Mask &= match00Mask;
+ }
+ if (position < 0)
+ throw new InvalidCipherTextException("pad block corrupted");
+
+ return block.Length - position;
+ }
+#endif
+ }
}
diff --git a/crypto/src/crypto/paddings/Pkcs7Padding.cs b/crypto/src/crypto/paddings/Pkcs7Padding.cs
index 4c192fcdf..46d97c9eb 100644
--- a/crypto/src/crypto/paddings/Pkcs7Padding.cs
+++ b/crypto/src/crypto/paddings/Pkcs7Padding.cs
@@ -32,43 +32,63 @@ namespace Org.BouncyCastle.Crypto.Paddings
get { return "PKCS7"; }
}
- /**
- * add the pad bytes to the passed in block, returning the
- * number of bytes added.
- */
- public int AddPadding(
- byte[] input,
- int inOff)
+ public int AddPadding(byte[] input, int inOff)
{
- byte code = (byte)(input.Length - inOff);
+ int count = input.Length - inOff;
+ byte padValue = (byte)count;
while (inOff < input.Length)
{
- input[inOff] = code;
- inOff++;
+ input[inOff++] = padValue;
}
- return code;
+ return count;
}
- /**
- * return the number of pad bytes present in the block.
- */
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int AddPadding(Span<byte> block, int position)
+ {
+ int count = block.Length - position;
+ byte padValue = (byte)count;
+ block[position..].Fill(padValue);
+ return count;
+ }
+#endif
+
public int PadCount(byte[] input)
{
- byte countAsByte = input[input.Length - 1];
- int count = countAsByte;
+ byte padValue = input[input.Length - 1];
+ int count = padValue;
int position = input.Length - count;
int failed = (position | (count - 1)) >> 31;
for (int i = 0; i < input.Length; ++i)
{
- failed |= (input[i] ^ countAsByte) & ~((i - position) >> 31);
+ failed |= (input[i] ^ padValue) & ~((i - position) >> 31);
+ }
+ if (failed != 0)
+ throw new InvalidCipherTextException("pad block corrupted");
+
+ return count;
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int PadCount(ReadOnlySpan<byte> block)
+ {
+ byte padValue = block[block.Length - 1];
+ int count = padValue;
+ int position = block.Length - count;
+
+ int failed = (position | (count - 1)) >> 31;
+ for (int i = 0; i < block.Length; ++i)
+ {
+ failed |= (block[i] ^ padValue) & ~((i - position) >> 31);
}
if (failed != 0)
throw new InvalidCipherTextException("pad block corrupted");
return count;
}
+#endif
}
}
diff --git a/crypto/src/crypto/paddings/TbcPadding.cs b/crypto/src/crypto/paddings/TbcPadding.cs
index 8034dc8ba..b54c5f4d0 100644
--- a/crypto/src/crypto/paddings/TbcPadding.cs
+++ b/crypto/src/crypto/paddings/TbcPadding.cs
@@ -1,5 +1,5 @@
using System;
-using Org.BouncyCastle.Crypto;
+
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Paddings
@@ -30,39 +30,44 @@ namespace Org.BouncyCastle.Crypto.Paddings
// nothing to do.
}
- /// <summary> add the pad bytes to the passed in block, returning the
- /// number of bytes added.
- /// <p>
- /// Note: this assumes that the last block of plain text is always
- /// passed to it inside in. i.e. if inOff is zero, indicating the
- /// entire block is to be overwritten with padding the value of in
- /// should be the same as the last block of plain text.
- /// </p>
- /// </summary>
+ /// <summary> add the pad bytes to the passed in block, returning the number of bytes added.</summary>
+ /// <remarks>
+ /// This assumes that the last block of plain text is always passed to it inside <paramref name="input"/>.
+ /// i.e. if <paramref name="inOff"/> is zero, indicating the padding will fill the entire block,the value of
+ /// <paramref name="input"/> should be the same as the last block of plain text.
+ /// </remarks>
public virtual int AddPadding(byte[] input, int inOff)
{
int count = input.Length - inOff;
- byte code;
-
- if (inOff > 0)
- {
- code = (byte)((input[inOff - 1] & 0x01) == 0?0xff:0x00);
- }
- else
- {
- code = (byte)((input[input.Length - 1] & 0x01) == 0?0xff:0x00);
- }
+ byte lastByte = inOff > 0 ? input[inOff - 1] : input[input.Length - 1];
+ byte padValue = (byte)((lastByte & 1) - 1);
while (inOff < input.Length)
{
- input[inOff] = code;
- inOff++;
+ input[inOff++] = padValue;
}
return count;
}
- /// <summary> return the number of pad bytes present in the block.</summary>
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ /// <summary> add the pad bytes to the passed in block, returning the number of bytes added.</summary>
+ /// <remarks>
+ /// This assumes that the last block of plain text is always passed to it inside <paramref name="block"/>.
+ /// i.e. if <paramref name="position"/> is zero, indicating the padding will fill the entire block,the value of
+ /// <paramref name="block"/> should be the same as the last block of plain text.
+ /// </remarks>
+ public virtual int AddPadding(Span<byte> block, int position)
+ {
+ byte lastByte = position > 0 ? block[position - 1] : block[block.Length - 1];
+ byte padValue = (byte)((lastByte & 1) - 1);
+
+ var padding = block[position..];
+ padding.Fill(padValue);
+ return padding.Length;
+ }
+#endif
+
public virtual int PadCount(byte[] input)
{
int i = input.Length;
@@ -76,5 +81,21 @@ namespace Org.BouncyCastle.Crypto.Paddings
}
return count;
}
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public virtual int PadCount(ReadOnlySpan<byte> block)
+ {
+ int i = block.Length;
+ int code = block[--i], count = 1, countingMask = -1;
+ while (--i >= 0)
+ {
+ int next = block[i];
+ int matchMask = ((next ^ code) - 1) >> 31;
+ countingMask &= matchMask;
+ count -= countingMask;
+ }
+ return count;
+ }
+#endif
}
}
diff --git a/crypto/src/crypto/paddings/X923Padding.cs b/crypto/src/crypto/paddings/X923Padding.cs
index fc9668116..12338aa04 100644
--- a/crypto/src/crypto/paddings/X923Padding.cs
+++ b/crypto/src/crypto/paddings/X923Padding.cs
@@ -1,7 +1,7 @@
using System;
-using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Paddings
{
@@ -35,37 +35,45 @@ namespace Org.BouncyCastle.Crypto.Paddings
get { return "X9.23"; }
}
- /**
- * add the pad bytes to the passed in block, returning the
- * number of bytes added.
- */
- public int AddPadding(
- byte[] input,
- int inOff)
+ public int AddPadding(byte[] input, int inOff)
{
- byte code = (byte)(input.Length - inOff);
-
- while (inOff < input.Length - 1)
+ int count = input.Length - inOff;
+ if (count > 1)
{
if (random == null)
{
- input[inOff] = 0;
+ Arrays.Fill(input, inOff, input.Length - 1, 0x00);
}
else
{
- input[inOff] = (byte)random.NextInt();
+ random.NextBytes(input, inOff, count - 1);
}
- inOff++;
}
+ input[input.Length - 1] = (byte)count;
+ return count;
+ }
- input[inOff] = code;
-
- return code;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int AddPadding(Span<byte> block, int position)
+ {
+ int count = block.Length - position;
+ if (count > 1)
+ {
+ var body = block[position..(block.Length - 1)];
+ if (random == null)
+ {
+ body.Fill(0x00);
+ }
+ else
+ {
+ random.NextBytes(body);
+ }
+ }
+ block[block.Length - 1] = (byte)count;
+ return count;
}
+#endif
- /**
- * return the number of pad bytes present in the block.
- */
public int PadCount(byte[] input)
{
int count = input[input.Length - 1];
@@ -77,5 +85,19 @@ namespace Org.BouncyCastle.Crypto.Paddings
return count;
}
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int PadCount(ReadOnlySpan<byte> block)
+ {
+ int count = block[block.Length - 1];
+ int position = block.Length - count;
+
+ int failed = (position | (count - 1)) >> 31;
+ if (failed != 0)
+ throw new InvalidCipherTextException("pad block corrupted");
+
+ return count;
+ }
+#endif
}
}
diff --git a/crypto/src/crypto/paddings/ZeroBytePadding.cs b/crypto/src/crypto/paddings/ZeroBytePadding.cs
index ab5f4a1a3..910fe7154 100644
--- a/crypto/src/crypto/paddings/ZeroBytePadding.cs
+++ b/crypto/src/crypto/paddings/ZeroBytePadding.cs
@@ -1,5 +1,5 @@
using System;
-using Org.BouncyCastle.Crypto;
+
using Org.BouncyCastle.Security;
namespace Org.BouncyCastle.Crypto.Paddings
@@ -28,25 +28,27 @@ namespace Org.BouncyCastle.Crypto.Paddings
// nothing to do.
}
- /// <summary> add the pad bytes to the passed in block, returning the
- /// number of bytes added.
- /// </summary>
- public int AddPadding(
- byte[] input,
- int inOff)
+ public int AddPadding(byte[] input, int inOff)
{
- int added = (input.Length - inOff);
+ int added = input.Length - inOff;
while (inOff < input.Length)
{
- input[inOff] = (byte) 0;
- inOff++;
+ input[inOff++] = 0x00;
}
return added;
}
- /// <summary> return the number of pad bytes present in the block.</summary>
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int AddPadding(Span<byte> block, int position)
+ {
+ int count = block.Length - position;
+ block[position..].Fill(0x00);
+ return count;
+ }
+#endif
+
public int PadCount(byte[] input)
{
int count = 0, still00Mask = -1;
@@ -60,5 +62,21 @@ namespace Org.BouncyCastle.Crypto.Paddings
}
return count;
}
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int PadCount(ReadOnlySpan<byte> block)
+ {
+ int count = 0, still00Mask = -1;
+ int i = block.Length;
+ while (--i >= 0)
+ {
+ int next = block[i];
+ int match00Mask = ((next ^ 0x00) - 1) >> 31;
+ still00Mask &= match00Mask;
+ count -= still00Mask;
+ }
+ return count;
+ }
+#endif
}
}
diff --git a/crypto/test/src/test/BlockCipherTest.cs b/crypto/test/src/test/BlockCipherTest.cs
index d0e5e20b3..e57a8ad09 100644
--- a/crypto/test/src/test/BlockCipherTest.cs
+++ b/crypto/test/src/test/BlockCipherTest.cs
@@ -79,11 +79,11 @@ namespace Org.BouncyCastle.Tests
"DES/CBC/PKCS5Padding",
"60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122afdc70484fb9c0232",
"DES/CBC/ISO10126Padding",
- "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122a980639850a2cc3e8",
+ "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122aee404f971826fd3b",
"DES/CBC/ISO7816-4Padding",
"60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122a1f80b9b0f1be49ac",
"DES/CBC/X9.23Padding",
- "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122a980639850a2cc3e8",
+ "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122aee404f971826fd3b",
"DESede/CBC/PKCS7Padding",
"4d3d7931875cf25593dc402298add8b914761e4936c9585ae22b2c1441169231a41e40695f1cff84",
"SKIPJACK/CBC/PKCS7Padding",
@@ -103,9 +103,9 @@ namespace Org.BouncyCastle.Tests
"IDEA/CBC/PKCS7Padding",
"30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d9e584751325ef7c32",
"IDEA/CBC/ISO10126Padding",
- "30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d978b3fd73135f033b",
+ "30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d937be6ee9fe5e35f6",
"IDEA/CBC/X9.23Padding",
- "30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d978b3fd73135f033b",
+ "30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d937be6ee9fe5e35f6",
"AES/CBC/PKCS7Padding",
"cf87f4d8bb9d1abb36cdd9f44ead7d046db2f802d99e1ef0a5940f306079e08389a44c4a8cc1a47cbaee1128da55bbb7",
"AES/CBC/ISO7816-4Padding",
|