密码算法


  加密是用某种方法伪装消息以隐藏内容的过程,即是通过加密算法将明文转换为密文,相反解密是将密文转换为明文的过程。 加密又分为对称加密、非对称加密和哈希(散列函数)加密。

  .Net Framework / .Net Standard 中提供了很多加密算法类,Fireasy 仅仅是将它们集中封装,使用 CryptographyFactory 类的 Create 方法获取相应的 ICryptoProvider 实例。ICryptoProvider 接口是所有加密算法的抽象,它提供加密解密的方法。


1、密码算法工厂

  CryptographyFactory 类用于根据 CryptoAlgorithm 枚举或一个算法名称创建一个 ICryptoProvider 对象,如下所示:

[TestMethod]
public void TestCreateCryptor()
{
    var md5 = CryptographyFactory.Create(CryptoAlgorithm.MD5);
    var des = CryptographyFactory.Create("DES");
}

  另外,CreateSymmetric、CreateAsymmetric 和 CreateHash 方法分别用于创建对称加密、非对称加密和散列哈希的实例,如果使用了非对应的密码算法,则会抛出 不支持 XXX 密码算法 的提示。


2、对称加密

  常见的对称加密算法有:DESAESRC2RC4RijndaelTripleDES,对应的密码类为 SymmetricCryptSymmetricCrypto 类使用时需要指定密钥 CryptKey 和初始化向量 CryptIV,也可以使用默认的数据。各算法 CryptKey 和 CryptIV 的位数如下表:

算法 CryptKey 位数 CryptIV 位数
DES、RC2、Rijndael 8 8
AES 8 -
TripleDES 24 8
RC4 不限 -

  对称加密与解密如下所示:

[TestMethod]
public void TestSymmetricCrypt()
{
    var encrypt = CryptographyFactory.Create(CryptoAlgorithm.DES) as SymmetricCrypto;
    //var encrypt = CryptographyFactory.CreateSymmetric(CryptoAlgorithm.DES);

    encrypt.CryptKey = new byte[] { 34, 44, 56, 123, 34, 56, 78, 75 };
    encrypt.CryptIV = new byte[] { 89, 35, 250, 56, 23, 67, 33, 45 };

    var bytes = encrypt.Encrypt("fireasy", Encoding.Default);
    Console.WriteLine(Encoding.Default.GetString(bytes));
        
    var str = encrypt.Decrypt(bytes, Encoding.Default);
    Console.WriteLine(str);
}

  也可以使用 SetKey 方法指定一个字符串,该字符串将被转换成相应位数的 CryptKey 和 CryptIV,它会根据不同的密码算法进行截断或补齐,不建议使用该方法指定它们,除非加解密都使用 Fireasy 来完成。如下所示:

[TestMethod]
public void TestSymmetricCrypt()
{
    var encrypt = CryptographyFactory.Create(CryptoAlgorithm.DES) as SymmetricCrypto;
    //var encrypt = CryptographyFactory.CreateSymmetric(CryptoAlgorithm.DES);
        
    encrypt.SetKey("faib studio");

    var bytes = encrypt.Encrypt("fireasy", Encoding.Default);
    Console.WriteLine(Encoding.Default.GetString(bytes));
        
    var str = encrypt.Decrypt(bytes, Encoding.Default);
    Console.WriteLine(str);
}

3、非对称加密

  常见的对称加密算法有:DSARSA,对应的密码类为 AsymmetricCryptoAsymmetricCrypto 类使用时设定公钥 PublicKey 和私钥 PrivateKey 两个属性。如下所示:

