【问题标题】:Encrypt / Decrypt in C# using Certificate使用证书在 C# 中加密/解密
【发布时间】:2017-05-26 11:14:51
【问题描述】:

我很难找到一个很好的例子来加密/解密 C# 中的字符串使用证书。我能够找到并实现 signing 和验证签名的示例,如下所示。有人可以指出一个简单的类似加密示例吗?

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 加载了证书中的密钥?
  • 你看过这个related post吗?
  • 请注意,您将/只能使用 RSA 加密少量数据,而不是任意长度的文本。
  • 我已经有一个 RSACryptoServiceProvider 加载了私钥/公钥。根据一些研究,我的理解是,我需要使用更快的对称加密来加密数据,然后使用更慢的非对称加密使用证书来加密密钥。我遇到的麻烦是将所有在线示例组合成一个加密/解密函数,例如用于签名。
  • 看看这是否有帮助:docs.microsoft.com/en-us/dotnet/api/…

标签: c# encryption certificate x509certificate x509


【解决方案1】:

根据.NET Framework team's guidance(必须搜索“密码学更新”,附近似乎没有锚点——或者,只需查看the code samples)。

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);
    }
}

注意事项:

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

【讨论】:

  • 感谢您的回复,但我无法使其正常工作。我有签名示例工作,当我执行原始签名时,它会提示我输入 CAC PIN 号码,一切正常。在您的示例中,由于某种原因加密不会提示我输入 PIN,即使我使用的是私钥,我认为它应该这样做。无论如何,解密时,我得到“密钥不存在”异常。有什么想法吗?
  • @Ilya Encrypting 不使用私钥,因此即使您有私钥(有能力的)密钥句柄,密钥提供者也可能愿意在没有 PIN 提示的情况下进行操作。而且...我看到示例中的公共/私有部分是倒退的。呃。更新我的答案:)
  • 我猜它不会提示输入密码,因为私钥是在 CAC 上编码的,所以如果 CAC 不存在,就无法解密。我按照您更新的示例交换了代码,但现在在解密时出现“Bad key”错误。
  • 所以回顾一下:使用 GetRSAPublicKey() 加密,然后在解密时使用 GetRSAPrivateKey() = "Bad Key" 解密。使用 GetRSAPrivateKey() 加密,然后使用 GetRSAPublicKey() 解密 = "密钥不存在。"解密时。
  • 使用您已经使用的 RSACryptoServiceProvider 对象调用 Decrypt 时,您是否收到 Bad Key 错误?如果 Sign 有效,但 Decrypt 无效,则可能是私钥中的权限设置(仅作为签名创建)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 2012-11-24
  • 2016-10-20
  • 1970-01-01
  • 2014-03-14
相关资源
最近更新 更多