Reputation: 31
I have jasypt-spring-boot-1.17 with spring version "4.2.5.RELEASE" and spring Boot version "1.5.3.RELEASE".
I am using the first method from this website (https://github.com/ulisesbocchio/jasypt-spring-boot) since I use @SpringBootApplication in my application.java class.
I did the first testing. 1. I used this notation @PropertySource("classpath:sampleservices.yml") or @PropertySource("classpath:sampleservices.properties") in my ApplicationMain.java. 2. I saved the ENC() password in a separate file, either the sampleservices.yml or the sampleservices.properties. 3. I defined the following code in my application.yml file. I set the plain password value for JASYPT_ENCRYPTOR_PASSWORD in the environmental variable. The test was successful. jasypt: encryptor: bean: encryptorBean password: ${JASYPT_ENCRYPTOR_PASSWORD:}
However, the real encrypted ENC() password is stored in the following nested fashion in my application.yml file. Please let me know what exactly I should implement in order to have the decryption process happen successful. I need to use this decrypted password to login to DB.
I did change this code @PropertySource("application.yml") but I don't know how to get to the password field here.
From application.yml file: Spring: profiles: sample datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql:abc username: userid password: ENC(xxxxxxxx)
I kept getting this error.
com.ulisesbocchio.jasyptspringboot.exception.DecryptionException: Decryption of Properties failed, make sure encryption/decryption passwords match
at com.ulisesbocchio.jasyptspringboot.resolver.DefaultPropertyResolver.resolvePropertyValue(DefaultPropertyResolver.java:37) ~[jasypt-spring-boot-1.17.jar!/:?]
Thanks a lot!
Upvotes: 1
Views: 5448
Reputation: 343
I tried the following few things(1 to 7) to resolve this exception, over which I've spent almost my entire day going insane. I consolidated my approaches & finally thought to pen it down into an answer to this exception. Hope it helps in some or the other way or gives you other possible ways through this answer at least.
Latest Jasypt maven dependency
1) pom.xml
<!-- JASYPT Maven Dependency -->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<!-- JASYPT Maven Plugin-->
<build>
<plugins>
<plugin>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-maven-plugin</artifactId>
<version>3.0.3</version>
</plugin>
</plugins>
</build>
2) @EnableEncryptableProperties
- Class level annotation
I added it to my configuration class, you can add it to your application class having main method too. I tried both & it worked fine but preferred to keep it in config class.
3) Changed my Encryption algo. to PBEWITHHMACSHA512ANDAES_256
earlier I was using PBEWithMD5AndDES
which works fine too. I preferred having AES-SHA due to few specifics instead of DES-MD5.
4) Added IvGenerator org.jasypt.iv.RandomIvGenerator
I added config.setIvGeneratorClassName( "org.jasypt.iv.RandomIvGenerator") which is the class to have an additional initialization vector key when encryption/decryption is performed.
5) Create a Unit Test(Spock/JUnit)
I also wrote a tiny spock unit test case which I honestly used for generating my encrypted keys for all my client secrets which also helped me test my unit logic for jasypt technique.
Spock
unit test is written in groovy
language which is almost as same as java. So if you don't know groovy just past this code in Java and change def to appropriate RHS side & change the method name too & add @Test
at method level & other required things for JUnit
.
void "Test the custom JASYPT encryptor functionality"() {
given: "OriginalPlainTextSecret and PrivateKey"
def OriginalPlainTextSecret = "SECRET_2B_ENCRYPTED_and_ENCODED_base64"
// JASYPT private key used for ciphering the actual secret. This key is not meant to be encrypted!
// It is intentionally kept same/common across all profiles/environments for simplicity.
def privateKey = environment.getRequiredProperty("jasypt.encryptor.privatekey")
def encryptor = new PooledPBEStringEncryptor()
def config = new SimpleStringPBEConfig()
config.setPassword(privateKey) // an additional private key required for encryption & decryption
config.setAlgorithm(CommonConstants.JASYPT_ENC_ALGO)
config.setKeyObtentionIterations(CommonConstants.OBTENTION_ITERATION)
config.setPoolSize(CommonConstants.POOL_SIZE)
config.setProviderName(CommonConstants.PROVIDER_NAME)
config.setSaltGeneratorClassName(CommonConstants.JASYPT_SALT_GENERATOR)
config.setIvGeneratorClassName(CommonConstants.JASYPT_INIT_VECTOR)
config.setStringOutputType(CommonConstants.BASE64_ENCODE)
encryptor.setConfig(config)
when: "When encryption & decryption is executed"
def encryptedData = encryptor.encrypt(OriginalPlainTextSecret)
def decryptedData = encryptor.decrypt(encryptedData)
then: "Validate the keys used"
println("ORIGINAL SECRET : " + OriginalPlainTextSecret)
println("ENCRYPTED SECRET : " + encryptedData)
println("DECRYPTED SECRET : " + decryptedData);
println("Is DECRYPTED SECRET identical as the ORIGINAL SECRET? :: " + OriginalPlainTextSecret.contentEquals(decryptedData))
}
6) Simplified the private key
(password - the extra key used for encryption)
My private key i.e the password(extra key) was unnecessarily too much complex and I made it less complex.
Following are few maven commands which help you understand this
7) Different maven commands for application.yaml
& application.properties
If you are using application.properties
mvn jasypt:encrypt -Djasypt.encryptor.password=UR_PRIVATE_KEY
If you are using application.yaml
- My file was placed under nested /config folder
mvn jasypt:encrypt -Djasypt.encryptor.password=UR_PRIVATE_KEY -Djasypt.plugin.path="file:src/main/resources/config/application.yaml"
Here, -Djasypt.encryptor.password=UR_PRIVATE_KEY is the additional jasypt encryptor's private key. DO NOT PLACE YOUR CLIENT SECRET/YOUR DATABASE PASSWORD HERE! You need to place them inside your yaml/properties file as mentioned in below links.
Following are different techniques just for learning new latest different techniques which I've thought of using in my microservice & which worked well for me but I feel were more of an overkill. But having some time, space, freedom and curiosity didn't hurt me. You can test it as well.
Upvotes: 1
Reputation: 151
I have had the same problem on spring boot 2.1.3. But I found out later it was just my silly case. I just understand it wrong between "input" and "password" parameter meaning. When I encrypt on Command prompt I thought "input" means key then I swap value between two of them when I run the application.
So, remember:
input=[your real password]
password=[is the jasypt key]
If this is not your root cause, another thing to consider is when you encrypt password on Windows it may not be able to use on Linux. You may have to encrypt on Linux when need to run applications on Linux.
Upvotes: 1