1

I was trying to make an crypto util, I want to encrypt string, save in db then decrypt, I'm using TextEncryptor queryable spring security crypto module, because I want to use for rest apiKey , but i can`t make it work.

Here is my code:

        import org.springframework.security.crypto.encrypt.Encryptors;
        import org.springframework.security.crypto.encrypt.TextEncryptor;
        import org.springframework.security.crypto.keygen.KeyGenerators;

        public class CryptoUtil {

            public static String encrypt(String plain, String password) {
                String salt = KeyGenerators.string().generateKey();
                TextEncryptor textEncryptor = Encryptors.queryableText(password, salt);
                return textEncryptor.encrypt(plain);
            }

            public static String decrypt(String encrypted, String password) {
                String salt = KeyGenerators.string().generateKey();
                TextEncryptor textEncryptor = Encryptors.queryableText(password, salt);
                return textEncryptor.decrypt(encrypted);
            }
        }

    ----------------------------------------------------    

    public static void main(String[] args) {
        String password = "password";
        String plain = "hello";

        String encrypted = CryptoUtil.encrypt(plain,password);`enter code here`
        String decrypted = CryptoUtil.decrypt(encrypted, password);
    }

    ----------------------------------------------------

    Exception in thread "main" java.lang.IllegalStateException: Unable to invoke Cipher due to bad padding
            at org.springframework.security.crypto.encrypt.CipherUtils.doFinal(CipherUtils.java:142)
            at org.springframework.security.crypto.encrypt.AesBytesEncryptor.decrypt(AesBytesEncryptor.java:128)
            at org.springframework.security.crypto.encrypt.HexEncodingTextEncryptor.decrypt(HexEncodingTextEncryptor.java:40)
            at com.ind.app.util.CryptoUtil.decrypt(CryptoUtil.java:18)
            at com.ind.app.Test.main(UsuarioTest.java:11)
            Caused by: javax.crypto.BadPaddingException: Given final block not properly padded
                at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
                at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
                at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
                at javax.crypto.Cipher.doFinal(Cipher.java:2165)
                at org.springframework.security.crypto.encrypt.CipherUtils.doFinal(CipherUtils.java:135)
                ... 4 more
jhuamanchumo
  • 385
  • 2
  • 7
  • 21
  • I guess you are running into this: [stackoverflow: Given final block not properly padded](https://stackoverflow.com/questions/8049872/given-final-block-not-properly-padded) – Frito Sep 26 '18 at 07:17
  • I think is the same exception, but not same case. I think the docs explain about queryable, because I want the same encrypted for a given texto. https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#spring-security-crypto-encryption-text – jhuamanchumo Sep 26 '18 at 12:58

1 Answers1

0

To anyone with this same problem:

String salt = KeyGenerators.string().generateKey();

Every call to this line according the docs:

Creates a StringKeyGenerator that hex-encodes SecureRandom keys of 8 bytes in length. The hex-encoded string is keyLength * 2 characters in length.

So the salt is random, for example: plain : "hello" password : "password" salt : "e606bfd5cf9f198e"

encrypted : "60e0e953841ca708b74ac657735a2236076f0a614ec85548d163fadf91e2be8f"

Then, when I try to decrypt and get the plain, the method generates another (random) salt, so TextEncryptor.decrypt(String encrypted) can't decrypt correctly because the salt is not the same.

Encryptors.queryableText(CharSequence password, CharSequence salt)

Creates an encryptor for queryable text strings that uses standard password-based encryption. Uses a 16-byte all-zero initialization vector so encrypting the same data results in the same encryption result. This is done to allow encrypted data to be queried against. Encrypted text is hex-encoded.

CryptoUtil working for encrypt and decrypt plain Strings, not recommended for passwords, but useful for api keys for example.

public class CryptoUtil {

private static final String salt = "e606bfd5cf9f198e"; //any random generated salt

        public static String encrypt(String plain, String password) {
            TextEncryptor textEncryptor = Encryptors.queryableText(password, salt);
            return textEncryptor.encrypt(plain);
        }

        public static String decrypt(String encrypted, String password) {
            TextEncryptor textEncryptor = Encryptors.queryableText(password, salt);
            return textEncryptor.decrypt(encrypted);
        }
    }
jhuamanchumo
  • 385
  • 2
  • 7
  • 21