You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
One of my workmates made an XML encryption / decryption process with certificates and CMS in Java using latest Bouncy Castle version.
Our customers want to implement those methods in .NET, so I'm trying to re-create it in C# using BC-CSharp. First, I have an encrypted XML in a stream and trying to decrypt it. The certificates / private keys used for encryption has 256-bit EC keys. The code what I've made so far:
private static Stream InitDecryptInputStream(Stream inputStream, KeystoreManager ksManager)
{
Pkcs12Store ks = KeyStoreUtils.OpenPkcs12Store(ksManager.KeystoreFile, ksManager.KeystorePassword);
CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(inputStream);
RecipientInformationStore recipients = ep.GetRecipientInfos();
IList<RecipientInformation> rec = recipients.GetRecipients();
IEnumerator it = rec.GetEnumerator();
while (it.MoveNext())
{
// no privateKey given, find the key from the keyStore using
// the encryption certificate
RecipientInformation recipient = (RecipientInformation)it.Current;
RecipientID recId = recipient.RecipientID;
if (recipient is KeyTransRecipientInformation || recipient is KeyAgreeRecipientInformation)
{
String info = recId.ToString();
X509Name issuer = null;
BigInteger serialNumber = null;
issuer = recId.Issuer;
serialNumber = recId.SerialNumber;
X509CertificateEntry[] certChain;
AsymmetricCipherKeyPair keyPair = KeyStoreUtils.GetKeyPairByIssuerAndSn(ks, issuer, serialNumber, out certChain);
X509Certificate cert = CertificateUtils.GetCertificate(certChain, issuer, serialNumber, false);
// we have found the crypter key in the keystore
if (cert != null)
{
logger.Info("Recipient cert: " + cert.ToString());
AsymmetricKeyParameter privateKey = null;
// only the given key acceptable
if (ksManager.Certificate != null)
{
if (ksManager.Certificate.Equals(cert))
{
privateKey = ksManager.KeyPair.Private;
}
}
else
{
String certAlias = ks.GetCertificateAlias(cert);
privateKey = ks.GetKey(certAlias).Key;
}
if (privateKey != null)
{
logger.Debug("Decrypting with certificate: " + cert);
CmsTypedStream recData = recipient.GetContentStream(privateKey);
return recData.ContentStream;
}
}
else
{
logger.Debug("No matching certificate found in our keystore for recipientId " + info +
". Serial number in hexadecimal format " + serialNumber.ToString(16));
}
}
else
{
logger.Warn("Unexpected type of recipient: " + recId.GetType());
}
}
throw new KeyException("No acceptable private Key found for decrypting the message");
}
The line CmsTypedStream recData = recipient.GetContentStream(privateKey); throws an exception:
Org.BouncyCastle.Cms.CmsException: couldn't create cipher.
---> Org.BouncyCastle.Security.SecurityUtilityException: Basic Agreement (with KDF) OID not recognised.
at Org.BouncyCastle.Security.AgreementUtilities.GetBasicAgreementWithKdf(DerObjectIdentifier oid, String wrapAlgorithm)
at Org.BouncyCastle.Security.AgreementUtilities.GetBasicAgreementWithKdf(DerObjectIdentifier agreeAlgOid, DerObjectIdentifier wrapAlgOid)
at Org.BouncyCastle.Cms.KeyAgreeRecipientInformation.CalculateAgreedWrapKey(DerObjectIdentifier wrapAlgOid, AsymmetricKeyParameter senderPublicKey, AsymmetricKeyParameter receiverPrivateKey)
at Org.BouncyCastle.Cms.KeyAgreeRecipientInformation.GetSessionKey(AsymmetricKeyParameter receiverPrivateKey)
Debugging through BC-CSharp source code, I've checked the algorithms.
The wrapAlgOid is aes128-wrap (2.16.840.1.101.3.4.1.5), which may not be a problem, but the agreeAlgOid is dhSinglePass-stdDH-sha256kdf-scheme (1.3.132.1.11.1), which exists in SecObjectIdentifiers class, but not mapped in AgreementUtilities class.
Is it possible, that dhSinglePass-stdDH-sha256kdf-scheme key agreement algorithm is not supported in C# yet and was implemented only in BC-Java? Or I should use other way to decrypt that kind of data?
The text was updated successfully, but these errors were encountered:
I see that this OID and other similar ones are not mapped (bc-csharp usually lags bc-java on what features are supported). However I think we already have the underlying implementation so it may be a reasonably simple fix.
I've added dhSinglePass-stdDH-sha256kdf-scheme (along with other similar ones) to the registries. If you are able to build from the latest source code, you could check whether that fixes things for you, or else let me know what else is blocking this for you.
Sorry for the late response. Built the BC-Sharp code from the latest commit.
Now the cipher was created, but when the code reaches this part: CmsTypedStream recData = recipient.GetContentStream(privateKey);
an exception occured.
2024-03-12 10:54:26.8281 | ERROR | Program | Org.BouncyCastle.Cms.CmsException: originator key invalid. ---> Org.BouncyCastle.Crypto.InvalidCipherTextException: checksum failed
at Org.BouncyCastle.Crypto.Engines.Rfc3394WrapEngine.Unwrap(Byte[] input, Int32 inOff, Int32 inLen)
at Org.BouncyCastle.Cms.KeyAgreeRecipientInformation.UnwrapSessionKey(DerObjectIdentifier wrapAlgOid, KeyParameter agreedKey)
at Org.BouncyCastle.Cms.KeyAgreeRecipientInformation.GetSessionKey(AsymmetricKeyParameter receiverPrivateKey)
I still cannot figure out why it fails, because the code finds the corresponding private key from the supplied keystore.
One of my workmates made an XML encryption / decryption process with certificates and CMS in Java using latest Bouncy Castle version.
Our customers want to implement those methods in .NET, so I'm trying to re-create it in C# using BC-CSharp. First, I have an encrypted XML in a stream and trying to decrypt it. The certificates / private keys used for encryption has 256-bit EC keys. The code what I've made so far:
The line
CmsTypedStream recData = recipient.GetContentStream(privateKey);
throws an exception:Debugging through BC-CSharp source code, I've checked the algorithms.
The
wrapAlgOid
isaes128-wrap (2.16.840.1.101.3.4.1.5)
, which may not be a problem, but theagreeAlgOid
isdhSinglePass-stdDH-sha256kdf-scheme (1.3.132.1.11.1)
, which exists inSecObjectIdentifiers
class, but not mapped inAgreementUtilities
class.Is it possible, that
dhSinglePass-stdDH-sha256kdf-scheme
key agreement algorithm is not supported in C# yet and was implemented only in BC-Java? Or I should use other way to decrypt that kind of data?The text was updated successfully, but these errors were encountered: