Playing back Ruby OpenSSL private_encrypt output in C #

I have a simple Ruby script that I use to make private_encrypt on some HTTP headers to sign a web request that needs to be sent to the Ruby REST API, the API checks the Base64 encoded base64 encoded string it generates, not decrypts Base64 decrypts the data and then tests the original string.

script i use

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 code is Base64 encoded is purely due to the lines and spaces in the input argument.

To use this, I need to lay out the ruby ​​using System.Diagnostics.Process and grab StdOut, although this is not a serious problem and works, I would like to remove the ruby ​​dependency, but I cannot reproduce the output using C # RsaCryptoServiceProvider.

If I Base64 Encodes the result of private_encrypt "SimpleString" using ruby, I sequentially get

auReJzoPSW3AhzsfT3EH4rD7lc4y2CJ026xIOiV6kjl2OKIj8GnzrPosoJDg \ nSHrvLVKrSxYlegYgJRMx + vaAHSAm7RXrZh5An2SnVuO3qITa2TJ78hTc3bAw \ nCDm4i9 / 4qictjxEFfnPRe6 EYCa4b3dnM5moa1eo9zbQPBa1eS6ItRCX4C0G0 \ n1tJpQsEvuums363eAhTUAYa6yEWuINLPmE0USW6jfFNnsxw8Nv9SnC + ziomb \ n / mwlt9dS5 / mzKM8yFMH6hdQYLoqc0QpjT + xaZ1ZyJ6dG5MVG h3JtjIVRTOSd \ n + Püü / Lq + obEHbrftG8u2uJImLSA + / 1e8aapHaa3WNg ==

When using .Net

 RsaCryptoServiceProvider.Encrypt("SimpleString", false) 

The result is always different from the result because it is encrypted with a public key.

I also tried

 RsaCryptoServiceProvider.SignData 

and although this always gives the same result, it differs from the ruby ​​result.

Is it possible to use some CryptoAPI directly from .Net, which will allow me to achieve the same result as Ruby?

+6
source share
3 answers

What you need is a method for generating raw signatures. Raw signatures typically consist of modular exponentiation of compatible PKCS # 1 v1.5 signature formats, although other filling methods may be used. The difference with the usual signature operation is that it does not perform any hashing, and in the case of compatible signature formats PKCS # 1 v1.5, it does not create an ASN.1 structure around the value of the hash function, which is used to identify the hash method used.

These raw signature formats are not a standardized method for generating signatures and should be avoided. private_encrypt is mainly used to support legacy versions of SSL, which uses this method to create a signature for authentication using concatenation of the raw output of the MD5 and SHA1 hash values.

Finally, as Shiva suggested, you can use the Bouncy Castle C # libraries to create raw signature formats. The original signature format is not supported out of the box by most higher-level APIs for the reasons indicated in the second paragraph.

[EDIT2] For this you need to use the raw functions of the "RSA".

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

After that, the RsaDigestSigner class will use the EncodeBlock method in DigestInfo to create the PKCS # 1 add-on. NullDigest does nothing, it simply returns the data given to it as a signature of itself.

+1
source

Why don't you use Bouncy Castle C # ? It provides a complete cryptography structure and there is a class for loading X509Certificate from a PEM file.

0
source

You can encrypt with the private key.

Here is at least one example:

http://www.csharpbydesign.com/2008/04/asymmetric-key-encryption-with.html

Note the use of the PrivateKey property when performing encryption (although decryption is mentioned in the article, you can do the same with encryption)

-1
source

Source: https://habr.com/ru/post/885400/


All Articles