1

I'm trying to replicate example from Java in c# with partial success

    CMSEnvelopedDataStreamGenerator gen = new CMSEnvelopedDataStreamGenerator();

    // NOTE: Uses the RECEIVER's PUBLIC encryption key
    gen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(remoteEncryptionCert, rsaesOaepIdentifier()));

    OutputEncryptor encryptor = new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES256_GCM).setProvider(BC).build();

    try (FileOutputStream fileStream = new FileOutputStream(OUTPUT_FILE); OutputStream encryptingOutputStream = gen.open(fileStream, encryptor)) {
                
                //
                // write file
                //
 
                encryptingOutputStream.flush();
            }

I've tried so far

Using System.Security.Cryptography.Pkcs

public byte[] Encrypt(byte[] plainBytes, X509Certificate2 recipientCert)
{
    // create ContentInfo
    ContentInfo plainContent = new ContentInfo(plainBytes);

    // EnvelopedCms represents encrypted data
    Oid encryptAlgoOid = new Oid("2.16.840.1.101.3.4.1.46"); // AES-256-GCM, 
    //Oid encryptAlgoOid = new Oid("2.16.840.1.101.3.4.1.42"); // AES-256-CBC
    EnvelopedCms encryptedData = new EnvelopedCms(plainContent, new AlgorithmIdentifier(encryptAlgoOid));

    // add a recipient
    CmsRecipient recipient = new CmsRecipient(recipientCert);

    // encrypt data with public key of recipient
    encryptedData.Encrypt(recipient); //Throws "Unknown cryptographic algorithm."

    // create PKCS #7 byte array
    byte[] encryptedBytes = encryptedData.Encode();

    // return encrypted data
    return encryptedBytes;
}

error stack trace

Unknown cryptographic algorithm.
   at Internal.Cryptography.Pal.Windows.PkcsPalWindows.EncodeHelpers.CreateCryptMsgHandleToEncode(CmsRecipientCollection recipients, Oid innerContentType, AlgorithmIdentifier contentEncryptionAlgorithm, X509Certificate2Collection originatorCerts, CryptographicAttributeObjectCollection unprotectedAttributes)
   at Internal.Cryptography.Pal.Windows.PkcsPalWindows.Encrypt(CmsRecipientCollection recipients, ContentInfo contentInfo, AlgorithmIdentifier contentEncryptionAlgorithm, X509Certificate2Collection originatorCerts, CryptographicAttributeObjectCollection unprotectedAttributes)
   at System.Security.Cryptography.Pkcs.EnvelopedCms.Encrypt(CmsRecipientCollection recipients)
   at System.Security.Cryptography.Pkcs.EnvelopedCms.Encrypt(CmsRecipient recipient)
   at ConsoleApp1.Program.Encrypt() in Program.cs:line 91

Using Org.BouncyCastle.Cms

public byte[] Encrypt(X509Certificate2 recipientCert)
{
    // file stream
    FileStream fileEncrypted = new FileStream(pathToFile)

    CmsEnvelopedDataStreamGenerator gen = new CmsEnvelopedDataStreamGenerator();
    gen.AddKeyTransRecipient(recipientCert);

    var outEncryptedStream = gen.Open(fileEncrypted, "2.16.840.1.101.3.4.1.46"); 
    // Throws "KeyGenerator 2.16.840.1.101.3.4.1.46 not recognised." CmsEnvelopedDataGenerator doesn't 
    // have named constant for aes256gcm 

    return outEncryptedStream
}

error stack trace

KeyGenerator 2.16.840.1.101.3.4.1.46 not recognised.
   at Org.BouncyCastle.Security.GeneratorUtilities.GetKeyGenerator(String algorithm)
   at Org.BouncyCastle.Cms.CmsEnvelopedDataStreamGenerator.Open(Stream outStream, String encryptionOid)
   at ConsoleApp1.Program.Encrypt() in Program.cs:line 128

I have to make it work in a way so i can encrypt files with c# code and decrypt with java and vice versa.

What i noticed that i if i encrypt file in c# using Aes256CBC i can decrypt it in java, hows that possible? Does that mean that i implemented encryption wrong?

So what are mine options to make this work?

  • 1
    The default padding option in java and c# are different. So you have to specify the padding in c#. – jdweng Aug 29 '20 at 09:45
  • ok, that maybe is another problem, but i cannot even finish encryption using AES256GCM algorithm – Zeljko Marinkovic Aug 29 '20 at 09:52
  • 1
    If the padding is wrong you will get an exception. The encryption class is able to determine bad inputs (inputs that do not match the paramers settings). See : https://stackoverflow.com/questions/21890805/encrypt-aes-with-c-sharp-to-match-java-encryption – jdweng Aug 29 '20 at 11:20
  • Probably is my broken English, put what does it have to do with padding. All methods are encryption methods, Java code is just example of how easy is to implement AES256GCM encryption algorithm while i cannot set it to AES256GCM in c# ``` var outEncryptedStream = gen.Open(fileEncrypted, "2.16.840.1.101.3.4.1.46"); ``` without getting exception. So file contains un-encrypted string "whatever", but im not able to encrypt it with c# using AES256GCM alg. This ``` public Stream Open( Stream outStream, string encryptionOid) ``` outStream is ok, but if i understand Oid is problem – Zeljko Marinkovic Aug 29 '20 at 11:39
  • 1
    There are lots of different parameters setting for the encryption classes. The exact same parameters need to be use for both encryption and decryption – jdweng Aug 29 '20 at 11:59
  • 1
    You are getting an exception when using AES256GCM - mhm let my think which of the 100+ exceptions it is... It's difficult to give help without the complete error stack trace and the point (the line of code) it is pointing to. So kindly edit your post and add the stacktrace, thanks. – Michael Fehr Aug 29 '20 at 14:10
  • @MichaelFehr hope this helps, edited question. Sorry about stack trace, forgot to include it – Zeljko Marinkovic Aug 29 '20 at 19:45

2 Answers2

1

I'm sorry, as per https://github.com/bcgit/bc-csharp/blob/5bd4c8c70f80f1e7ead8e3c73459b78eb93d0ef7/crypto/src/security/GeneratorUtilities.cs it seems to be that AES-256-GCM mode is not available even in actual C# Bouncy Castle:

static GeneratorUtilities()
...
AddKgAlgorithm("AES256",
  "2.16.840.1.101.3.4.42",
  NistObjectIdentifiers.IdAes256Cbc,
  NistObjectIdentifiers.IdAes256Cfb,
  NistObjectIdentifiers.IdAes256Ecb,
  NistObjectIdentifiers.IdAes256Ofb,
  NistObjectIdentifiers.IdAes256Wrap);
...
Michael Fehr
  • 5,827
  • 2
  • 19
  • 40
0

As per Michael Fehr comment AES-256-GCM module is not available in C# Bouncy Castle so we made Java Api and called from our codebase