diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs
index bd2a4faea..41e3c3195 100644
--- a/crypto/src/util/Arrays.cs
+++ b/crypto/src/util/Arrays.cs
@@ -1,4 +1,8 @@
using System;
+using System.Runtime.CompilerServices;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+using System.Security.Cryptography;
+#endif
using System.Text;
using Org.BouncyCastle.Math;
@@ -93,34 +97,46 @@ namespace Org.BouncyCastle.Utilities
return true;
}
- /// <summary>
- /// A constant time equals comparison - does not terminate early if
- /// test will fail.
- /// </summary>
- /// <param name="a">first array</param>
- /// <param name="b">second array</param>
- /// <returns>true if arrays equal, false otherwise.</returns>
+ [Obsolete("Use 'FixedTimeEquals' instead")]
public static bool ConstantTimeAreEqual(byte[] a, byte[] b)
{
+ return FixedTimeEquals(a, b);
+ }
+
+ [Obsolete("Use 'FixedTimeEquals' instead")]
+ public static bool ConstantTimeAreEqual(int len, byte[] a, int aOff, byte[] b, int bOff)
+ {
+ return FixedTimeEquals(len, a, aOff, b, bOff);
+ }
+
+#if !(NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER)
+ [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
+#endif
+ public static bool FixedTimeEquals(byte[] a, byte[] b)
+ {
if (null == a || null == b)
return false;
- if (a == b)
- return true;
- int len = System.Math.Min(a.Length, b.Length);
- int nonEqual = a.Length ^ b.Length;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return CryptographicOperations.FixedTimeEquals(a, b);
+#else
+ int len = a.Length;
+ if (len != b.Length)
+ return false;
+
+ int d = 0;
for (int i = 0; i < len; ++i)
{
- nonEqual |= (a[i] ^ b[i]);
- }
- for (int i = len; i < b.Length; ++i)
- {
- nonEqual |= (b[i] ^ ~b[i]);
+ d |= a[i] ^ b[i];
}
- return 0 == nonEqual;
+ return 0 == d;
+#endif
}
- public static bool ConstantTimeAreEqual(int len, byte[] a, int aOff, byte[] b, int bOff)
+#if !(NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER)
+ [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
+#endif
+ public static bool FixedTimeEquals(int len, byte[] a, int aOff, byte[] b, int bOff)
{
if (null == a)
throw new ArgumentNullException("a");
@@ -133,27 +149,28 @@ namespace Org.BouncyCastle.Utilities
if (bOff > (b.Length - len))
throw new IndexOutOfRangeException("'bOff' value invalid for specified length");
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return CryptographicOperations.FixedTimeEquals(a.AsSpan(aOff, len), b.AsSpan(bOff, len));
+#else
int d = 0;
for (int i = 0; i < len; ++i)
{
d |= a[aOff + i] ^ b[bOff + i];
}
return 0 == d;
+#endif
}
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ [Obsolete("Use 'FixedTimeEquals' instead")]
public static bool ConstantTimeAreEqual(Span<byte> a, Span<byte> b)
{
- if (a.Length != b.Length)
- throw new ArgumentException("Spans to compare must have equal length");
-
- int d = 0;
- for (int i = 0, count = a.Length; i < count; ++i)
- {
- d |= a[i] ^ b[i];
- }
- return 0 == d;
+ return CryptographicOperations.FixedTimeEquals(a, b);
+ }
+ public static bool FixedTimeEquals(ReadOnlySpan<byte> a, ReadOnlySpan<byte> b)
+ {
+ return CryptographicOperations.FixedTimeEquals(a, b);
}
#endif
|