6

I am encryption and decryption using following code, while decryption I am getting a error while running. error message is 'Illegal base64 character 20'

Encryption code:

String secretValue = "sazhwsxplokmeroo";
keyValue = secretValue.getBytes();
Key generatedKey = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.ENCRYPT_MODE, generatedKey);
byte[] encValue = c.doFinal(userEmail.getBytes());
String encryptedValue = Base64.getEncoder().encodeToString(encValue);

secretKey:

 private Key generateKey() {
     Key secretKey = new SecretKeySpec(keyValue, ALGO);
     return secretKey;
}

Decryption code:

String secretValue = "sazhwsxplokmeroo";
keyValue = secretValue.getBytes();
Key generatedKey = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.DECRYPT_MODE, generatedKey);
byte[] decodedValue = Base64.getDecoder().decode(encryptEmail.getBytes()); //error throws from this line as illegal base64 character 20
byte[] decValue = c.doFinal(decodedValue);
String decryptedValue = decValue.toString();

how can I decrypt the encrypted value without error

encrypted value = 3aW0qv4pN+y3Tj8raXDHtos95ChpLu2JzEnfW+KfgEE=

this value appears in the spring controller as = 3aW0qv4pN y3Tj8raXDHtos95ChpLu2JzEnfW KfgEE=

it shows two spaces "+" get converted to "(space)"

Now I have changed my secret key as 'sa278asabmnbmnbm'

I am getting encrypt value as 40SRNEe9PgaxEeprPyqlyeP08hBHq00Ow9WWBgP6ZTM=

