I am writing a function that does a constant time compare of two byte arrays. I want it to be constant time to insure there is no side channel attacks possible.
- Does the code protect against timing attacks or other side channel attacks (of which I could fix)
- Any other suggestions for improvements
Note: This code is called infrequently so performance is not a big deal
/// <summary>
/// Performs a comparison of two identical sized byte arrays.
/// Performs in constant time to prevent timing/side channel attacks
/// </summary>
public int CompareConstantTime(byte[] bytesA, byte[] bytesB)
{
if (bytesA == null)
throw new ArgumentNullException(nameof(bytesA));
if (bytesB == null)
throw new ArgumentNullException(nameof(bytesB));
if (bytesA.Length != bytesB.Length)
throw new ArgumentOutOfRangeException("byte length must be equal");
//only the lest significant bit is used
int aIsLarger = 0;
int bIsLarger = 0;
unchecked
{
for (int i = 0; i < bytesA.Length; i++)
{
int byteA = bytesA[i];
int byteB = bytesB[i];
int byteAIsLarger = ((byteB - byteA) >> 8) & 1;
int byteBIsLarger = ((byteA - byteB) >> 8) & 1;
aIsLarger = aIsLarger | (byteAIsLarger & ~bIsLarger);
bIsLarger = bIsLarger | (byteBIsLarger & ~aIsLarger);
}
//fixes to standard compaire results (0 if A = B, 1 if A > B, -1: B > A)
int result = aIsLarger - bIsLarger;
return result;
}
}
O(N). He is talking about algorithm called constant time string/array comparison. See: security.stackexchange.com/questions/77428/… or crypto.stackexchange.com/questions/30958/… \$\endgroup\$int byteA = bytes[i] & 0xFFto get rid of the first sign extension. The deliberate underflow to negative values in the integer based calculation is probably all right, as internally they will just be registers - although setting the carry bit might still leak the tiniest bit of info. \$\endgroup\$