DotNETWeekly-io / DotNetWeekly

DotNet weekly newsletter
MIT License
209 stars 3 forks source link

【文章推荐】C# 代码哈希加密汇总 #327

Closed gaufung closed 1 year ago

gaufung commented 1 year ago

https://code-maze.com/dotnet-cryptography-implementations/

gaufung commented 1 year ago

image

数据加密是现在计算机网络的基础,通过加密可以确保我们数据的安全性,那么在 C# 中如何使用这些加密算法呢?

  1. Hash 加密

Hash 加密是一种单向加密,也就是说将一个输入转换到一个特定空间的数据。通常不能进行反向操作,通过这种方法可以判断输入的内容事否一致。通常有三种类别

该算法已经被标记为不安全算法。

var strStreamOne = new MemoryStream(Encoding.UTF8.GetBytes("This is my password! Dont read me!"));
byte[] hashOne;
using (var hasher = MD5.Create())
{
    hashOne = await hasher.ComputeHashAsync(strStreamOne);
}
var hashAsString = Convert.ToHexString(hashOne);
Console.WriteLine("Hash Value:\n" + hashAsString)

通常有 Sha-1, sha2 这样的算法

var strStreamOne = new MemoryStream(Encoding.UTF8.GetBytes("This is my password! Dont read me!"));
byte[] hashOne;
using (var sha256 = SHA256.Create())
{
    hashOne = await sha256.ComputeHashAsync(strStreamOne);
}
var hashAsString = Convert.ToHexString(hashOne);

这是一个需要密钥才能生成的哈希算法

var strStreamOne = new MemoryStream(Encoding.UTF8.GetBytes("This is my password! Dont read me!"));
byte[] hashOne;
byte[] key = Encoding.UTF8.GetBytes("superSecretH4shKey1!");
using (var hmac = new HMACSHA256(key))
{
    hashOne = await hmac.ComputeHashAsync(strStreamOne);
}
var hashAsString = Convert.ToHexString(hashOne);
  1. 对称加密

这是一个可以进行加密和解密的算法,两端使用相同的密钥进行工作,通常使用 AES 算法

var dataStr = "This is corporate research! Dont read me!";
var data = Encoding.UTF8.GetBytes(dataStr);
var key = GenerateAESKey();
var encryptedData = Encrypt(data, key, out var iv);
var encryptedDataAsString = Convert.ToHexString(encryptedData);

public static byte[] Encrypt(byte[] data, byte[] key, out byte[] iv)
{
    using (var aes = Aes.Create())
    {
        aes.Mode = CipherMode.CBC; // better security
        aes.Key = key;
        aes.GenerateIV(); // IV = Initialization Vector

        using (var encryptor = aes.CreateEncryptor())
        {
            iv = aes.IV;
            return encryptor.TransformFinalBlock(data, 0, data.Length);
        }
    }
}

public static byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
{
    using (var aes = Aes.Create())
    {
        aes.Key = key;
        aes.IV = iv;
        aes.Mode = CipherMode.CBC; // same as for encryption

        using (var decryptor = aes.CreateDecryptor())
        {
            return decryptor.TransformFinalBlock(data, 0, data.Length);
        }
    }
}
public static byte[] GenerateAESKey()
{
    var rnd = new RNGCryptoServiceProvider();
    var b = new byte[16];
    rnd.GetNonZeroBytes(b);
    return b;
}
  1. 非对称加密

就是加密方和解密方使用不同的密钥来操作,通常分为公钥和私钥,公钥可以公开,任何人都可以加密。但是只有私钥才能解开,反之亦然,私钥加密的内容,只有公钥才能解开。这样可以保证私钥的安全性。最著名的就是 RSA 算法,这也是 HTTPS 协议的基石。

var dataStr = "This is corporate research! Dont read me!";
var data = Encoding.UTF8.GetBytes(dataStr);
var keyLength = 2048; // size in bits
GenerateKeys(keyLength , out var publicKey, out var privateKey);
var encryptedData = Encrypt(data, publicKey);
var encryptedDataAsString = Convert.ToHexString(encryptedData);
public void GenerateKeys(int keyLength, out RSAParameters publicKey, out RSAParameters privateKey)
{
    using (var rsa = RSA.Create())
    {
        rsa.KeySize = keyLength;
        publicKey = rsa.ExportParameters(includePrivateParameters: false);
        privateKey = rsa.ExportParameters(includePrivateParameters: true);
    }
}
public byte[] Encrypt(byte[] data, RSAParameters publicKey)
{
    using (var rsa = RSA.Create())
    {
        rsa.ImportParameters(publicKey);

        var result = rsa.Encrypt(data, RSAEncryptionPadding.OaepSHA256);
        return result;
    }
}
public byte[] Decrypt(byte[] data, RSAParameters privateKey)
{
    using (var rsa = RSA.Create())
    {
        rsa.ImportParameters(privateKey);
        return rsa.Decrypt(data, RSAEncryptionPadding.OaepSHA256);
    }
}

另外一种是 DSA 算法,用来进行数字签名,因为它只需要校验事否匹配,性能上有优势。

var dsa = DSA.Create();
var dataStr = "This is corporate research! Dont read me!";
var data = Encoding.UTF8.GetBytes(dataStr);
var signedData = Sign(dsa, data);
dsa.Dispose();
public byte[] Sign(DSA dsa, byte[] data)
{
    if(dsa is null)
        throw new NullReferenceException(nameof(dsa));
    var result = dsa.SignData(data, HashAlgorithmName.SHA256);
    return result;
}
public bool VerifySignature(DSA dsa, byte[] data, byte[] signedData)
{
    if (dsa is null)
        throw new NullReferenceException(nameof(dsa));
    return dsa.VerifyData(data, signedData, HashAlgorithmName.SHA256);
}