[TestMethod]
public void TestAsymmetricCrypto()
{
    var encrypt = CryptographyFactory.Create(CryptoAlgorithm.RSA) as AsymmetricCrypto;
    //var encrypt = CryptographyFactory.CreateAsymmetric(CryptoAlgorithm.RSA);
        
    encrypt.PublicKey = "<RSAKeyValue><Modulus>4UdQ4HttFv3wLdm5cQ8zU3u9YjMXVLsJkmG3E/60G7nxNMJ4gBLQiSGfj4ByKBR0Pvyk2HJ4PCVb3csHjgORjmzF2UeNQgu2SiqD1P+6nU1i2eugp4AxAJed91WRXn6dSb3vqTcwi+KaswcngR0/+YJ9szHi/VADsAQtORc3zBU=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
        
    encrypt.PrivateKey = "<RSAKeyValue><Modulus>4UdQ4HttFv3wLdm5cQ8zU3u9YjMXVLsJkmG3E/60G7nxNMJ4gBLQiSGfj4ByKBR0Pvyk2HJ4PCVb3csHjgORjmzF2UeNQgu2SiqD1P+6nU1i2eugp4AxAJed91WRXn6dSb3vqTcwi+KaswcngR0/+YJ9szHi/VADsAQtORc3zBU=</Modulus><Exponent>AQAB</Exponent><P>9YuKs6X7UU+rtQ0NFRAhr1KMbSe/k7L2OuKkNo9NpHUa3bubb2SY0sNACmLVgp7/wOcflSP1lJcH04J2P/gJHQ==</P><Q>6t7eKKSOZJIqWAQZDEr2SsGecKK3dM+1yMwKe78JfwhyQRdAq9rgblqyD4QvSpvn+mTZIlf+2cwgN+m6Pu5VWQ==</Q><DP>YiqUnDf6nspkUnDSTx5w6R/uhmFCxTDiIi6kCjAGkX5D7Gvpu4ITWwe2XbCfvaYFh8CfLsf+kZZECbp5vh9SvQ==</DP><DQ>uCgLVR7Br0WUAfMkmKjmOHNcAcDzy5lZVZn21lRR49MBktvij11M//oJB3WDhyJ7X69XOUB5yNfuoyiWKeXB8Q==</DQ><InverseQ>x9BzXYBzpw2chFdo+pyTDno5KuilsDGkMiwyqnIsb5eyu5XZm3B2hSpPyBmCzpIJE5z6PJRJiKtrpgEJ3unljw==</InverseQ><D>Xqxv6sc0I1N42mwDqOXwdgcsodZC2dL4xNHX9Mk3u+c63SdVKM2/YcIFonMihoGCEO5wAJ6qtOwmXWFzvVT2mBBsZSROl9VKQboWdjLyBb/q81pnR1skolrBVs913eOHxOdBXVl+yIuhOBr83MFsP/pshafnIS5hHoOF7CzHG8E=</D></RSAKeyValue>";

    var bytes = encrypt.Encrypt("fireasy", Encoding.Default);
    Console.WriteLine(Encoding.Default.GetString(bytes));
        
    var str = encrypt.Decrypt(bytes, Encoding.Default);
    Console.WriteLine(str);
}

  PublicKey 和 PrivateKey 可以使用 GeneratePublicKey 和 GeneratePrivateKey 两个方法生成,注意它俩必须在同一个实例里生成。如下所示:

[TestMethod]
public void TestGenerateKeys()
{
    var encrypt = CryptographyFactory.Create(CryptoAlgorithm.RSA) as AsymmetricCrypto;
    //var encrypt = CryptographyFactory.CreateAsymmetric(CryptoAlgorithm.RSA);
        
    var publicKey = encrypt.GeneratePublicKey();
    var privateKey = encrypt.GeneratePrivateKey();
}

  CreateSignature 和 VerifySignature 方法分别用于生成签名和验证签名,在使用之前,需要使用散列哈希函数生成数据。如下所示:

[TestMethod]
public void TestCreateAndVerifySignature()
{
    var encrypt = CryptographyFactory.CreateAsymmetric(CryptoAlgorithm.RSA);

    encrypt.PublicKey = encrypt.GeneratePublicKey();
    encrypt.PrivateKey = encrypt.GeneratePrivateKey();

    var sha1 = CryptographyFactory.CreateHash(CryptoAlgorithm.SHA1);
    var bytes = sha1.Encrypt(Encoding.Default.GetBytes("fireasy"));

    var signatures = encrypt.CreateSignature(bytes, "SHA1");
    var verify = encrypt.VerifySignature(bytes, signatures, "SHA1");
        
    Assert.IsTrue(verify);
}

4、散列哈希

  常见的对称加密算法有:MD5SHA1SHA256SHA384SHA512,对应的密码类为 HashCrypto。如下所示:

[TestMethod]
public void TestHashCrypt()
{
    var encrypt = CryptographyFactory.Create(CryptoAlgorithm.MD5);
    //var encrypt = CryptographyFactory.CreateHash(CryptoAlgorithm.MD5);
        
    var bytes = encrypt.Encrypt("fireasy", Encoding.Default);
    Console.WriteLine(Encoding.Default.GetString(bytes));
}

  HashCrypto 类的 Decrypt 方法将抛出异常。