public static void Mac() { var digest = new Blake2bMac(new PinnedMemory <byte>(new byte[] { 63, 61, 77, 20, 63, 61, 77 }, false)); // This is a common, but could be unsafe example of dealing with strings from a form using text encoding. using var exampleHash = new PinnedMemory <byte>(new byte[digest.GetLength()]); var unsafeCaw = "caw caw caw"; // this is unsafe because string's can't be pinned and are subject to garbage collection, and being written to disk (pagefile). var caw = new PinnedMemory <byte>(Encoding.UTF8.GetBytes(unsafeCaw), false); // this is now safe but ONLY the variable caw, unsafeCaw is STILL exposed. unsafeCaw = string.Empty; // unsafeCaw COULD STILL exposed even tho we set it to empty because this depends on garbage collection getting around to clearing it. digest.UpdateBlock(caw, 0, caw.Length); digest.DoFinal(exampleHash, 0); Console.WriteLine(BitConverter.ToString(exampleHash.ToArray())); // This is a more uncommon but should be safer example of how to use strings with SecureString for input. using var exampleHash2 = new PinnedMemory <byte>(new byte[digest.GetLength()]); var secureCaw = new SecureString(); secureCaw.AppendChar('c'); secureCaw.AppendChar('a'); secureCaw.AppendChar('w'); secureCaw.AppendChar(' '); secureCaw.AppendChar('c'); secureCaw.AppendChar('a'); secureCaw.AppendChar('w'); secureCaw.AppendChar(' '); secureCaw.AppendChar('c'); secureCaw.AppendChar('a'); secureCaw.AppendChar('w'); secureCaw.MakeReadOnly(); using var pinnedCaw = new PinnedMemory <char>(new char[secureCaw.Length]); var cawPointer = Marshal.SecureStringToBSTR(secureCaw); for (var i = 0; i <= secureCaw.Length - 1; i++) { var c = (char)Marshal.ReadByte(cawPointer, i * 2); pinnedCaw[i] = c; } using var pinnedCawBytes = new PinnedMemory <byte>(Encoding.UTF8.GetBytes(pinnedCaw.ToArray()), false); digest.UpdateBlock(pinnedCawBytes, 0, secureCaw.Length); digest.DoFinal(exampleHash2, 0); Console.WriteLine(BitConverter.ToString(exampleHash2.ToArray())); }
private static void Mac() { // This is an example of hashing byte[] using PinnedMemory. This is the best method as it protects bytes during creation of the mac // and not just the output. It will also zero bytes after there written. However, raw byte[] is also accepted as shown in the commented version. var digest = new Blake2bMac(new PinnedMemory <byte>(new byte[] { 63, 61, 77, 20, 63, 61, 77 }, false)); using var exampleHash = new PinnedMemory <byte>(new byte[digest.GetLength()]); // digest.UpdateBlock(new byte[] {63, 61, 77, 20, 63, 61, 77, 20, 63, 61, 77}, 0, 11); // This may be exposed without being pinned. digest.UpdateBlock(new PinnedMemory <byte>(new byte[] { 63, 61, 77, 20, 63, 61, 77, 20, 63, 61, 77 }, false), 0, 11); digest.DoFinal(exampleHash, 0); Console.WriteLine(BitConverter.ToString(exampleHash.ToArray())); }