views:

357

answers:

3

I'm trying to asymetrically encrypt a message of arbitrary length with bouncycastle. (1.4+ with C#)

This is the code I have right now. It is supposed to (but doesn't) generate a CMS message where the data itself is encrypted with AES256 with a random key and the key is encrypted with the public key from keyPair.

keyPair is an RSA-Key (RsaKeyParameters)

public static byte[] Encrypt(byte[] input, AsymmetricCipherKeyPair keyPair)
{
    CmsEnvelopedDataGenerator generator = new CmsEnvelopedDataGenerator();

    // those two lines are certainly wrong.
    // I have no idea what the subKeyID parameter does
    byte[] subKeyId = new byte[] {};
    generator.AddKeyTransRecipient(keyPair.Public, subKeyId);

    CmsProcessableByteArray cmsByteArray = new CmsProcessableByteArray(input);
    CmsEnvelopedData envelopeData = 
      generator.Generate(cmsByteArray, CmsEnvelopedDataGenerator.Aes256Cbc);

    return envelopeData.GetEncoded();
}

What is the subKeyId parameter in the Encrypt method for and what value does it need to have?

A: 

To use AES, it is not enough to use a AsymmetricCipherKeyPair.

You should use a X509 certificate, where the public key is signed by an certificate authority (CA).

the subKeyId is an attribute of the certificate, the subject Key Identifier:

       (X509Certificate) cert.getSubjectUniqueID()

To encrypt a message of artrary length, you should use AES only to exchange a symmetric Keypassword and use this key for symmetric encryption.

mancereus
I just have a RSA-Keypair. So I can't use getSubjectUniqueID() because there is no certificate.
levinalex
Re: "To encrypt a message of artrary length, you should use AES only to exchange a symmetric Keypassword and use this key for symmetric encryption." (I think you mean RSA, AES is a symmetric Algorithm)Isn't that exactly what CMSEnvelopedData is supposed to do?
levinalex
A: 

Look at the function TryKekAlgorithm in the EnvelopedDataTest.cs file of the BouncyCastle source. Instead of doing AddKeyTransRecipient, they are doing AddKekRecipient.

    public static byte[] Encrypt(byte[] input, AsymmetricCipherKeyPair keyPair)
    {
        CmsEnvelopedDataGenerator generator = new CmsEnvelopedDataGenerator();
        DerObjectIdentifier algOid = //initialize

        //Still trying to figure out kekId here.
        byte[] kekId = new byte[] { 1, 2, 3, 4, 5 };
        string keyAlgorithm = ParameterUtilities.GetCanonicalAlgorithmName("AES256");

        generator.AddKekRecipient(keyAlgorithm, keyPair.Public, kekId);

        CmsProcessableByteArray cmsByteArray = new CmsProcessableByteArray(input);
        CmsEnvelopedData envelopeData =
          generator.Generate(cmsByteArray, CmsEnvelopedDataGenerator.Aes256Cbc);

        return envelopeData.GetEncoded();
    }

Edit: I think the kekId is just a unique identifier used to reference the key. Just a way to "name" the key. So you can have a book of keys, and each one has an identifier. When you send an encrypted message, the unencrypted key identifier tells you which of the keys was used to encrypt the message.

Here is a pretty good explanation of key identifiers on page 140: [http://books.google.com/books?id=Pgg-Es2j3UEC&pg=PA140&lpg=PA140&dq=understanding+key+identifiers+encrypt&source=bl&ots=nFg0BzM2ht&sig=Ux5sreXMKyuEEZu0uaxE7cXC1VI&hl=en&ei=JKKJStbHGJivtgffsNznDA&sa=X&oi=book%5Fresult&ct=result&resnum=6#v=onepage&q=&f=false%5D%5B1%5D

And here is another book that is using BouncyCastleCrypto, but it looks like they did little more than rip off the unit test source code. They have explained it a little: [http://books.google.com/books?id=WLLAD2FKH3IC&pg=PA343&lpg=PA343&dq=CmsEnvelopedDataGenerator+AddKekRecipient&source=bl&ots=O9HinJm3yB&sig=K5Z99DIVWW4-0abPIFR7x4lzBhU&hl=en&ei=g6aJSrjeDuHktgennNjnDA&sa=X&oi=book%5Fresult&ct=result&resnum=6#v=onepage&q=CmsEnvelopedDataGenerator%20AddKekRecipient&f=false%5D%5B2%5D

AaronLS
+1  A: 

aaronls is being a little unfair to the author of "Beginning cryptography with Java", who after all wrote all the unit tests himself in the first place...

As other commenters have pointed out, CMS works with certificates, you can't just pass a public key; it must be possible to refer to the key either by "SubjectKeyIdentifier" or by "IssuerAndSerialNumber". The two alternatives of AddKeyTransRecipient allow this. If these terms don't mean anything to you, you probably need to do some background reading on X.509.

Peter Dettman