/// <summary> /// Returns a Secret comprised entirely of random bytes retrieved from /// a cryptographically secure RNG. /// </summary> public static Secret Random(int numBytes) { if (numBytes < 0) { throw Error.Common_ValueMustBeNonNegative(nameof(numBytes)); } if (numBytes == 0) { byte dummy; return(new Secret(&dummy, 0)); } else { // Don't use CNG if we're not on Windows. if (!OSVersionUtil.IsWindows()) { return(new Secret(ManagedGenRandomImpl.Instance.GenRandom(numBytes))); } byte[] bytes = new byte[numBytes]; fixed(byte *pbBytes = bytes) { try { BCryptUtil.GenRandom(pbBytes, (uint)numBytes); return(new Secret(pbBytes, numBytes)); } finally { UnsafeBufferUtil.SecureZeroMemory(pbBytes, numBytes); } } } }
public static ProtectedMemoryBlob Random(int numBytes) { CryptoUtil.Assert(numBytes >= 0, "numBytes >= 0"); if (numBytes == 0) { byte dummy; return(new ProtectedMemoryBlob(&dummy, 0)); } else { // Don't use CNG if we're not on Windows. if (!OSVersionUtil.IsBCryptOnWin7OrLaterAvailable()) { return(new ProtectedMemoryBlob(ManagedGenRandomImpl.Instance.GenRandom(numBytes))); } byte[] bytes = new byte[numBytes]; fixed(byte *pbBytes = bytes) { try { BCryptUtil.GenRandom(pbBytes, (uint)numBytes); return(new ProtectedMemoryBlob(pbBytes, numBytes)); } finally { UnsafeBufferUtil.SecureZeroMemory(pbBytes, numBytes); } } } }
public void GenRandom_PopulatesBuffer() { // Arrange byte[] bytes = new byte[sizeof(Guid) + 6]; bytes[0] = 0x04; // leading canary bytes[1] = 0x10; bytes[2] = 0xE4; bytes[sizeof(Guid) + 3] = 0xEA; // trailing canary bytes[sizeof(Guid) + 4] = 0xF2; bytes[sizeof(Guid) + 5] = 0x6A; fixed(byte *pBytes = &bytes[3]) { for (int i = 0; i < 100; i++) { // Act BCryptUtil.GenRandom(pBytes, (uint)sizeof(Guid)); // Check that the canaries haven't changed Assert.Equal(0x04, bytes[0]); Assert.Equal(0x10, bytes[1]); Assert.Equal(0xE4, bytes[2]); Assert.Equal(0xEA, bytes[sizeof(Guid) + 3]); Assert.Equal(0xF2, bytes[sizeof(Guid) + 4]); Assert.Equal(0x6A, bytes[sizeof(Guid) + 5]); // Check that the buffer was actually filled. // This check will fail once every 2**128 runs, which is insignificant. Guid newGuid = new Guid(bytes.Skip(3).Take(sizeof(Guid)).ToArray()); Assert.NotEqual(Guid.Empty, newGuid); // Check that the first and last bytes of the buffer are not zero, which indicates that they // were in fact filled. This check will fail around 0.8% of the time, so we'll iterate up // to 100 times, which puts the total failure rate at once every 2**700 runs, // which is insignificant. if (bytes[3] != 0x00 && bytes[18] != 0x00) { return; // success! } } } Assert.True(false, "Buffer was not filled as expected."); }
public void GenRandom(byte *pbBuffer, uint cbBuffer) { BCryptUtil.GenRandom(pbBuffer, cbBuffer); }