在 C# 中重现 Ruby OpenSSL private_encrypt 输出

发布于 2024-10-31 09:17:35 字数 1394 浏览 5 评论 0原文

我有一个简单的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

东风软 2024-11-07 09:17:35

您需要的是一种生成“原始签名”的方法。原始签名通常由 PKCS#1 v1.5 兼容签名格式的模幂组成,但也可以使用其他填充方法。与正常签名操作的区别在于,它执行任何散列,并且 - 在 PKCS#1 v1.5 兼容签名格式的情况下 - 不会围绕散列创建 ASN.1 结构value,用于标识所使用的哈希方法。

这种原始签名格式不是生成签名的标准化方法,应该避免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 不执行任何操作,它只是返回作为其自身签名提供给它的数据。

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.

if (mechanism.Equals("RSA"))
{
    return (new RsaDigestSigner(new NullDigest()));
}

After that the RsaDigestSigner class will use the EncodeBlock method in DigestInfo to generate the PKCS#1 padding. The NullDigest does not do nothing, it just returns the data given to it as signature of itself.

方圜几里 2024-11-07 09:17:35

为什么不使用 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.

热风软妹 2024-11-07 09:17:35

您可以使用私钥进行加密。

这里至少有一个这样做的例子:

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)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文