我有一个简单的 Ruby 脚本,我用它在某些 HTTP header 上执行 private_encrypt 以签署要发送到 ruby REST API 的 Web 请求,该 API 会根据 Base64 编码字符串测试 Base64 编码字符串生成而不是解码 Base64 和解密数据然后测试原始字符串。
我使用的脚本是
require "openssl"
require "base64"
path_to_cert = ARGV[0].dup
plain_text = Base64.decode64(ARGV[1].dup)
private_key = OpenSSL::PKey::RSA.new(File.read(path_to_cert))
puts Base64.encode64(private_key.private_encrypt(plain_text))
输入是 Base64 编码的事实纯粹是由于输入参数中的换行符和空格。
要使用它,我必须使用 System.Diagnostics.Process 处理 ruby 并捕获 StdOut,虽然这不是主要问题并且可以工作,但我想删除对 ruby 的依赖,但我无法使用 C# RsaCryptoServiceProvider 重现输出。
如果我使用 ruby 对“SimpleString”的 private_encrypt 结果进行 Base64 编码,我始终得到 p>
auReJzoPSW3AhzsfT3EH4rD7lc4y2CJ026xIOiV6kjl2OKIj8GnzrPosoJDg\nSHrvLVKrSxYlegYgJRMx+vaAHSAm7RXrZh5An2SnVuO3qITa2TJ78hTc3bAw\nCDm4i9/4qictjxEFfnPRe6 EYCa4b3dnM5moa1eo9zbQPBa1eS6ItRCX4C0G0\n1tJpQsEvuums363eAhTUAYa6yEWuINLPmE0USW6jfFNnsxw8Nv9SnC+ziomb\n/mwlt9dS5/mzKM8yFMH6hdQYLoqc0QpjT+xaZ1ZyJ6dG5MVG h3JtjIVRTOSd\n+pUU/bo+obEHbrftG8u2uJImLSA+/1e8aapHaa3WNg==
使用 .Net 时
RsaCryptoServiceProvider.Encrypt("SimpleString", false)
结果总是不同的输出,因为它是用公钥加密的。
我也试过
RsaCryptoServiceProvider.SignData
虽然这总是产生相同的结果,但它与 ruby 的结果不同。
我可以直接从 .Net 使用一些 CryptoAPI 来实现与 Ruby 相同的结果吗?
最佳答案
您需要的是一种生成“原始签名”的方法。原始签名通常由 PKCS#1 v1.5 兼容签名格式的模幂组成,尽管也可以使用其他填充方法。与普通签名操作的区别在于它不执行任何散列,并且 - 在 PKCS#1 v1.5 兼容签名格式的情况下 - 不围绕散列创建 ASN.1 结构值,用于标识所使用的哈希方法。
这种原始签名格式不是生成签名的标准方法,应该避免。 private_encrypt
主要用于支持已弃用的 SSL 版本,该版本使用 MD5 和 SHA1 哈希值的原始输出的串联来创建用于身份验证的签名。
最后,正如 Siva 所建议的,您可以使用 Bouncy CaSTLe C# 库来创建原始签名格式。由于第二段中给出的原因,大多数更高级别的 API 不直接支持原始签名格式。
[EDIT2] 为此,您需要使用原始的“RSA”功能。
if (mechanism.Equals("RSA"))
{
return (new RsaDigestSigner(new NullDigest()));
}
之后 RsaDigestSigner
类将使用 DigestInfo
中的 EncodeBlock
方法生成 PKCS#1 填充。 NullDigest
不会什么都不做,它只是返回给它的数据作为它自己的签名。
关于c# - 在 C# 中重现 Ruby OpenSSL private_encrypt 输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5579665/