a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
173 lines
6.0 KiB
C#
173 lines
6.0 KiB
C#
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
|
|
|
|
using System.IO;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using Xunit;
|
|
using Assert = Microsoft.TestCommon.AssertEx;
|
|
|
|
namespace System.Web.Helpers.Test
|
|
{
|
|
/// <summary>
|
|
///This is a test class for CryptoTest and is intended
|
|
///to contain all CryptoTest Unit Tests
|
|
///</summary>
|
|
public class CryptoTest
|
|
{
|
|
[Fact]
|
|
public void SHA256HashTest_ReturnsValidData()
|
|
{
|
|
string data = "foo bar";
|
|
string expected = "FBC1A9F858EA9E177916964BD88C3D37B91A1E84412765E29950777F265C4B75";
|
|
string actual;
|
|
actual = Crypto.SHA256(data);
|
|
Assert.Equal(expected, actual);
|
|
|
|
actual = Crypto.Hash(Encoding.UTF8.GetBytes(data));
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
[Fact]
|
|
public void GenerateSaltTest()
|
|
{
|
|
string salt = Crypto.GenerateSalt();
|
|
salt = Crypto.GenerateSalt(64);
|
|
Assert.Equal(24, Crypto.GenerateSalt().Length);
|
|
Assert.Equal(12, Crypto.GenerateSalt(8).Length);
|
|
Assert.Equal(88, Crypto.GenerateSalt(64).Length);
|
|
Assert.Equal(44, Crypto.GenerateSalt(32).Length);
|
|
}
|
|
|
|
[Fact]
|
|
public void HashPassword_PasswordGeneration()
|
|
{
|
|
// Act - call helper directly
|
|
string generatedHash = Crypto.HashPassword("my-password");
|
|
byte[] salt = new byte[16];
|
|
Buffer.BlockCopy(Convert.FromBase64String(generatedHash), 1, salt, 0, 16); // extract salt from generated hash
|
|
|
|
// Act - perform PBKDF2 directly
|
|
string generatedHash2;
|
|
using (var ms = new MemoryStream())
|
|
{
|
|
using (var bw = new BinaryWriter(ms))
|
|
{
|
|
using (var deriveBytes = new Rfc2898DeriveBytes("my-password", salt, iterations: 1000))
|
|
{
|
|
bw.Write((byte)0x00); // version identifier
|
|
bw.Write(salt); // salt
|
|
bw.Write(deriveBytes.GetBytes(32)); // subkey
|
|
}
|
|
|
|
generatedHash2 = Convert.ToBase64String(ms.ToArray());
|
|
}
|
|
}
|
|
|
|
// Assert
|
|
Assert.Equal(generatedHash2, generatedHash);
|
|
}
|
|
|
|
[Fact]
|
|
public void HashPassword_RoundTripping()
|
|
{
|
|
// Act & assert
|
|
string password = "ImPepper";
|
|
Assert.True(Crypto.VerifyHashedPassword(Crypto.HashPassword(password), password));
|
|
Assert.False(Crypto.VerifyHashedPassword(Crypto.HashPassword(password), "ImSalt"));
|
|
Assert.False(Crypto.VerifyHashedPassword(Crypto.HashPassword("Impepper"), password));
|
|
}
|
|
|
|
[Fact]
|
|
public void VerifyHashedPassword_CorrectPassword_ReturnsTrue()
|
|
{
|
|
// Arrange
|
|
string hashedPassword = "ALyuoraY/cIWD1hjo+K81/pf83qo6Q6T+UBYcXN9P3A9WHLvEY10f+lwW5qPG6h9xw=="; // this is for 'my-password'
|
|
|
|
// Act
|
|
bool retVal = Crypto.VerifyHashedPassword(hashedPassword, "my-password");
|
|
|
|
// Assert
|
|
Assert.True(retVal);
|
|
}
|
|
|
|
[Fact]
|
|
public void VerifyHashedPassword_IncorrectPassword_ReturnsFalse()
|
|
{
|
|
// Arrange
|
|
string hashedPassword = "ALyuoraY/cIWD1hjo+K81/pf83qo6Q6T+UBYcXN9P3A9WHLvEY10f+lwW5qPG6h9xw=="; // this is for 'my-password'
|
|
|
|
// Act
|
|
bool retVal = Crypto.VerifyHashedPassword(hashedPassword, "some-other-password");
|
|
|
|
// Assert
|
|
Assert.False(retVal);
|
|
}
|
|
|
|
[Fact]
|
|
public void VerifyHashedPassword_InvalidPasswordHash_ReturnsFalse()
|
|
{
|
|
// Arrange
|
|
string hashedPassword = "AAECAw=="; // this is an invalid password hash
|
|
|
|
// Act
|
|
bool retVal = Crypto.VerifyHashedPassword(hashedPassword, "hello-world");
|
|
|
|
// Assert
|
|
Assert.False(retVal);
|
|
}
|
|
|
|
[Fact]
|
|
public void MD5HashTest_ReturnsValidData()
|
|
{
|
|
string data = "foo bar";
|
|
string expected = "327B6F07435811239BC47E1544353273";
|
|
string actual;
|
|
actual = Crypto.Hash(data, algorithm: "md5");
|
|
Assert.Equal(expected, actual);
|
|
|
|
actual = Crypto.Hash(Encoding.UTF8.GetBytes(data), algorithm: "MD5");
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
[Fact]
|
|
public void SHA1HashTest_ReturnsValidData()
|
|
{
|
|
string data = "foo bar";
|
|
string expected = "3773DEA65156909838FA6C22825CAFE090FF8030";
|
|
string actual;
|
|
actual = Crypto.SHA1(data);
|
|
Assert.Equal(expected, actual);
|
|
|
|
actual = Crypto.Hash(Encoding.UTF8.GetBytes(data), algorithm: "sha1");
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
[Fact]
|
|
public void SHA1HashTest_WithNull_ThrowsException()
|
|
{
|
|
Assert.Throws<ArgumentNullException>(() => Crypto.SHA1((string)null));
|
|
Assert.Throws<ArgumentNullException>(() => Crypto.Hash((byte[])null, algorithm: "SHa1"));
|
|
}
|
|
|
|
[Fact]
|
|
public void SHA256HashTest_WithNull_ThrowsException()
|
|
{
|
|
Assert.Throws<ArgumentNullException>(() => Crypto.SHA256((string)null));
|
|
Assert.Throws<ArgumentNullException>(() => Crypto.Hash((byte[])null, algorithm: "sHa256"));
|
|
}
|
|
|
|
[Fact]
|
|
public void MD5HashTest_WithNull_ThrowsException()
|
|
{
|
|
Assert.Throws<ArgumentNullException>(() => Crypto.Hash((string)null, algorithm: "mD5"));
|
|
Assert.Throws<ArgumentNullException>(() => Crypto.Hash((byte[])null, algorithm: "mD5"));
|
|
}
|
|
|
|
[Fact]
|
|
public void HashWithUnknownAlg_ThrowsException()
|
|
{
|
|
Assert.Throws<InvalidOperationException>(() => Crypto.Hash("sdflksd", algorithm: "hao"), "The hash algorithm 'hao' is not supported, valid values are: sha256, sha1, md5");
|
|
}
|
|
}
|
|
}
|