This is code generated for my Algorithm Implementation's class. I was to create my own RSA public and private keys using modPow and modInverse and use that to implement a digital signature. That works great, not the problem here. For extra credit I am implementing a digital envelope that will encrypt the actual message and have an AES key "sent" with it encrypted by my own RSA implementation. I am just using BigInteger.modPow with my known public, private and modulus values where appropriate to encrypt and decrypt the AES key.

Everything has been made and when I ran it it decrypted and worked great, however without modifying anything it randomly throws a InvalidKeyLength exception when decrypting the sealed object (the message). Can anyone tell me how to ensure it decrypts every time?

Below is the code I think is vital. If any more is needed I will post upon request.

This is from my keyGenerator

KeyGenerator keygen = KeyGenerator.getInstance("AES");
SecretKey key = keygen.generateKey();
//outputs symmetric cypher key to file
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("AES.key"));
System.out.println("\nGenerated AES Symmetric Cipher Key");

From my DigitalEnvelope Constructor where I encrypt the AES Key

//Reads in AES Key
ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream("AES.key"));
SecretKey key = (SecretKey) keyIn.readObject();
//Outputs key as bytes and then encrypts with RSA Public Key
EncryptedKey = new BigInteger(1, key.getEncoded()).modPow(RSAPublicKey, RSAModulus);

This is my decryption routine

public boolean decryptMessage(String envelopeName) throws FileNotFoundException, IOException, ClassNotFoundException, GeneralSecurityException
//Reads in RSA Keys that were Generated
Scanner fileScan = new Scanner(new FileInputStream("keys.txt"));	
ArrayList<String> keys = new ArrayList<String>();
while (fileScan.hasNext()) //reads public key, private key and N into an ArrayList as Strings
BigInteger PrivateKey = new BigInteger(keys.get(1)); //initializes RSA Private Key
//reads in the digital Envelope
RSAEnvelope fileEnvelope;
FileInputStream fin = new FileInputStream(envelopeName);]
ObjectInputStream ois = new ObjectInputStream(fin);
fileEnvelope = (RSAEnvelope) ois.readObject();
//rebuilds the AES key from decrypted bytes	    
byte [] data = fileEnvelope.getEncryptedKey().modPow(PrivateKey,RSAModulus).toByteArray();
AESKey = new SecretKeySpec(data,"AES");
//initalize AES Cipher with decrypted key and decrypt the signed Message	    
Cipher decipher = Cipher.getInstance("AES");
decipher.init(Cipher.DECRYPT_MODE, AESKey);
//write out signed message to file
SignedMessage deCryptedMessage = (SignedMessage) fileEnvelope.getSealedObject().getObject(decipher);
FileOutputStream fout = new FileOutputStream(deCryptedMessage.getMessageName().concat(".unencrypted.signed"));
ObjectOutputStream oos = new ObjectOutputStream(fout);
catch (InvalidKeyException e)
{return false;}
return true;

It is only ten points extra credit which I will probably still get at this point, but that isn't what is important to me. I just want to know why it doesn't work and how to fix it.


Figured out the issue. After digging in deep the reason it worked most times but not some is that by decrypting the key with mod pow and then reconverting to bytes sometimes in the cast due to the special case of the numbers generated the key length would shift from 16 bytes to either 15 or 17 bytes.

This is my kludge of a solution due to it being 2:30 AM and I need some sleep. So it most likely then is the way BigInteger.toByteArray() stores the data or just the number had trailing or leading zeros that were dropped off.

Anyone have any idea which and an efficient way to avoid this issue?

			r = new SecureRandom(); //generate secure random number
	        KeyGenerator keygen = KeyGenerator.getInstance("AES");  //instaniate AES
	        keygen.init(128,r);  //prime AES to 128 bit key seeded with a random number
	        SecretKey key = keygen.generateKey(); 
	        rawKey = key.getEncoded(); //encode key into bytes
			//brute force special case check.  Small Chance of AES being 15 or 17 bytes after encryption cycle and
			//re-encoding process.  Checks for that case and regenerates key if problem arises
			BigInteger rawKeyInt = new BigInteger(rawKey);
			String s = rawKeyInt.toString(32);
			BigInteger EncryptedKey = new BigInteger(s,32);
			EncryptedKey = EncryptedKey.modPow(e, n);      
		    s = EncryptedKey.modPow(d, n).toString(32);
		    rawKeyInt = new BigInteger(s,32);
		    rawKey = rawKeyInt.toByteArray();

		} while (rawKey.length != 16);