0

I have seen a lot of questions/answers but no one works for me. The problem is that, when I want to decrypt a text, I go throw BadPaddingException and doesn't know why.

Here is my code to encrypt text:

            KeyAgreement keyAgreement = this.getSecretKeyAgreement(publicOtherUserKey, privateOwnKey);
            SecretKey secretKey = new SecretKeySpec(keyAgreement.generateSecret(), "AES");
            Cipher aesCipher = null;
            aesCipher = Cipher.getInstance("AES");
            aesCipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] byteDataToEncrypt = text.getBytes();
            byte[] byteCipherText = aesCipher.doFinal(byteDataToEncrypt);
            byte[] encodedBytes = Base64.encodeBase64(byteCipherText);
            textEncrypted = new String(encodedBytes);

Where "publicOtherUserKey" and "privateOwnKey" where generated using Diffie-Hellman Protocol.

Here is the code that decrypt the text, that goes throw BadPaddingException

        KeyAgreement keyAgreement = this.getSecretKeyAgreement(publicOtherUserKey, privateOwnKey);
        byte[] encodedBytes = text.getBytes();
        SecretKey secretKey = new SecretKeySpec(keyAgreement.generateSecret(), "AES");
        byte[] decodedBytes = Base64.decodeBase64(encodedBytes);
        Cipher decrypt = Cipher.getInstance("AES");
        decrypt.init(Cipher.DECRYPT_MODE, secretKey);
        textDecrypted = new String(decrypt.doFinal(decodedBytes));

Where "publicOtherUserKey" and "privateOwnKey" where generated using Diffie-Hellman Protocol, and "text" is the encrypted text.

Can you help me?

EDIT

It's important to mention that all the keys and texts are encoded in Base64

EDIT 2

Code for Start key exchange with Diffie-Hellman

    int bitLength = 256; // 256 bits
    SecureRandom rnd = new SecureRandom();
    BigInteger p = BigInteger.probablePrime(bitLength, rnd);
    BigInteger g = BigInteger.probablePrime(bitLength, rnd);

    DHParameterSpec dhParams = new DHParameterSpec(p, g);
    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH", "BC");
    keyGen.initialize(dhParams, new SecureRandom());

    KeyAgreement aKeyAgree = KeyAgreement.getInstance("DH", "BC");
    KeyPair aPair = keyGen.generateKeyPair();
    aKeyAgree.init(aPair.getPrivate());

    byte[] aPairPrivateKey = aPair.getPrivate().getEncoded();
    byte[] encodedBytesPrivateKey = Base64.encodeBase64(aPairPrivateKey);
    String privateKey = new String(encodedBytesPrivateKey);

    byte[] aPairPublicKey = aPair.getPublic().getEncoded();
    byte[] encodedBytesPublicKey = Base64.encodeBase64(aPairPublicKey);
    String publicKey = new String(encodedBytesPublicKey);

Where "publicKey" and "privateKey" are the keys to later generate the secret key. "publicKey" is the Key sended to the other user. "p" and "g" are the numbers to generate the Key too.

The code for complete the exchange:

    DHParameterSpec dhParams = new DHParameterSpec(p, g);
    KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH", "BC");
    keyGen.initialize(dhParams, new SecureRandom());

    KeyAgreement bKeyAgree = KeyAgreement.getInstance("DH", "BC");
    KeyPair bPair = keyGen.generateKeyPair();
    bKeyAgree.init(bPair.getPrivate());

    byte[] userPublicBytesBase64 = base64EncodedPublicKey.getBytes();
    byte[] userPublicKey = Base64.decodeBase64(userPublicBytesBase64);

    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(userPublicKey);
    KeyFactory keyFactory = KeyFactory.getInstance("DH");
    PublicKey aPublicKey = keyFactory.generatePublic(keySpec);
    bKeyAgree.doPhase(aPublicKey, true);

    final byte[] bPairPrivateKey = bPair.getPrivate().getEncoded();
    byte[] encodedBytesPrivateKey = Base64.encodeBase64(bPairPrivateKey);
    String privateKey = new String(encodedBytesPrivateKey);

    final byte[] bPairPublicKey = bPair.getPublic().getEncoded();
    byte[] encodedBytesPublicKey = Base64.encodeBase64(bPairPublicKey);
    String publicKey = new String(encodedBytesPublicKey);

"base64EncodedPublicKey" is the Key generated in the first block of Code ("publicKey"), and "p" and "g" are too the primes generated in the first block of Code.

Julian Ezequiel
  • 183
  • 1
  • 10
  • Looks correct, but not secure. Please provide a full and minimal example (including the Diffie Hellman part in a single method). – Artjom B. Nov 11 '15 at 18:35
  • `Cipher.getInstance("AES")` probably defaults to `"AES/ECB/PKCS5Padding"`. Never use ECB mode. You really need to use at least CBC mode with a random IV. The IV doesn't have to be secret, so you can prepend it to the ciphertext. Furthermore, you should authenticate your ciphertexts. This can be done with an authenticated mode like GCM or with a MAC like HMAC-SHA256 in an encrypt-then-MAC scheme. – Artjom B. Nov 11 '15 at 18:37
  • Edited with Diffie-Hellman part – Julian Ezequiel Nov 12 '15 at 12:32
  • I don't understand why (try to) you generate *p* and *g* yourself when `KeyPairGenerator` is [perfectly capable of doing that](http://stackoverflow.com/questions/19323178/how-to-do-diffie-hellman-key-generation-and-retrieve-raw-key-bytes-in-java). Your *g* is probably not a primitive root modulo *p*, so this won't function correctly. – Artjom B. Nov 12 '15 at 22:22

0 Answers0