Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
Pbkdf2Implementation.cs
Go to the documentation of this file.
1using System;
6
8
9internal static class Pbkdf2Implementation
10{
11 private static readonly bool s_useKeyDerivation = OperatingSystem.IsWindowsVersionAtLeast(6, 2);
12
14
15 public static void Fill(ReadOnlySpan<byte> password, ReadOnlySpan<byte> salt, int iterations, HashAlgorithmName hashAlgorithmName, Span<byte> destination)
16 {
18 {
19 FillKeyDerivation(password, salt, iterations, hashAlgorithmName.Name, destination);
20 }
21 else
22 {
23 FillDeriveKeyPBKDF2(password, salt, iterations, hashAlgorithmName.Name, destination);
24 }
25 }
26
27 private unsafe static void FillKeyDerivation(ReadOnlySpan<byte> password, ReadOnlySpan<byte> salt, int iterations, string hashAlgorithmName, Span<byte> destination)
28 {
29 int hashBlockSize = GetHashBlockSize(hashAlgorithmName);
30 Span<byte> span = default(Span<byte>);
31 ReadOnlySpan<byte> readOnlySpan = default(Span<byte>);
32 int cbSecret;
33 if (password.IsEmpty)
34 {
35 Span<byte> span2 = stackalloc byte[1];
36 readOnlySpan = span2;
37 cbSecret = 0;
38 span = default(Span<byte>);
39 }
40 else if (password.Length <= hashBlockSize)
41 {
42 readOnlySpan = password;
43 cbSecret = password.Length;
44 span = default(Span<byte>);
45 }
46 else
47 {
48 Span<byte> destination2 = stackalloc byte[64];
49 int num = hashAlgorithmName switch
50 {
51 "SHA1" => SHA1.HashData(password, destination2),
52 "SHA256" => SHA256.HashData(password, destination2),
53 "SHA384" => SHA384.HashData(password, destination2),
54 "SHA512" => SHA512.HashData(password, destination2),
55 _ => throw new CryptographicException(),
56 };
57 span = destination2.Slice(0, num);
58 readOnlySpan = span;
59 cbSecret = num;
60 }
61 global::Interop.BCrypt.NTSTATUS nTSTATUS;
63 if (global::Interop.BCrypt.PseudoHandlesSupported)
64 {
65 fixed (byte* pbSecret = readOnlySpan)
66 {
67 nTSTATUS = global::Interop.BCrypt.BCryptGenerateSymmetricKey(817u, out phKey, IntPtr.Zero, 0, pbSecret, cbSecret, 0u);
68 }
69 }
70 else
71 {
72 if (s_pbkdf2AlgorithmHandle == null)
73 {
74 SafeBCryptAlgorithmHandle phAlgorithm;
75 global::Interop.BCrypt.NTSTATUS nTSTATUS2 = global::Interop.BCrypt.BCryptOpenAlgorithmProvider(out phAlgorithm, "PBKDF2", null, global::Interop.BCrypt.BCryptOpenAlgorithmProviderFlags.None);
76 if (nTSTATUS2 != 0)
77 {
78 phAlgorithm.Dispose();
80 throw global::Interop.BCrypt.CreateCryptographicException(nTSTATUS2);
81 }
83 }
84 fixed (byte* pbSecret2 = readOnlySpan)
85 {
86 nTSTATUS = global::Interop.BCrypt.BCryptGenerateSymmetricKey(s_pbkdf2AlgorithmHandle, out phKey, IntPtr.Zero, 0, pbSecret2, cbSecret, 0u);
87 }
88 }
90 if (nTSTATUS != 0)
91 {
92 phKey.Dispose();
93 throw global::Interop.BCrypt.CreateCryptographicException(nTSTATUS);
94 }
95 ulong num2 = (ulong)iterations;
96 using (phKey)
97 {
98 fixed (char* ptr2 = hashAlgorithmName)
99 {
100 fixed (byte* ptr = salt)
101 {
102 fixed (byte* pbDerivedKey = destination)
103 {
104 Span<global::Interop.BCrypt.BCryptBuffer> span3 = stackalloc global::Interop.BCrypt.BCryptBuffer[3];
105 span3[0].BufferType = global::Interop.BCrypt.CngBufferDescriptors.KDF_ITERATION_COUNT;
106 span3[0].pvBuffer = (IntPtr)(&num2);
107 span3[0].cbBuffer = 8;
108 span3[1].BufferType = global::Interop.BCrypt.CngBufferDescriptors.KDF_SALT;
109 span3[1].pvBuffer = (IntPtr)ptr;
110 span3[1].cbBuffer = salt.Length;
111 span3[2].BufferType = global::Interop.BCrypt.CngBufferDescriptors.KDF_HASH_ALGORITHM;
112 span3[2].pvBuffer = (IntPtr)ptr2;
113 span3[2].cbBuffer = checked((hashAlgorithmName.Length + 1) * 2);
114 fixed (global::Interop.BCrypt.BCryptBuffer* ptr3 = span3)
115 {
116 Unsafe.SkipInit(out global::Interop.BCrypt.BCryptBufferDesc bCryptBufferDesc);
117 bCryptBufferDesc.ulVersion = 0;
118 bCryptBufferDesc.cBuffers = span3.Length;
119 bCryptBufferDesc.pBuffers = (IntPtr)ptr3;
120 uint pcbResult;
121 global::Interop.BCrypt.NTSTATUS nTSTATUS3 = global::Interop.BCrypt.BCryptKeyDerivation(phKey, &bCryptBufferDesc, pbDerivedKey, destination.Length, out pcbResult, 0);
122 if (nTSTATUS3 != 0)
123 {
124 throw global::Interop.BCrypt.CreateCryptographicException(nTSTATUS3);
125 }
126 if (destination.Length != pcbResult)
127 {
128 throw new CryptographicException();
129 }
130 }
131 }
132 }
133 }
134 }
135 }
136
137 private unsafe static void FillDeriveKeyPBKDF2(ReadOnlySpan<byte> password, ReadOnlySpan<byte> salt, int iterations, string hashAlgorithmName, Span<byte> destination)
138 {
139 int hashSizeInBytes;
140 SafeBCryptAlgorithmHandle cachedBCryptAlgorithmHandle = global::Interop.BCrypt.BCryptAlgorithmCache.GetCachedBCryptAlgorithmHandle(hashAlgorithmName, global::Interop.BCrypt.BCryptOpenAlgorithmProviderFlags.BCRYPT_ALG_HANDLE_HMAC_FLAG, out hashSizeInBytes);
141 fixed (byte* pbPassword = password)
142 {
143 fixed (byte* pbSalt = salt)
144 {
145 fixed (byte* pbDerivedKey = destination)
146 {
147 global::Interop.BCrypt.NTSTATUS nTSTATUS = global::Interop.BCrypt.BCryptDeriveKeyPBKDF2(cachedBCryptAlgorithmHandle, pbPassword, password.Length, pbSalt, salt.Length, (ulong)iterations, pbDerivedKey, destination.Length, 0u);
148 if (nTSTATUS != 0)
149 {
150 throw global::Interop.BCrypt.CreateCryptographicException(nTSTATUS);
151 }
152 }
153 }
154 }
155 }
156
157 private static int GetHashBlockSize(string hashAlgorithmName)
158 {
159 switch (hashAlgorithmName)
160 {
161 case "SHA1":
162 case "SHA256":
163 return 64;
164 case "SHA384":
165 case "SHA512":
166 return 128;
167 default:
168 throw new CryptographicException();
169 }
170 }
171}
static SafeBCryptAlgorithmHandle s_pbkdf2AlgorithmHandle
static int GetHashBlockSize(string hashAlgorithmName)
static void Fill(ReadOnlySpan< byte > password, ReadOnlySpan< byte > salt, int iterations, HashAlgorithmName hashAlgorithmName, Span< byte > destination)
static unsafe void FillDeriveKeyPBKDF2(ReadOnlySpan< byte > password, ReadOnlySpan< byte > salt, int iterations, string hashAlgorithmName, Span< byte > destination)
static unsafe void FillKeyDerivation(ReadOnlySpan< byte > password, ReadOnlySpan< byte > salt, int iterations, string hashAlgorithmName, Span< byte > destination)
static bool IsWindowsVersionAtLeast(int major, int minor=0, int build=0, int revision=0)
static byte[] HashData(byte[] source)
Definition SHA1.cs:66
static byte[] HashData(byte[] source)
Definition SHA256.cs:66
static byte[] HashData(byte[] source)
Definition SHA384.cs:66
static byte[] HashData(byte[] source)
Definition SHA512.cs:66
static int CompareExchange(ref int location1, int value, int comparand)
static readonly IntPtr Zero
Definition IntPtr.cs:18
Span< T > Slice(int start)
Definition Span.cs:271