ulisesbocchio / jasypt-spring-boot

Jasypt integration for Spring boot
MIT License
2.91k stars 522 forks source link

Decrypted value ends with "=" #18

Closed ffalcinelli closed 8 years ago

ffalcinelli commented 8 years ago

I'm experiencing a very strange issue. When using encrypted password with an Oracle datasource

spring.datasource.url=jdbc:oracle:thin:@PCSRPWDSVIL:1521:dbrecpwd
spring.datasource.userId=otpuser
spring.datasource.password=ENC(0FiLiCHZdFUOnb938Gtfj9q3s23nmRyP)
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver

I always get an Invalid username/password error:

2016-01-27 17:49:09.686 ERROR 6411 --- [           main] o.a.tomcat.jdbc.pool.ConnectionPool      : Unable to create initial connections of pool.

java.sql.SQLException: ORA-01017: invalid username/password; logon denied

    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447) ~[ojdbc6-11.2.0.4.jar!/:11.2.0.4.0]
...

It works in plaintext. So I've wrote a very simple controller just for testing purposes, this is the controller code

@Controller
@RequestMapping("/encrypt")
public class JasyptController {

    private Logger logger = Logger.getLogger(JasyptController.class);

    @Autowired
    private StringEncryptor stringEncryptor;

    @RequestMapping(method = RequestMethod.POST)
    public
    @ResponseBody
    String encrypt(
            @RequestBody String text) {
        String encrypted = stringEncryptor.encrypt(text.trim());
        logger.info("ENCRYPTED: " + encrypted);
        logger.info("DECRYPTED: " + stringEncryptor.decrypt(encrypted));
        return String.format("ENC(%s)", encrypted);
    }
}

while this is the custom configuration made in Application class (1to1 copy from the project readme)

    @Bean
    static public StringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        //TODO: replace with real secret... Read somewhere, e.g. a system property
        String secret = "password";
        config.setPassword(secret);
        config.setAlgorithm("PBEWithMD5AndDES");
        config.setKeyObtentionIterations("1000");
        config.setPoolSize("1");
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setStringOutputType("base64");
        encryptor.setConfig(config);
        return encryptor;
    }

This is how I invoke it

$ curl localhost:8080/encrypt --data mytext
ENC(kdOzCGcWc1ypiGmr2MIG8A==)

And this is the log:

2016-01-27 17:39:20.663  INFO 6368 --- [nio-8080-exec-1] c.n.m.controllers.JasyptController       : ENCRYPTED: kdOzCGcWc1ypiGmr2MIG8A==
2016-01-27 17:39:20.665  INFO 6368 --- [nio-8080-exec-1] c.n.m.controllers.JasyptController       : DECRYPTED: mytext=

So I think the problem resides in an additional base64 padding performed somewhere on the decrypted value... Really strange. Any advice? Or maybe am I missing something?

Thanks in advance, and best regards, Fabio

ulisesbocchio commented 8 years ago

Hey Fabio, thanks for using the library :) The problem is your Encryption endpoint and the way you're invoking it. You're taking the whole body (@RequestBody String test) as input in your endpoint, and when doing the curl, you're sending it as FORM data by default (without specifying content-type). So when you capture the Request Body in your endpoint and is converted to String, Spring finds that you only defined one parameter mytext that has no value, so its literally "mytext=" in URL form enconded format. Since you're sending --data mytext

Change your encrypt method in JasyptController to this:

    @RequestMapping(method = RequestMethod.POST)
    public
    @ResponseBody
    String encrypt(
        @RequestParam("text") String text) {
        String encrypted = stringEncryptor.encrypt(text.trim());
        logger.info("ORIGINAL: " + text);
        logger.info("ENCRYPTED: " + encrypted);
        logger.info("DECRYPTED: " + stringEncryptor.decrypt(encrypted));
        return String.format("ENC(%s)", encrypted);
    }

Notice the change from @RequestBody to @RequestParam("text"). So when you invoke it from curl, you need to send a parameter called text in your URL-encoded-form data:

$ curl localhost:8080/encrypt --data text=mytext
ENC(nWdKNNDGamuA+79stkv5ww==)

Best Regards, Uli

ffalcinelli commented 8 years ago

No words... You're right and I'm feeling totally silly! I'm sorry for having wasted your time, thank you a lot!

ulisesbocchio commented 8 years ago

No worries man, glad I could help. If you like the library please give it a star. Best, Uli