Implementing openssl command
openssl rsautl -sign -in rasi.bin -inkey riktest.key -out allkiri.bin
is based on code from answer Converting Openssl signing to .NET6
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers;
using System;
using System.Text;
using System.IO;
using System.Security.Cryptography;
public class Program
{
public static void Main()
{
// For testing purposes a 512 bits key is used.
// In practice, keys >= 2048 bits must be used for security reasons!
string privatePkcs1Pem = @"-----BEGIN RSA PRIVATE KEY-----
MIIBOwIBAAJBANoHbFSEZoOSB9Kxt7t8PoBwmauaODjECHqJgtTU3h4MW5K3857+
04Flc6x6a9xxyvCKS5RtOP2gaOlOVtrph0ECAwEAAQJBALu8LpRr2RWrdV7/tfQT
HIJd8oQnbAe9DIvuwh/fF08IwApOE/iGL+Ded49eoHHu1OXycZhpHavN/sQMnssP
FNECIQDyDIW7V5UUu16ZAeupeQ7zdV6ykVngd0bb3FEn99EchQIhAOaYe3ll211q
SIXVjKHudMn3xe6Vvguc9O7cwCB+gyqNAiEAsr3kk6/de23SMZNlf8TR8Z8eyybj
BAuQ3BMaKzWpyjECIFMR0UFNYTYIyLF12aCoH2h2mtY1GW5jj5TQ72GFUcktAiAf
WWXnts7m8kZWuKjfD0MQiW+w4iAph+51j+wiL3EMAQ==
-----END RSA PRIVATE KEY-----";
byte[] dataToSign = SHA256.HashData(Encoding.UTF8.GetBytes("Data to sign"));
// Import private PKCS#1 key, PEM encoded
PemReader pemReader = new PemReader(new StringReader(privatePkcs1Pem));
AsymmetricKeyParameter privateKeyParameter = ((AsymmetricCipherKeyPair)pemReader.ReadObject()).Private;
// Sign raw data
ISigner signer = new GenericSigner(new Pkcs1Encoding(new RsaBlindedEngine()), new NullDigest());
signer.Init(true, privateKeyParameter);
signer.BlockUpdate(dataToSign, 0, dataToSign.Length);
byte[] signature = signer.GenerateSignature();
Console.WriteLine(Convert.ToHexString(signature));
}
}
BouncyCastle developer comment in Comment https://github.com/bcgit/bc-csharp/issues/621 recommends to use PreHash.For and made hash part of signing.
replacing NullDigest with PreHash.For(new Sha256Digest()) may be useful.
Of course the hashing could also just be made part of the signing by replacing NullDigest with Sha256Digest.
How to implement this? There is no PreHash.For()
method in .NET 9 and in BouncyCastle 2.6.0
It ought to be:
Org.BouncyCastle.Crypto.Digests.Prehash.ForDigest(new Sha256Digest())
For algorithms that normally hash the input, in case you already performed the hashing, a NullDigest
can be used to just return the input without re-applying the hash.
A Prehash
instance acts like a NullDigest
except that it will validate the input is of the expected length for the given digest (and it also can report the correct AlgorithmName
).
EDIT: The part about making hashing part of signing is separate from Prehash suggestion:
byte[] dataToSign = Encoding.UTF8.GetBytes("Data to sign");
//...
ISigner signer = new GenericSigner(new Pkcs1Encoding(new RsaBlindedEngine()), new Sha256Digest());
That's preferable unless there is a reason to separate the hash calculation and signature generation.