2

I'm implementing the following steps:

  1. Bob encrypts a message with AES
  2. Bob encodes the encryption to a base64 string
  3. Bob writes the string to a file
  4. Alice reads the file
  5. Alice converts the string to byte
  6. Alice decrypts the message

However, I'm failing at the last step.

Heres the encryption:

public void sendHelloWorld() {
    String msg = "hello world!";
    try {
        SecretKeySpec AesKeySpec = new SecretKeySpec(aesKeyBytes, "AES");
        Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
        c.init(Cipher.ENCRYPT_MODE, AesKeySpec);
        aesEncryptedHello = c.doFinal(msg.getBytes());
    } catch (BadPaddingException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    String s = new String(aesEncryptedHello, StandardCharsets.UTF_8);
    System.out.println("Message = " + s);
    sendMessage(Base64.getEncoder().encodeToString(aesEncryptedHello));
}

Here's the decrypt:

public void decryptAESMessage(byte[] encryptedMessage) {
    try {
        String s = new String(encryptedMessage, StandardCharsets.UTF_8);
        System.out.println("Message = " + s);
        SecretKeySpec AesKeySpec = new SecretKeySpec(bobAesKey, "AES");
        Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
        c.init(Cipher.DECRYPT_MODE, AesKeySpec);
        byte[] aesMessage = c.doFinal(encryptedMessage);
        String message = new String(aesMessage, StandardCharsets.UTF_8);
        System.out.println("Message is " + message);
    } catch (BadPaddingException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    
}

Here's the write to file:

public void sendMessage(String msg) {
    try {
        
        FileWriter myWriter = new FileWriter(<myredactedfilepath>);
        myWriter.write(msg);
        myWriter.close();
    } catch (IOException e) {
        System.out.println("An error occurred.");}
}

Here's stage 5, just to show the decode isn't missed:

alice.decryptAESMessage(Base64.getDecoder().decode(alice.readEncryptedMessage()));

I print the keys and the encrypted messages at both ends and they match.

kelalaka
  • 5,064
  • 5
  • 27
  • 44
qz_99
  • 185
  • 1
  • 12
  • Encrypt `AES/CBC/PKCS5Padding` and IV is missing. Decrypt `AES/ECB/PKCS5Padding` make both either ECB ( please don't) or CBC with the IV is provided and appended to the beginning of the ciphertext. During decryption resolved it and use it. There are tons of examples of this on this site. – kelalaka Nov 10 '20 at 21:31
  • @kelalaka nooooo, can't believe I spent so long and didn't notice that. Thank you – qz_99 Nov 10 '20 at 21:35
  • There may be some other errors, too that I did not look that deeoer... – kelalaka Nov 10 '20 at 21:41
  • No that was it, it works fine now – qz_99 Nov 10 '20 at 21:42
  • In this case, you may write an answer to your question. – kelalaka Nov 10 '20 at 21:43
  • If you want to use your comment as an answer I'll accept it :) – qz_99 Nov 10 '20 at 21:44

1 Answers1

1

In the Encryption part, you used AES/CBC/PKCS5Padding that is CBC mode of operation with PKCS#5 - actually, it is PKCS#7 - the there is an IV is missing. The CBC mode requires and IV and that should be at least random. That can be generated with

SecureRandom randomSecureRandom = new SecureRandom();
byte[] iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);

In the decryption part, you used AES/ECB/PKCS5Padding. Normally both must match. Make both either ECB ( please don't) or CBC with the IV.

The IV in generally, appended to the beginning of the ciphertext. During decryption resolved it and use it.

Also, make the base64 decoding inside of the decryption. This will make your mode more robust.

Final note: if there is no specific reason, prefer AES-GCM which can provide not only confidentiality but also integrity and authentication. If you need to stick CBC you need additionally use HMAC to achieve integrity and authentication.

And for a full code example; See the Maartens answer

kelalaka
  • 5,064
  • 5
  • 27
  • 44