While decrypt I am getting [B@75141845 as decrypted Value

expected : shamith@alraislabs.in

Shamith S Kumar
  • 89
  • 1
  • 1
  • 7
  • What is value of `encryptEmail`? Does it by any chance have a space in it? – Andreas Mar 21 '17 at 03:23
  • yes, the "+" appears in the encrypted code get converted to space from spring controller – Shamith S Kumar Mar 21 '17 at 03:40
  • 1
    Because you forgot to URL Encode the Base64 string, so the `+` would have been `%2B`. – Andreas Mar 21 '17 at 03:45
  • any suggestion to resolve the issue/ – Shamith S Kumar Mar 21 '17 at 03:59
  • 3
    Yes, **URL Encode the Base64 string** *(I already told you that you forgot to do that)* before sending it to the web server, aka Spring controller. – Andreas Mar 21 '17 at 04:39
  • The other issue is that `decValue.toString()` should be `new String(decValue)`. But this can lead to wrong results, because you're not specifying the charset during encryption and decryption. It will use the platform default and it might be different during encryption and decryption. – Artjom B. Mar 21 '17 at 06:30
  • **Never use [ECB mode](http://crypto.stackexchange.com/q/14487/13022)**. It's deterministic and therefore not semantically secure. You should at the very least use a randomized mode like [CBC](http://crypto.stackexchange.com/q/22260/13022) or [CTR](http://crypto.stackexchange.com/a/2378/13022). It is better to authenticate your ciphertexts so that attacks like a [padding oracle attack](http://crypto.stackexchange.com/q/18185/13022) are not possible. This can be done with authenticated modes like GCM or EAX, or with an [encrypt-then-MAC](http://crypto.stackexchange.com/q/202/13022) scheme. – Artjom B. Mar 21 '17 at 06:30

1 Answers1

0

I'm well aware that I am late to answer this question. But, I stumbled across a very "similar" situation and would be glad to share my learning as an answer instead of a comment since its not short. I'll briefly explain my context & how I encountered this scenario. I also have logged my learnings here as an answer with tiny details. I have been playing with JASYPT ciphering where I've used a private key.

String jasyptPrivateKey = "Hello@123"; which contains '@'. However, there are few things I overlooked which resulted in my short lived failure.

Following is the stack trace for my Spock unit test case I've written.

java.lang.IllegalStateException: Failed to load ApplicationContext

    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:190)
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:132)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244)
    at org.spockframework.spring.SpringTestContextManager.prepareTestInstance(SpringTestContextManager.java:56)
    at org.spockframework.spring.SpringInterceptor.interceptInitializerMethod(SpringInterceptor.java:43)
    at org.spockframework.runtime.extension.AbstractMethodInterceptor.intercept(AbstractMethodInterceptor.java:24)
    at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:101)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$1(NodeTestTask.java:111)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:111)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:79)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.spockframework.runtime.model.MethodInfo.invoke(MethodInfo.java:136)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stargateOauthPropertiesBean': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Illegal base64 character 40
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:405)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1413)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:771)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:763)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:438)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:339)
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:123)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    ... 46 more
Caused by: java.lang.IllegalArgumentException: Illegal base64 character 40
    at java.base/java.util.Base64$Decoder.decode0(Base64.java:746)
    at java.base/java.util.Base64$Decoder.decode(Base64.java:538)
    at java.base/java.util.Base64$Decoder.decode(Base64.java:561)
    at com.ulisesbocchio.jasyptspringboot.encryptor.SimpleAsymmetricConfig.lambda$null$0(SimpleAsymmetricConfig.java:46)
    at java.base/java.util.Optional.map(Optional.java:265)
    at com.ulisesbocchio.jasyptspringboot.encryptor.SimpleAsymmetricConfig.lambda$loadResource$3(SimpleAsymmetricConfig.java:46)
    at java.base/java.util.Optional.orElseGet(Optional.java:369)
    at com.ulisesbocchio.jasyptspringboot.encryptor.SimpleAsymmetricConfig.loadResource(SimpleAsymmetricConfig.java:44)
    at com.ulisesbocchio.jasyptspringboot.encryptor.SimpleAsymmetricConfig.loadPrivateKeyResource(SimpleAsymmetricConfig.java:54)
    at com.ulisesbocchio.jasyptspringboot.util.Singleton.lambda$fromLazy$4(Singleton.java:35)
    at com.ulisesbocchio.jasyptspringboot.util.Singleton.lambda$new$6(Singleton.java:42)
    at com.ulisesbocchio.jasyptspringboot.util.Singleton.get(Singleton.java:53)
    at com.ulisesbocchio.jasyptspringboot.encryptor.SimpleAsymmetricByteEncryptor.decrypt(SimpleAsymmetricByteEncryptor.java:35)
    at com.ulisesbocchio.jasyptspringboot.encryptor.ByteEncryptorStringEncryptorDelegate.decrypt(ByteEncryptorStringEncryptorDelegate.java:32)
    at com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor.decrypt(DefaultLazyEncryptor.java:57)
    at com.ulisesbocchio.jasyptspringboot.resolver.DefaultPropertyResolver.lambda$resolvePropertyValue$0(DefaultPropertyResolver.java:44)
    at java.base/java.util.Optional.map(Optional.java:265)
    at com.ulisesbocchio.jasyptspringboot.resolver.DefaultPropertyResolver.resolvePropertyValue(DefaultPropertyResolver.java:40)
    at com.ulisesbocchio.jasyptspringboot.resolver.DefaultLazyPropertyResolver.resolvePropertyValue(DefaultLazyPropertyResolver.java:50)
    at com.ulisesbocchio.jasyptspringboot.EncryptablePropertySource.getProperty(EncryptablePropertySource.java:20)
    at com.ulisesbocchio.jasyptspringboot.caching.CachingDelegateEncryptablePropertySource.getProperty(CachingDelegateEncryptablePropertySource.java:41)
    at com.ulisesbocchio.jasyptspringboot.wrapper.EncryptableMapPropertySourceWrapper.getProperty(EncryptableMapPropertySourceWrapper.java:31)
    at org.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:85)
    at org.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:62)
    at org.springframework.core.env.AbstractEnvironment.getProperty(AbstractEnvironment.java:588)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$1.getProperty(PropertySourcesPlaceholderConfigurer.java:137)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$1.getProperty(PropertySourcesPlaceholderConfigurer.java:133)
    at org.springframework.core.env.PropertySourcesPropertyResolver.getProperty(PropertySourcesPropertyResolver.java:85)
    at org.springframework.core.env.PropertySourcesPropertyResolver.getPropertyAsRawString(PropertySourcesPropertyResolver.java:74)
    at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:153)
    at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
    at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:239)
    at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210)
    at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:175)
    at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:936)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1321)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
    ... 63 more

Solution I forgot to add the Bean name to my getJasyptStringEncryptor bean.

'@Bean(name = "jasyptStringEncryptor")' This registered the bean and allows the application to know about this bean. Moreover I also added @EnableEncryptableProperties to my configuration class which was missing earlier.

In my answer here you will find many other details if you are struggling with your encryption or can provide you few clues and other possible tryouts you haven't done. I have tried to be verbose and clear & hopefully it helps and saves your time.

Aniket
  • 173
  • 2
  • 11