使用证书在C#中进行加密/解密

26

我在寻找使用证书以C#加密/解密字符串的好例子,但是遇到了麻烦。我已经找到并实现了签名和验证签名的示例(如下所示)。请问是否有人可以为我指点一个简单且类似的加密示例?

private static string Sign(RSACryptoServiceProvider privateKey, string content)
{
    SHA1Managed sha1 = new SHA1Managed();
    UnicodeEncoding  encoding = new UnicodeEncoding ();
    byte[] data = encoding.GetBytes(content);
    byte[] hash = sha1.ComputeHash(data);

    // Sign the hash
    var signature = privateKey.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
    return Convert.ToBase64String(signature);
}

public static bool Verify(RSACryptoServiceProvider publicKey, string content, string hashString)
{
    SHA1Managed sha1 = new SHA1Managed();
    UnicodeEncoding  encoding = new UnicodeEncoding ();
    byte[] data = encoding.GetBytes(content);
    byte[] hash = sha1.ComputeHash(data);
    return publicKey.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), Convert.FromBase64String(hashString));
}

你是在询问如何加载用于RSA的证书,还是已经加载了包含证书密钥的RSACryptoServiceProvider? - Alex K.
你看过这个相关帖子吗? - Axel Kemper
请注意,您只能使用RSA加密少量数据,而不能加密任意长度的文本。 - Alex K.
我已经加载了一个包含私钥/公钥的RSACryptoServiceProvider。经过一些研究,我了解到需要使用更快速的对称加密算法加密数据,然后使用证书进行较慢的非对称加密算法加密密钥。我的问题在于如何将所有在线示例编织成加密/解密函数,就像签名功能一样。 - Ilya
看看这个能否帮到你:https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.xml.encryptedxml.xmlencrsa15url?view=dotnet-plat-ext-3.1 - neo
1个回答

35
根据.NET Framework团队的指导(需要搜索“Cryptography Updates”,附近似乎没有锚点--或者,只需查看代码示例),请注意。
public static byte[] EncryptDataOaepSha1(X509Certificate2 cert, byte[] data)
{
    // GetRSAPublicKey returns an object with an independent lifetime, so it should be
    // handled via a using statement.
    using (RSA rsa = cert.GetRSAPublicKey())
    {
        // OAEP allows for multiple hashing algorithms, what was formermly just "OAEP" is
        // now OAEP-SHA1.
        return rsa.Encrypt(data, RSAEncryptionPadding.OaepSHA1);
    }
}

解密将会是这样的

public static byte[] DecryptDataOaepSha1(X509Certificate2 cert, byte[] data)
{
    // GetRSAPrivateKey returns an object with an independent lifetime, so it should be
    // handled via a using statement.
    using (RSA rsa = cert.GetRSAPrivateKey())
    {
        return rsa.Decrypt(data, RSAEncryptionPadding.OaepSHA1);
    }
}

注意事项:

  • 在.NET Framework 4.6(以及.NET Core 1.0 / .NET Standard 1.3)中添加了RSA.Encrypt(byte[], RSAEncryptionPadding),因此请确保您正在构建具有足够高目标版本的项目。
  • RSA加密主要用于加密对称密钥,而不是实际数据负载,因为它很昂贵并且有大小限制(始终低于密钥大小(以字节为单位),不同的填充模式消耗不同数量的可用空间)。
  • 尽管RSA基类谈论OaepSHA256(等等),但.NET Core中所有提供程序仅支持Pkcs1和OaepSHA1。(OaepSHA256+仅限于RSACng)

2
@Ilya 加密不使用私钥,因此即使您拥有一个私钥(能够)密钥句柄,密钥提供程序可能愿意在没有 PIN 提示的情况下执行操作。而且...我看到示例中的公共/私有部分是颠倒的。哎呀。更新我的答案 :) - bartonjs
1
因此,简要概括一下: 使用GetRSAPublicKey()进行加密,然后使用GetRSAPrivateKey()进行解密=解密时出现"Bad Key"。 使用GetRSAPrivateKey()进行加密,然后使用GetRSAPublicKey()进行解密=解密时出现"Key does not exist."。 - Ilya
1
当您使用已经工作的RSACryptoServiceProvider对象调用“Decrypt”时,是否出现了“Bad Key”错误?如果签名有效但解密无效,则可能是私钥中的权限设置(它仅被创建为签名)。 - bartonjs
我的卡上有三个证书 - 一个带数字签名(80),一个带密钥加密(20),还有一个带有两个密钥用途列表:数字签名,不可否认性(c0)。我假设我需要使用带有“密钥加密(20)”的那个证书? - Ilya
谢谢!快速提示一下,你选择了被认为是不安全的sha1哈希算法(详情见https://crypto.stackexchange.com/questions/48289/how-secure-is-sha1-what-are-the-chances-of-a-real-exploit)。我不是专家,但我认为使用sha256或者sha512会更安全。 - Omer Levi Hevroni
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接