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?
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.
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.
You could get out of complexity trouble by just us the wrap mode/function of the Cipher class. You can see my source code for an example of how to do that.
精彩评论