【问题标题】:Decrypt string using the pem or pkcs key received in c#使用 c# 中收到的 pem 或 pkcs 密钥解密字符串
【发布时间】:2015-05-01 04:46:21
【问题描述】:

给定 pem 格式的密钥,类似于

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,DE1BB301BDE4BB45

msUEpZKZ0uaOmhGXBPnh2GoNSXyExdeqETd9w71l0G1bk1cCbiV4EOnmR7bcN+OE
(20 lines)
YoIx/E+tFHkt3gQcFhVUNgSOe/5+huXwRwUC5dthPzzZFlDCXHfwfrrBzOSGxZpX
uBs1JxY4qOLRdZVaZlQespForxBTYD6RuHi1UI5lqEW7363VyCLho9QYgGFM0LUi
qbln5WV37PTmayxMfzlGUB2XazwON+WU3obbXuCFXAy96Y6VGzv0lQ==
-----END RSA PRIVATE KEY-----

我尝试使用以下代码解密的加密字符串(使用公钥加密)

TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
des.IV = HextoByte("DE1BB301BDE4BB45");                
des.Padding = PaddingMode.None;
des.Mode = CipherMode.CBC;   
des.Key = Convert.FromBase64String(//Key from above from ms.. to ==);                                                                  
byte[] encrypted = Convert.FromBase64String("");
byte[] decrypted = des.CreateDecryptor().TransformFinalBlock(encrypt, 0, encrypt.Length);
string decryptedString = Encoding.UTF8.GetString(decrypted) 

分配键时导致异常 “指定的密钥不是该算法的有效大小”

密钥是使用生成的(也尝试使用 192)

openssl genrsa -des3 -out Key.pem 2048

公钥是使用

生成的
openssl rsa -in Key.pem -pubout > Key.pub

谁能帮我指出我遗漏了什么或做错了什么?

谢谢

【问题讨论】:

  • 您使用的是哪个版本的 OpenSSH?
  • ssh -v OpenSSH_6.2p2, OSSLShim 0.9.8r 2011 年 12 月 8 日。版本会影响什么吗?
  • 不确定,但拥有版本信息是一个完整的问题。
  • 我什至尝试过使用从 openssl genrsa -des3 -out Key.pem 192 生成的密钥
  • "ms...==" 是序列化和编码的私钥,而不是 DES 密钥!只是为了确保,您是说您没有使用密码加密私钥?

标签: c# encryption rsa


【解决方案1】:

您正在使用带有 3DES 密码的 RSA 密钥。钥匙打错了。

您问题中的私钥已使用 3DES 加密,可能使用了基于密码的加密。您需要密钥才能解密私钥,然后才能将其用于任何事情。

一旦您恢复了 RSA 私钥,您很可能会使用它来解密对称密钥。通常,每条加密消息都将包含一个对称密钥,用接收者的公钥加密。这就是您将使用您恢复的 RSA 私钥解密的内容。

一旦您拥有第二个对称密钥,您就可以使用它来解密实际消息,正如您在问题中所展示的那样。

在伪代码中:

rsaPvtKey = passwordDecrypt(password, encryptedPrivateKey)
contentKey = rsaDecrypt(rsaPvtKey, encryptedContentKey)
message = tripleDesDecrypt(contentKey, encryptedMessage)

原始问题中的代码非常接近。问题是密钥是从密码中导出的,而消息是 base-64 编码的信息。成功解密这将产生一个 PKCS #8 格式的 RSA 私钥,并且 .NET 应该有一个用于加载它的 API。

OpenSSL 密钥派生不是标准的(也不是很好)。您需要查找或编写一些代码,以使用 MD5 哈希算法从您的密码创建 DES-EDE3 密钥。

d0 = md5(password || iv)        /* Hash password and IV */
d1 = md5(d0 || password || iv)  /* Hash first hash, password, and IV */
key = subarray(d0 || d1, 0, 24) /* Take the first 24 bytes of d0 + d1 */

JavaScience code 包含一个函数 GetOpenSSL3deskey 来执行此密钥派生。您可以使用提取的iv、密码、count 1 和miter 2 来调用它。

完成此操作后,将其分配给原始代码中的des.Key。分配给des.Key 的内容应该分配给encrypt。 (这就是DecodeOpenSSLPrivateKey 函数的作用。)当您完成解密时,字节数组decrypted 将包含PKCS #1 的中国剩余定理格式的RSA 私钥。应该有一些 .NET API 来从中构造一个 RSA 私钥。 (请参阅DecodeRSAPrivateKey 函数。)

此 RSA 私钥随后可用于解密其他消息。

【讨论】:

  • 是的,它使用密码加密。你知道如何在 .Net 中使用原生类来做到这一点吗?
  • @user3614386 有很多步骤,每个步骤都有多种方法。使用什么软件加密消息本身?
  • 如果这个密钥是另一种格式,步骤会更少吗?就像它的pk8格式只有几行代码
  • @user3614386 是的,您应该能够使用openssl 解密密钥(如果我记得,请使用不带-<cipher> 选项的pkey 命令);这将消除可能涉及非标准 openssl 加密格式的第一步。消息是否采用 PGP 或 CMS (S/MIME) 等标准格式?
  • Message 是一个简单的字符串,需要在 c# 中解密,在 Java 中使用 pkcs8 格式的密钥加密。 Java 显然可以用几行代码对本地类做到这一点。很惊讶 c# 需要很多行才能做到这一点。我可以使用jensign.com/opensslkey/opensslkey.cs 来做到这一点,但这要经历很多使用各种参数设置 RSA 类的过程。我期待一个带有密码和解密的简单加载密钥。
【解决方案2】:

C# 中 3DES 的最大密钥大小为 192 位。另请参阅 MSDN 文档here

因此,您需要确保 Convert.FromBase64String() 确实返回 24 字节。

还请查看以下问题/答案:

【讨论】:

    猜你喜欢
    • 2012-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-30
    • 1970-01-01
    • 1970-01-01
    • 2015-07-31
    • 1970-01-01
    相关资源
    最近更新 更多