File: Cng\BCryptUtilTests.cs
Web Access
Project: src\src\DataProtection\Cryptography.Internal\test\Microsoft.AspNetCore.Cryptography.Internal.Tests.csproj (Microsoft.AspNetCore.Cryptography.Internal.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Linq;
using Microsoft.AspNetCore.DataProtection.Test.Shared;
using Microsoft.AspNetCore.InternalTesting;
using Xunit;
 
namespace Microsoft.AspNetCore.Cryptography.Cng;
 
public unsafe class BCryptUtilTests
{
    [ConditionalFact]
    [ConditionalRunTestOnlyOnWindows]
    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.Fail("Buffer was not filled as expected.");
    }
}