I was this last Friday and still at an impasse.
When I run this command:
echo -n "Data To Sign" | openssl pkeyutl -sign -inkey path/to/my.pem | openssl base64
via openssl I get the output:
1c284UkFgC6pqyJ+woSU+DiWB4MabWVDVhhUbBrTtF7CkpG8MjY+KkPFsZm9ZNM8vCjZjf...Kw=
I want to reproduce this behavior in C #. The first attempt I made was to use openssl to create a .p12 file from my .pem file. I did this by running two openssl commands:
openssl req -new -key path/to/my.pem -x509 -batch > my.crt openssl pkcs12 -export -in my.crt -inkey path/to/my.pem -out my.p12
and then use the X509Certificate2 and RSACryptoServiceProvider to load the .p12 and sign. Code below:
var dataToSign = "Data To Sign"; var p12 = new X509Certificate2(@"path\to\my.p12",""); var rsa = (RSACryptoServiceProvider)p12.PrivateKey; var signedBytes = rsa.SignData(Encoding.UTF8.GetBytes(dataToSign), "SHA1"); var result = Convert.ToBase64String(signedBytes);
which gives:
B2qM6MTjoZFSbnckezzpXrKFq67vFgsCPYBmaAbKOFmzVQLIU4a+GC6LWTMdNO4...Q0=
Unfortunately, the outputs do not match. After battling this for a while, I decided to take the BouncyCastle route suggested by several answers here on SO. Here is the code I used using this library:
StreamReader sr = new StreamReader(@"path\to\my.pem"); PemReader pr = new PemReader(sr); var pemKeyParams = (RsaPrivateCrtKeyParameters)pr.ReadObject(); var cypherParams = new RsaKeyParameters(true, pemKeyParams.Modulus, pemKeyParams.Exponent); ISigner sig = SignerUtilities.GetSigner("SHA1withRSA"); sig.Init(true, cypherParams); var bytes = Encoding.UTF8.GetBytes("Data To Sign"); sig.BlockUpdate(bytes, 0, bytes.Length); byte[] signature = sig.GenerateSignature(); var result = Convert.ToBase64String(signature);
which also gives:
B2qM6MTjoZFSbnckezzpXrKFq67vFgsCPYBmaAbKOFmzVQLIU4a+GC6LWTMdNO4...Q0=
The BouncyCastle output matches the output date of the C # code that uses its own libraries in the Security namespace, but I want to combine the openssl output. What am I doing wrong?
Versions -
OpenSSL 1.0.1c
.NET 4.0
BouncyCastle 1.7.0
Windows 7
my.pem -
----- BEGIN PRIVATE KEY ----- MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOtk3bYdQsjeG1Xy 2KgF8ecWcPudPLEnV32OIbtA + h2hXQ853ZRsxusopm7vmqtI2 / aVfc2vyw9AGY0U cjqPnyEq7et5oQydo5 + aTEW3PenP9DR3MJ273ipPbrYX + I3XzJ + I6 // k6DO / OAIA JLlXc9iT1pblSrHymFNEkIFiUgj3AgMBAAECgYBtP1Lmwo3MS8jECwEieh / a8D9f h4ozbd7dFqnxDicGuW1HM8PyrsljOmqD8hAGjroHpznLzFqhqU4ye9rH8wAWsKUj Qst / RjyDU3SNscyU / e.g., + ezuawUXafpPUEUTJ0aofdHn9GIVipiIi / 4uaPP / IYtuC U2smep4C2 + geqfTugQJBAP5MTaRQjoYBGKS / Bgd0JB16MHFV6FPDCX3NZ2CLTyZm o8edQZI4SbWoxkJaGqBOqDbz / dSmTLfRNmpAmC + az5sCQQDs + CyDLbs3URvD7ajx JjsJoPbuVmqPBPGmAy / 4Qt3QVp9AWk + 9uckU90DYMqJp5bdGoeokmA65uuEcvqbs yzfVAkEA018FIlE7RjNfEoEdN9DXvBC2d14a0JTLLOAwz1S8I4UpGWCjAjD7Q53X vYs7mogG1jaUg87 + 8cNaYZLzbI5XhQJANyqbajqGQB2Awj8cum81BUvU0K2LhxoW i5hoXXprmynfTyL3N2r99gSNswcuqkqRPT9KfBRuMSzhZUi5IZ05tQJBAKdQ3mJZ 1Vys2nEAXbQD5 / ldi1 + VF / 0t4Z + JxqFBjqtsAoASBN + kSiPAnRl3r175oZ9m9gkd 5YISN0L + WD5Bf4U = ----- END OF PRIVATE KEY -----
For the purposes of this question, I generated a new .pem. The above key does not provide anything important, but I provide it to reproduce my steps above.
Things I've reviewed so far:
* Encoding (ASCII vs UTF8)
* Endianess (-rev for openssl still does not match any encoded result)
* hashalg (I could not find anywhere that "SHA1" was officially the correct hash algorithm, but it seems that others used and tried other options did not help)
* newlines (I believe that -n on echo needs to be on par with libraries, but deleting it did not help)
* Ask for SO (pending results :-))
TIA