public static void ChasmSerializer_WriteRead_TreeNodeMap(IChasmSerializer ser) { var node0 = new TreeNode("a", NodeKind.Blob, s_hasher.HashData("abc")); var node1 = new TreeNode("b", NodeKind.Tree, s_hasher.HashData("def")); var node2 = new TreeNode("c", NodeKind.Tree, s_hasher.HashData("hij")); var expected = new TreeNodeMap(node0, node1, node2); using (IMemoryOwner <byte> owner = ser.Serialize(expected)) { TreeNodeMap actual = ser.DeserializeTree(owner.Memory.Span); Assert.Equal(expected, actual); } }
public static void When_check_empty() { var expected = Sha1.Parse(Sha1TestVectors.Empty); // Empty Array singleton Sha1 actual = s_sha1.HashData(Array.Empty <byte>()); Assert.Equal(expected, actual); Assert.Equal(expected.GetHashCode(), actual.GetHashCode()); // Empty Array actual = s_sha1.HashData(new byte[0]); Assert.Equal(expected, actual); Assert.Equal(expected.GetHashCode(), actual.GetHashCode()); // Empty default ArraySegment actual = s_sha1.HashData(default(ArraySegment <byte>)); Assert.Equal(expected, actual); Assert.Equal(expected.GetHashCode(), actual.GetHashCode()); // Empty new ArraySegment actual = s_sha1.HashData(new ArraySegment <byte>(new byte[0], 0, 0)); Assert.Equal(expected, actual); Assert.Equal(expected.GetHashCode(), actual.GetHashCode()); // Empty default Span actual = s_sha1.HashData(default(Span <byte>)); Assert.Equal(expected, actual); Assert.Equal(expected.GetHashCode(), actual.GetHashCode()); // Empty new Span actual = s_sha1.HashData(new Span <byte>(new byte[0], 0, 0)); Assert.Equal(expected, actual); Assert.Equal(expected.GetHashCode(), actual.GetHashCode()); // Empty default ReadOnlySpan actual = s_sha1.HashData(default(ReadOnlySpan <byte>)); Assert.Equal(expected, actual); Assert.Equal(expected.GetHashCode(), actual.GetHashCode()); // Empty new ReadOnlySpan actual = s_sha1.HashData(new ReadOnlySpan <byte>(new byte[0], 0, 0)); Assert.Equal(expected, actual); Assert.Equal(expected.GetHashCode(), actual.GetHashCode()); // Empty String actual = s_sha1.HashData(string.Empty); Assert.Equal(expected, actual); Assert.Equal(expected.GetHashCode(), actual.GetHashCode()); }
public static void TreeId_equality() { var treeId1 = new TreeId(s_hasher.HashData("abc")); var treeId2 = new TreeId(s_hasher.HashData("abc")); var treeId3 = new TreeId(s_hasher.HashData("def")); Assert.True(treeId1 == treeId2); Assert.False(treeId1 != treeId2); Assert.True(treeId1.Equals((object)treeId2)); Assert.Equal(treeId1.Sha1.ToString(), treeId1.ToString()); Assert.Equal(treeId2.Sha1.ToString(), treeId2.ToString()); Assert.Equal(treeId3.Sha1.ToString(), treeId3.ToString()); Assert.Equal(treeId1, treeId2); Assert.Equal(treeId1.GetHashCode(), treeId2.GetHashCode()); Assert.Equal(treeId1.ToString(), treeId2.ToString()); Assert.NotEqual(treeId3, treeId1); Assert.NotEqual(treeId3.GetHashCode(), treeId1.GetHashCode()); Assert.NotEqual(treeId3.ToString(), treeId1.ToString()); }
public static void BlobId_equality() { var blobId1 = new BlobId(s_hasher.HashData("abc")); var blobId2 = new BlobId(s_hasher.HashData("abc")); var blobId3 = new BlobId(s_hasher.HashData("def")); Assert.True(blobId1 == blobId2); Assert.False(blobId1 != blobId2); Assert.True(blobId1.Equals((object)blobId2)); Assert.False(blobId1.Equals(new object())); Assert.Equal(blobId1.Sha1.ToString(), blobId1.ToString()); Assert.Equal(blobId2.Sha1.ToString(), blobId2.ToString()); Assert.Equal(blobId3.Sha1.ToString(), blobId3.ToString()); Assert.Equal(blobId1, blobId2); Assert.Equal(blobId1.GetHashCode(), blobId2.GetHashCode()); Assert.Equal(blobId1.ToString(), blobId2.ToString()); Assert.NotEqual(blobId3, blobId1); Assert.NotEqual(blobId3.GetHashCode(), blobId1.GetHashCode()); Assert.NotEqual(blobId3.ToString(), blobId1.ToString()); }
/// <summary> /// Computes the hash value of the specified input stream and signs the resulting hash value. /// </summary> /// <param name="buffer">The input data for which to compute the hash.</param> /// <returns>The DSA signature for the specified data.</returns> public byte[] SignData(byte[] buffer) { byte[] hashVal = SHA1.HashData(buffer); return(SignHash(hashVal, null)); }
/// <summary> /// Computes the hash value of the specified input stream and signs the resulting hash value. /// </summary> /// <param name="inputStream">The input data for which to compute the hash.</param> /// <returns>The DSA signature for the specified data.</returns> public byte[] SignData(Stream inputStream) { byte[] hashVal = SHA1.HashData(inputStream); return(SignHash(hashVal, null)); }
/// <summary> /// Verifies the specified signature data by comparing it to the signature computed for the specified data. /// </summary> /// <param name="rgbData">The data that was signed.</param> /// <param name="rgbSignature">The signature data to be verified.</param> /// <returns>true if the signature verifies as valid; otherwise, false.</returns> public bool VerifyData(byte[] rgbData, byte[] rgbSignature) { byte[] hashVal = SHA1.HashData(rgbData); return(VerifyHash(hashVal, null, rgbSignature)); }
/// <summary> /// Signs a byte array from the specified start point to the specified end point. /// </summary> /// <param name="buffer">The input data to sign.</param> /// <param name="offset">The offset into the array from which to begin using data.</param> /// <param name="count">The number of bytes in the array to use as data.</param> /// <returns>The DSA signature for the specified data.</returns> public byte[] SignData(byte[] buffer, int offset, int count) { byte[] hashVal = SHA1.HashData(new ReadOnlySpan <byte>(buffer, offset, count)); return(SignHash(hashVal, null)); }
private static unsafe void FillKeyDerivation( ReadOnlySpan <byte> password, ReadOnlySpan <byte> salt, int iterations, string hashAlgorithmName, Span <byte> destination) { SafeBCryptKeyHandle keyHandle; int hashBlockSizeBytes = GetHashBlockSize(hashAlgorithmName); // stackalloc 0 to let compiler know this cannot escape. Span <byte> clearSpan = stackalloc byte[0]; ReadOnlySpan <byte> symmetricKeyMaterial = stackalloc byte[0]; int symmetricKeyMaterialLength; if (password.IsEmpty) { // CNG won't accept a null pointer for the password. symmetricKeyMaterial = stackalloc byte[1]; symmetricKeyMaterialLength = 0; clearSpan = default; } else if (password.Length <= hashBlockSizeBytes) { // Password is small enough to use as-is. symmetricKeyMaterial = password; symmetricKeyMaterialLength = password.Length; clearSpan = default; } else { // RFC 2104: "The key for HMAC can be of any length (keys longer than B bytes are // first hashed using H). // We denote by B the byte-length of such // blocks (B=64 for all the above mentioned examples of hash functions) // // Windows' PBKDF2 will do this up to a point. To ensure we accept arbitrary inputs for // PBKDF2, we do the hashing ourselves. Span <byte> hashBuffer = stackalloc byte[512 / 8]; // 64 bytes is SHA512, the largest digest handled. int hashBufferSize; switch (hashAlgorithmName) { case HashAlgorithmNames.SHA1: hashBufferSize = SHA1.HashData(password, hashBuffer); break; case HashAlgorithmNames.SHA256: hashBufferSize = SHA256.HashData(password, hashBuffer); break; case HashAlgorithmNames.SHA384: hashBufferSize = SHA384.HashData(password, hashBuffer); break; case HashAlgorithmNames.SHA512: hashBufferSize = SHA512.HashData(password, hashBuffer); break; default: Debug.Fail($"Unexpected hash algorithm '{hashAlgorithmName}'"); throw new CryptographicException(); } clearSpan = hashBuffer.Slice(0, hashBufferSize); symmetricKeyMaterial = clearSpan; symmetricKeyMaterialLength = hashBufferSize; } Debug.Assert(symmetricKeyMaterial.Length > 0); NTSTATUS generateKeyStatus; if (Interop.BCrypt.PseudoHandlesSupported) { fixed(byte *pSymmetricKeyMaterial = symmetricKeyMaterial) { generateKeyStatus = Interop.BCrypt.BCryptGenerateSymmetricKey( (nuint)BCryptAlgPseudoHandle.BCRYPT_PBKDF2_ALG_HANDLE, out keyHandle, pbKeyObject: IntPtr.Zero, cbKeyObject: 0, pSymmetricKeyMaterial, symmetricKeyMaterialLength, dwFlags: 0); } } else { if (s_pbkdf2AlgorithmHandle is null) { NTSTATUS openStatus = Interop.BCrypt.BCryptOpenAlgorithmProvider( out SafeBCryptAlgorithmHandle pbkdf2AlgorithmHandle, Internal.NativeCrypto.BCryptNative.AlgorithmName.Pbkdf2, null, BCryptOpenAlgorithmProviderFlags.None); if (openStatus != NTSTATUS.STATUS_SUCCESS) { pbkdf2AlgorithmHandle.Dispose(); CryptographicOperations.ZeroMemory(clearSpan); throw Interop.BCrypt.CreateCryptographicException(openStatus); } // This might race, and that's okay. Worst case the algorithm is opened // more than once, and the ones that lost will get cleaned up during collection. Interlocked.CompareExchange(ref s_pbkdf2AlgorithmHandle, pbkdf2AlgorithmHandle, null); } fixed(byte *pSymmetricKeyMaterial = symmetricKeyMaterial) { generateKeyStatus = Interop.BCrypt.BCryptGenerateSymmetricKey( s_pbkdf2AlgorithmHandle, out keyHandle, pbKeyObject: IntPtr.Zero, cbKeyObject: 0, pSymmetricKeyMaterial, symmetricKeyMaterialLength, dwFlags: 0); } } CryptographicOperations.ZeroMemory(clearSpan); if (generateKeyStatus != NTSTATUS.STATUS_SUCCESS) { keyHandle.Dispose(); throw Interop.BCrypt.CreateCryptographicException(generateKeyStatus); } Debug.Assert(!keyHandle.IsInvalid); ulong kdfIterations = (ulong)iterations; // Previously asserted to be positive. using (keyHandle) fixed(char *pHashAlgorithmName = hashAlgorithmName) fixed(byte *pSalt = salt) fixed(byte *pDestination = destination) { Span <BCryptBuffer> buffers = stackalloc BCryptBuffer[3]; buffers[0].BufferType = CngBufferDescriptors.KDF_ITERATION_COUNT; buffers[0].pvBuffer = (IntPtr)(&kdfIterations); buffers[0].cbBuffer = sizeof(ulong); buffers[1].BufferType = CngBufferDescriptors.KDF_SALT; buffers[1].pvBuffer = (IntPtr)pSalt; buffers[1].cbBuffer = salt.Length; buffers[2].BufferType = CngBufferDescriptors.KDF_HASH_ALGORITHM; buffers[2].pvBuffer = (IntPtr)pHashAlgorithmName; // C# spec: "A char* value produced by fixing a string instance always points to a null-terminated string" buffers[2].cbBuffer = checked ((hashAlgorithmName.Length + 1) * sizeof(char)); // Add null terminator. fixed(BCryptBuffer *pBuffers = buffers) { Interop.BCrypt.BCryptBufferDesc bufferDesc; bufferDesc.ulVersion = Interop.BCrypt.BCRYPTBUFFER_VERSION; bufferDesc.cBuffers = buffers.Length; bufferDesc.pBuffers = (IntPtr)pBuffers; NTSTATUS deriveStatus = Interop.BCrypt.BCryptKeyDerivation( keyHandle, &bufferDesc, pDestination, destination.Length, out uint resultLength, dwFlags: 0); if (deriveStatus != NTSTATUS.STATUS_SUCCESS) { throw Interop.BCrypt.CreateCryptographicException(deriveStatus); } if (destination.Length != resultLength) { Debug.Fail("PBKDF2 resultLength != destination.Length"); throw new CryptographicException(); } } } }