I'm using BouncyCastle (BC) API for C#.
After Hours going through this API hell i figured out how to sign/verify and encrypt/decrypt using CMS with BC. I have to encrypt the symmetric key for the CMSEnvelope with RSA-OAEP (SHA256 + MGF1 with SHA256) as key encryption algorithm. On default BC obviously uses RSA.
In RecipientInfo structure of the CMS envelope I have to use KeyTransRecipientInfo.
I can't figure out how to set the RSA-OAEP-algorithm to the recipientInfo:
//Create Encrypted cms envelope
X509Certificate otherscert = new X509CertificateParser().ReadCertificate(myCertBytes)
CmsEnvelopedDataGenerator envDataGen = new CmsEnvelopedDataGenerator();
envDataGen.AddKeyTransRecipient(othersCert); //setting Cert, but how the key encr. algorithm?
CmsProcessableByteArray sData = new CmsProcessableByteArray(signedData.GetEncoded());
var envData = envDataGen.Generate(sData, CmsEnvelopedDataGenerator.Aes256Cbc); //generate the envelope
Now in the recipientInfo KeyEncryptionAlgOid is 1.2.840.113549.1.1.1 (RSA)
I need it to be 1.2.840.113549.1.1.7 (RSA-OAEP) with the mentioned key encryption parameters.
Any idea how to do that in BC's C#-API?
EDIT:
Now I got the Source from Git and did the following edits. The problem was not just setting the keyEncryptionAlgorithm to the recipient. BC's logic takes the certificates SubjectPublicKeyInfo-algorithm for key encryption.
in CMSEnvelopedGenerator.cs I added
public void AddKeyTransRecipientRsaOaep(
X509Certificate cert, DerObjectIdentifier digest, DerObjectIdentifier mgf1digest, AlgorithmIdentifier pSource = null)
{
if (pSource == null)
{
pSource = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0]));
}
AlgorithmIdentifier hash = new AlgorithmIdentifier(digest, DerNull.Instance);
AlgorithmIdentifier mask = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, mgf1digest);
var rsaOaepParams = new RsaesOaepParameters(hash, mask, pSource);
KeyTransRecipientInfoGenerator ktrig = new KeyTransRecipientInfoGenerator();
ktrig.RecipientCert = cert;
ktrig.AlgorithmId = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdRsaesOaep, rsaOaepParams);
recipientInfoGenerators.Add(ktrig);
}
In KeyTransrecipientInfoGenerator.cs I added
private AlgorithmIdentifier keyEncryptionAlg;
...
internal AlgorithmIdentifier AlgorithmId
{
set
{
keyEncryptionAlg = value;
}
}
...
protected virtual AlgorithmIdentifier AlgorithmDetails
{
get
{
if (keyEncryptionAlg == null)
{
return info.AlgorithmID;
}
else
{
return keyEncryptionAlg;
}
}
}
//In the Generate() method I changed
keyEncryptionAlgorithm = AlgorithmDetails;
//to
AlgorithmIdentifier keyEncryptionAlgorithm;
if (this.keyEncryptionAlg != null)
{
keyEncryptionAlgorithm = this.keyEncryptionAlg;
}
else
{
keyEncryptionAlgorithm = AlgorithmDetails;
}
Now the keyEncryption algorithm and parameters are set correctly and it encrypts without exception:
CmsEnvelopedDataGenerator envDataGen = new CmsEnvelopedDataGenerator();
envDataGen.AddKeyTransRecipientRsaOaep(othersCert, NistObjectIdentifiers.IdSha256, NistObjectIdentifiers.IdSha256);
CmsProcessableByteArray sData = new CmsProcessableByteArray(signedData.GetEncoded());
var envData = envDataGen.Generate(sData, CmsEnvelopedDataGenerator.Aes256Cbc);
Reading the Envelope with BC or NetCore3 works fine. The RecipientInfos are set as intended (keyEncryptionAlgorithm, params).
But Decryption fails on both... :(