在 C# 中重现 Ruby OpenSSL private_encrypt 输出
我有一个简单的 Ruby 脚本,用于在某些 HTTP 标头上执行 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 编码,我始终得到
auReJzoPSW3AhzsfT3EH4rD7lc4y2CJ026xIOiV6kjl2OKIj8GnzrPosoJDg\nSHrvLVKrSxYlegYgJRMx+vaAHSAm7RXrZh5An2SnVuO3qITa2TJ78hTc3bAw\nCDm4i9/4qictjxEFfnPRe6 EYCa4b3dnM5moa1eo9zbQPBa1eS6ItRCX4C0G0\n1tJpQsEvuums363eAhTUAYa6yEWuINLPmE0USW6jfFNnsxw8Nv9SnC+ziomb\n/mwlt9dS5/mzKM8yFMH6hdQYLoqc0QpjT+xaZ1Zy J6dG5MVG h3JtjIVRTOSd\n+pUU/bo+obEHbrftG8u2uJImLSA+/1e8aapHaa3WNg==
使用 .Net 时,
RsaCryptoServiceProvider.Encrypt("SimpleString", false)
由于使用公钥加密,结果始终是不同的输出。
我也尝试过
RsaCryptoServiceProvider.SignData
,虽然这总是产生相同的结果,但它与 ruby 的结果不同。
我可以直接使用 .Net 中的 CryptoAPI 来实现与 Ruby 相同的结果吗?
I have a simple Ruby script that I am using to do a private_encrypt on some HTTP headers to sign a web request that is to be sent to a ruby REST API, the API tests the Base64 encoded string against a Base64 encoded string it generates rather than decoding the Base64 and decrypting the data then testing the original string.
The script I am using is
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))
The fact that the input is Base64 encoded is purely due to linebreaks and spaces in the input argument.
To use this I am having to shell out to ruby using System.Diagnostics.Process and capture the StdOut, while this isn't a major problem and works I'd like to remove the dependency on ruby but I am unable to reproduce the output using the C# RsaCryptoServiceProvider.
If I Base64 Encode the private_encrypt result of "SimpleString" using ruby i consistently get
auReJzoPSW3AhzsfT3EH4rD7lc4y2CJ026xIOiV6kjl2OKIj8GnzrPosoJDg\nSHrvLVKrSxYlegYgJRMx+vaAHSAm7RXrZh5An2SnVuO3qITa2TJ78hTc3bAw\nCDm4i9/4qictjxEFfnPRe6
EYCa4b3dnM5moa1eo9zbQPBa1eS6ItRCX4C0G0\n1tJpQsEvuums363eAhTUAYa6yEWuINLPmE0USW6jfFNnsxw8Nv9SnC+ziomb\n/mwlt9dS5/mzKM8yFMH6hdQYLoqc0QpjT+xaZ1ZyJ6dG5MVG
h3JtjIVRTOSd\n+pUU/bo+obEHbrftG8u2uJImLSA+/1e8aapHaa3WNg==
When using the .Net
RsaCryptoServiceProvider.Encrypt("SimpleString", false)
The result is always a different output due to the fact it is encrypting with the public key.
I have also tried
RsaCryptoServiceProvider.SignData
and while this always yields the same result, it is different to the result from ruby.
Can I use some CryptoAPI directly from .Net that will allow me to achieve the same result as Ruby?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您需要的是一种生成“原始签名”的方法。原始签名通常由 PKCS#1 v1.5 兼容签名格式的模幂组成,但也可以使用其他填充方法。与正常签名操作的区别在于,它不执行任何散列,并且 - 在 PKCS#1 v1.5 兼容签名格式的情况下 - 不会围绕散列创建 ASN.1 结构value,用于标识所使用的哈希方法。
这种原始签名格式不是生成签名的标准化方法,应该避免。
private_encrypt
主要用于支持已弃用的 SSL 版本,该版本使用 MD5 和 SHA1 哈希值的原始输出串联来创建用于身份验证的签名。最后,正如 Siva 建议的那样,您可以使用 Bouncy Castle C# 库来创建原始签名格式。由于第二段中给出的原因,大多数更高级别的 API 不支持开箱即用的原始签名格式。
[EDIT2] 要实现此目的,您需要使用原始的“RSA”功能。
之后,
RsaDigestSigner
类将使用DigestInfo
中的EncodeBlock
方法生成 PKCS#1 填充。NullDigest
不执行任何操作,它只是返回作为其自身签名提供给它的数据。What you require is a method of generating "raw signatures". Raw signatures generally consist of modular exponentiation of PKCS#1 v1.5 compatible signature formats, although other padding methods may be used as well. The difference with a normal signing operation is that it does not perform any hashing, and - in the case of PKCS#1 v1.5 compatible signature formats - does not create the ASN.1 structure around the hash value, which is used to identify the hashing method used.
This raw signature formats are not a standardized method of generating signatures and should be avoided.
private_encrypt
mainly is used to support deprecated versions of SSL, that uses the method to create a signature for authentication using a concatenation of the raw output of MD5 and SHA1 hash values.Finally, as Siva suggested, you may use the Bouncy Castle C# libraries to create raw signature formats. The raw signature format is not supported out of the box by most higher level API's, for the reasons given in the second paragraph.
[EDIT2] To accomplish this you need to use the raw "RSA" functionality.
After that the
RsaDigestSigner
class will use theEncodeBlock
method inDigestInfo
to generate the PKCS#1 padding. TheNullDigest
does not do nothing, it just returns the data given to it as signature of itself.为什么不使用 Bouncy Castle C#?它提供了完整的加密框架,并且有类从 PEM 文件加载 X509Certificate。
Why don't you use Bouncy Castle C#? It provides complete framework for cryptography and there is class to load X509Certificate from PEM file.
您可以使用私钥进行加密。
这里至少有一个这样做的例子:
http://www. csharpbydesign.com/2008/04/ametry-key-encryption-with.html
请注意在进行加密时使用 PrivateKey 属性(尽管本文引用了解密,但您可以执行以下操作)与加密相同)
You can encrypt using the private key.
Here's at least one example of doing it:
http://www.csharpbydesign.com/2008/04/asymmetric-key-encryption-with.html
Note the use of the PrivateKey property when doing the encryption (although the article references decryption, you can do the same with encryption as well)