Beispiel #1
0
        /// <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);
 }