-
Notifications
You must be signed in to change notification settings - Fork 63
Expand file tree
/
Copy pathCryptographicOperations.cs
More file actions
66 lines (57 loc) · 2.85 KB
/
CryptographicOperations.cs
File metadata and controls
66 lines (57 loc) · 2.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// Source: https://github.com/dotnet/runtime/blob/16b456426dfb5212a24bfb78bfd5d9adfcc95185/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/CryptographicOperations.cs
using System.Runtime.CompilerServices;
#if NETSTANDARD2_1_OR_GREATER
[assembly: TypeForwardedTo(typeof(System.Security.Cryptography.CryptographicOperations))]
#else
namespace System.Security.Cryptography
{
public static class CryptographicOperations
{
/// <summary>
/// Determine the equality of two byte sequences in an amount of time which depends on
/// the length of the sequences, but not the values.
/// </summary>
/// <param name="left">The first buffer to compare.</param>
/// <param name="right">The second buffer to compare.</param>
/// <returns>
/// <c>true</c> if <paramref name="left"/> and <paramref name="right"/> have the same
/// values for <see cref="ReadOnlySpan{T}.Length"/> and the same contents, <c>false</c>
/// otherwise.
/// </returns>
/// <remarks>
/// This method compares two buffers' contents for equality in a manner which does not
/// leak timing information, making it ideal for use within cryptographic routines.
/// This method will short-circuit and return <c>false</c> only if <paramref name="left"/>
/// and <paramref name="right"/> have different lengths.
///
/// Fixed-time behavior is guaranteed in all other cases, including if <paramref name="left"/>
/// and <paramref name="right"/> reference the same address.
/// </remarks>
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
public static bool FixedTimeEquals(ReadOnlySpan<byte> left, ReadOnlySpan<byte> right)
{
// NoOptimization because we want this method to be exactly as non-short-circuiting
// as written.
//
// NoInlining because the NoOptimization would get lost if the method got inlined.
if (left.Length != right.Length)
{
return false;
}
int length = left.Length;
int accum = 0;
for (int i = 0; i < length; i++)
{
accum |= left[i] - right[i];
}
return accum == 0;
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
// NoOptimize to prevent the optimizer from deciding this call is unnecessary
// NoInlining to prevent the inliner from forgetting that the method was no-optimize
public static void ZeroMemory(Span<byte> buffer) => buffer.Clear();
}
}
#endif