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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With