views:

243

answers:

2

Hello,

I am trying to make a program that Encrypts data using AES, then encrypts the AES key with RSA, and then decrypt. However, once i encrypt the AES key it comes out to 128 bytes. RSA will only allow me to decrypt 117 bytes or less, so when i go to decrypt the AES key it throws an error.

Relavent code:

    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(1024);
    KeyPair kpa = kpg.genKeyPair();
    pubKey = kpa.getPublic();
    privKey = kpa.getPrivate();

    updateText("Private Key: " +privKey +"\n\nPublic Key: " +pubKey);

    updateText("Encrypting " +infile);
    //Genereate aes key
    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    kgen.init(128); // 192/256
    SecretKey aeskey = kgen.generateKey();
    byte[] raw = aeskey.getEncoded();

    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

    updateText("Encrypting data with AES");
    //encrypt data with AES key
    Cipher aesCipher = Cipher.getInstance("AES");
    aesCipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    SealedObject aesEncryptedData = new SealedObject(infile, aesCipher);

    updateText("Encrypting AES key with RSA");
    //encrypt AES key with RSA
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    byte[] encryptedAesKey = cipher.doFinal(raw);

    updateText("Decrypting AES key with RSA. Encrypted AES key length: " +encryptedAesKey.length);
    //decrypt AES key with RSA       
    Cipher decipher = Cipher.getInstance("RSA");
    decipher.init(Cipher.DECRYPT_MODE, privKey);
    byte[] decryptedRaw = decipher.doFinal(encryptedAesKey); //error thrown here because encryptedAesKey is 128 bytes
    SecretKeySpec decryptedSecKey = new SecretKeySpec(decryptedRaw, "AES");

    updateText("Decrypting data with AES");
    //decrypt data with AES key
    Cipher decipherAES = Cipher.getInstance("AES");
    decipherAES.init(Cipher.DECRYPT_MODE, decryptedSecKey);
    String decryptedText = (String) aesEncryptedData.getObject(decipherAES);

    updateText("Decrypted Text: " +decryptedText);

Any idea on how to get around this?

+2  A: 

When you use encryption, always specifying padding. Otherwise, your clear-text will be padded to the block size. For example,

Cipher aes = Cipher.getInstance("AES/CBC/PKCS5Padding");

Cipher rsa = Cipher.getInstance("RSA/None/PKCS1Padding");

The AES key is only 16 bytes for 128-bit. So it should fit in any RSA block nicely.

ZZ Coder
Thanks, do you have any more information on which padding schemes for which algorithms are possible?
Petey B
The padding supported by each algorithm is depended on the JCE implementation. The values in my example are the recommended settings for AES and RSA.
ZZ Coder
-1 His problem has absolutely nothing to do with the type of padding used. A block cipher will always produce blocks of the same size, and padding is a requirement. For instance AES 128 will always produce cipher text divisible by 128bits. Unless of course you are using OFB mode.
Rook
It seems no matter which padding i specify (even NOPADDING) the encrypted AES key always comes out to 128 bytes
Petey B
+1  A: 

Edit: I misunderstood the problem. You should use a larger RSA key, for instance RSA 4096 allows you to encrypt 501 bytes.

You can try using AES in OFB mode which will allow you to encrypt a message of an arbitrary size. Alternately you could use a stream cipher like RC4 which will also allow you to encrypt an arbitrary sized message. If you go with RC4 make sure to use RC4-drop1024 which just means you throw away the first 1024 bytes of cipher text. The first 1024 bits of rc4 are predictable and this as well as many other issues led to the downfall of WEP used to secure WIFI. Another problem with RC4 is that you cannot reuse the PRNG stream, Basically you must use a different key for each message or an attacker can break the system pretty easily using nothing more than XOR. I'd go with AES in OFB mode, but RC4 can be used securely.

All other block cipher modes will always produce a message divisible by their block size. For instance AES 128 in CBC mode will always produce a message divisible by 128 bits. If the message is smaller than 128 bits its often padded with nulls. If this a string, then it should be null terminated and you don't have to worry.

On a Side not make sure you don't use ECB mode. Another problem is I don't see that you are using a rotating or randomized Initialization Vector (IV), which significantly weakens any block cipher. Failure to properly implement a IV is a recognized vulnerability by CWE-329.

Rook
Thanks for the suggestions, especially about IV, however the problem is not with the implementation of AES but rather RSA. Whenever i encrypt the 16 byte AES key (with RSA) the result comes out to 128 bytes, which is larger than RSA's 117 byte cap so i am unable to decrypt it.
Petey B
@Petey B Oah sorry I misunderstood, thats an even easier problem to solve, just use a larger RSA key. For instance RSA 4096 allows you to encrypt 501 bytes.
Rook
All is well now, thank you
Petey B
@Petey B Your welcome I'm happy to help.
Rook
This is so confusing. The size of the original RSA key should have been more than enough. And the reported error doesn't occur for the code posted.
GregS