I am using Jasypt's CLI for testing encryption and decryption. The encryption is successful for all the algorithms but decryption fails for stronger algorithms. Here is the encryption and decryption for PBEWithMD5AndDES:
Encryption:
prakash#prakash:~$ java -cp ~/.m2/repository/org/jasypt/jasypt/1.9.2/jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI password=secret algorithm=PBEWITHMD5ANDDES input=encryptThis
----ENVIRONMENT-----------------
Runtime: Oracle Corporation OpenJDK 64-Bit Server VM 11.0.2+9-Ubuntu-3ubuntu118.04.3
----ARGUMENTS-------------------
input: encryptThis
password: secret
algorithm: PBEWITHMD5ANDDES
----OUTPUT----------------------
pZRJ9Egt+OcjBX28cSJUYDbvqiKIUVxR
Decryption:
prakash#prakash:~$ java -cp ~/.m2/repository/org/jasypt/jasypt/1.9.2/jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI password=secret algorithm=PBEWITHMD5ANDDES input=pZRJ9Egt+OcjBX28cSJUYDbvqiKIUVxR
----ENVIRONMENT-----------------
Runtime: Oracle Corporation OpenJDK 64-Bit Server VM 11.0.2+9-Ubuntu-3ubuntu118.04.3
----ARGUMENTS-------------------
input: pZRJ9Egt+OcjBX28cSJUYDbvqiKIUVxR
password: secret
algorithm: PBEWITHMD5ANDDES
----OUTPUT----------------------
encryptThis
Now If I change the algorithm to PBEWITHHMACSHA1ANDAES_128, here are the results:
Encryption:
prakash#prakash:~$ java -cp ~/.m2/repository/org/jasypt/jasypt/1.9.2/jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI password=secret algorithm=PBEWITHHMACSHA1ANDAES_128 input=encryptThis
----ENVIRONMENT-----------------
Runtime: Oracle Corporation OpenJDK 64-Bit Server VM 11.0.2+9-Ubuntu-3ubuntu118.04.3
----ARGUMENTS-------------------
input: encryptThis
password: secret
algorithm: PBEWITHHMACSHA1ANDAES_128
----OUTPUT----------------------
tAIe6mUS6uBCG/OkHJWT2LWRagHOMBxwK/v9L7SGZIA=
Decryption:
prakash#prakash:~$ java -cp ~/.m2/repository/org/jasypt/jasypt/1.9.2/jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI password=secret algorithm=PBEWITHHMACSHA1ANDAES_128 input=tAIe6mUS6uBCG/OkHJWT2LWRagHOMBxwK/v9L7SGZIA=
----ENVIRONMENT-----------------
Runtime: Oracle Corporation OpenJDK 64-Bit Server VM 11.0.2+9-Ubuntu-3ubuntu118.04.3
----ARGUMENTS-------------------
input: tAIe6mUS6uBCG/OkHJWT2LWRagHOMBxwK/v9L7SGZIA=
password: secret
algorithm: PBEWITHHMACSHA1ANDAES_128
----ERROR-----------------------
Operation not possible (Bad input or parameters)
The jasypt version I'm using is 2.0.0 and I've tried this on both java-8 and java-11. In both the machines I've JCE's unlimited strength policy enabled.
The list of Algorithms that were decrypted successfully are:
PBEWITHMD5ANDDES,
PBEWITHMD5ANDTRIPLEDES,
PBEWITHSHA1ANDDESEDE,
PBEWITHSHA1ANDRC2_128,
PBEWITHSHA1ANDRC2_40,
PBEWITHSHA1ANDRC4_128,
PBEWITHSHA1ANDRC4_40.
The algorithms with which decryption fails are:
PBEWITHHMACSHA1ANDAES_128
PBEWITHHMACSHA1ANDAES_256
PBEWITHHMACSHA224ANDAES_128
PBEWITHHMACSHA224ANDAES_256
PBEWITHHMACSHA256ANDAES_128
PBEWITHHMACSHA256ANDAES_256
PBEWITHHMACSHA384ANDAES_128
PBEWITHHMACSHA384ANDAES_256
PBEWITHHMACSHA512ANDAES_128
PBEWITHHMACSHA512ANDAES_256.
I've been stuck at this problem for three days. Someone please help me out!
Edit:
After suggestions from Maarten, I went ahead and copied the code from JasyptPBEStringDecryptionCLI and made my own class in hope to reproduce the error through code and get the stacktrace.
Here is the code I wrote:
package com.example.HelloWorldApiUbuntu;
import java.util.Properties;
import org.jasypt.intf.service.JasyptStatelessService;
public class TestingJasyptStringDecryptionCLI {
public static void main(final String[] args) throws Exception{
final JasyptStatelessService service = new JasyptStatelessService();
String input = "P/25Hp3CKdFj7pz85eJyHETugwX5ZxWEF7PpzJ/fBGI=";
final String result =
service.decrypt(
input,
"secret",
null,
null,
"PBEWITHHMACSHA512ANDAES_128",
null,
null,
"1000",
null,
null,
"org.jasypt.salt.RandomSaltGenerator",
null,
null,
"SunJCE",
null,
null,
/*argumentValues.getProperty(ArgumentNaming.ARG_PROVIDER_CLASS_NAME)*/null,
null,
null,
/*argumentValues.getProperty(ArgumentNaming.ARG_STRING_OUTPUT_TYPE)*/null,
null,
null);
System.out.println(result);
}
}
This class produces same behaviour as JasyptPBEStringDecryptionCLI and works for same algorithms listed above and fails on stronger ones.
Here is the little error stacktrace:
Exception in thread "main" org.jasypt.exceptions.EncryptionOperationNotPossibleException
at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.decrypt(StandardPBEByteEncryptor.java:1055)
at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.decrypt(StandardPBEStringEncryptor.java:725)
at org.jasypt.intf.service.JasyptStatelessService.decrypt(JasyptStatelessService.java:595)
at com.example.HelloWorldApiUbuntu.TestingJasyptStringDecryptionCLI.main(TestingJasyptStringDecryptionCLI.java:12)
I know the problem is with jasypt and not my java because I ran this code to test encryption-decryption on my local with stronger algorithms and it works perfectly.
Edit 2: I also tried the solution given at https://github.com/melloware/jasypt, it gives me the same result.
It works with Jasypt 1.9.3 with additional parameter ivGeneratorClassName=org.jasypt.iv.RandomIvGenerator
Encryption:
java -cp ~/.m2/repository/org/jasypt/jasypt/1.9.3/jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI password=secret algorithm=PBEWITHHMACSHA1ANDAES_128 input=encryptThis ivGeneratorClassName=org.jasypt.iv.RandomIvGenerator
Decryption:
java -cp ~/.m2/repository/org/jasypt/jasypt/1.9.3/jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI password=secret algorithm=PBEWITHHMACSHA1ANDAES_128 input=j5oaiHBv5RB8MOxQekM/b/AMWxgOCmgB91X/ObBpyA0lr57z7ecrcVGZN0LtcFan ivGeneratorClassName=org.jasypt.iv.RandomIvGenerator
This is a bug in jasypt. it fixed with this patch. See this link too. I fixed my similar problem with this patch and version 1.9.4 CLI.
Related
I have a spring boot project (Running with Spring Boot v2.1.7.RELEASE, Spring v5.1.9.RELEASE ) and i'm trying to use Jasypt (2.1.2) to encrypt my database password.
I have an application.yml file that store my database user/password url & ect'
my pom.xml with the Jasypt looks like this:
<!--Jasypt-->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>2.1.2</version>
<scope>compile</scope>
</dependency>
My Main has the following annotation :
#EnableEncryptableProperties
my db configuration class :
Configuration
#PropertySource("classpath:application.yml")
#PropertySource("classpath:external.properties")
//#EncryptablePropertySource("classpath:external.properties")
//#EncryptablePropertySource("classpath:application.yml")
#EnableTransactionManagement
public class DBConfiguration {
#Value("${spring.datasource.pps-db.driver-class-name}")
private String driver;
#Value("${spring.datasource.pps-db.password}")
private String password;
I have generated the password using :
java -cp ~/.m2/repository/org/jasypt/jasypt/1.9.2/jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="Aa123456" password=secret algorithm=PBEWithMD5AndDES
----ENVIRONMENT-----------------
Runtime: Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 11.0.5+10-LTS
----ARGUMENTS-------------------
input: Aa123456
password: secret
algorithm: PBEWithMD5AndDES
----OUTPUT----------------------
c+E+8syd2Y1Tp1oNkJ2Xqk/9Pqt9l92B
in my application.yaml , at the database password location I placed the generated password I genereted using Jasypt.
ENC("myGeneratedPassword")
When i run my application everything is working OK , the password is decrypted and the application work ok .
my problem is when i have a strong password like : "A12$$T##!" and i . want to encrypt it ,
i get :
java -cp ~/.m2/repository/org/jasypt/jasypt/1.9.2/jasypt-1.9.2.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="A12$$T##!" password=secret algorithm=PBEWithMD5AndDESA1
-**bash: !": event not found**
I think it is because of the "!"
I have created a class to use a stronger password :
import org.jasypt.util.text.AES256TextEncryptor;
import java.security.NoSuchAlgorithmException;
public class JasyptPasswordEcryptor {
public static void main(String[] args) throws NoSuchAlgorithmException {
String password = "A12$$T##!";
AES256TextEncryptor encryptor = new AES256TextEncryptor();
encryptor.setPassword("secret");
String myEncryptedText = encryptor.encrypt(password);
System.out.println("Encrypted: "+myEncryptedText);
String plainText = encryptor.decrypt(myEncryptedText);
System.out.println("Decrypted: "+plainText);
}
}
and the result is :
Encrypted: QGPEnAN7MpkRC4opCHn8ztSMoiX8Imx0PT/HI7X6yVDtE/bIs/pTaAID76teJ6TG
Decrypted: A12$$T##!
when I apply my new encrypted password in my to application.yml :
password: ENC(QGPEnAN7MpkRC4opCHn8ztSMoiX8Imx0PT/HI7X6yVDtE/bIs/pTaAID76teJ6TG)
and then i try to run my application (mvn spring-boot:run) : i get an exception .. and i don't understand what is the problem .. (i think it has something to do with the java.security ,,, doesn't have a AES256TextEncryptor algorithm or something like that )
i get a null from the decrypt process :
here is the stack-trace:
Caused by: org.springframework.cache.Cache$ValueRetrievalException: Value for key 'spring.datasource.pps-db.password' could not be loaded using 'com.ulisesbocchio.jasyptspringboot.caching.CachingDelegateEncryptablePropertySource$$Lambda$400/0x0000000800721440#2dec0f40'
at org.springframework.cache.concurrent.ConcurrentMapCache.lambda$get$0 (ConcurrentMapCache.java:149)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent (ConcurrentHashMap.java:1705)
at org.springframework.cache.concurrent.ConcurrentMapCache.get (ConcurrentMapCache.java:144)
at com.ulisesbocchio.jasyptspringboot.caching.CachingDelegateEncryptablePropertySource.getProperty (CachingDelegateEncryptablePropertySource.java:34)
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:539)
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:151)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders (PropertyPlaceholderHelper.java:124)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders (AbstractPropertyResolver.java:237)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders (AbstractPropertyResolver.java:211)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0 (PropertySourcesPlaceholderConfigurer.java:175)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue (AbstractBeanFactory.java:851)
when i try again mvn apring-boot:run i get :
at java.lang.Thread.run (Thread.java:834)
Caused by: org.springframework.cache.Cache$ValueRetrievalException: Value for key 'spring.datasource.pps-db.password' could not be loaded using 'com.ulisesbocchio.jasyptspringboot.caching.CachingDelegateEncryptablePropertySource$$Lambda$401/0x000000080071f840#618d748'
at org.springframework.cache.concurrent.ConcurrentMapCache.lambda$get$0 (ConcurrentMapCache.java:149)
at java.lang.reflect.Method.invoke (Method.java:566)
at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run (AbstractRunMojo.java:543)
at java.lang.Thread.run (Thread.java:834)
Caused by: java.lang.IllegalStateException: either 'jasypt.encryptor.password' or one of ['jasypt.encryptor.private-key-string', 'jasypt.encryptor.private-key-location'] must be provided for Password-based or Asymmetric encryption
at com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor.lambda$null$5 (DefaultLazyEncryptor.java:54)
at java.util.Optional.orElseThrow (Optional.java:408)
at com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor.lambda$createDefault$6 (DefaultLazyEncryptor.java:54)
at java.util.Optional.orElseGet (Optional.java:369)
at com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor.createDefault (DefaultLazyEncryptor.java:50)
at com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor.lambda$null$2 (DefaultLazyEncryptor.java:38)
at java.util.Optional.orElseGet (O
I hope someone can help me out !!
Thank You all ,
I would like to share my ipnut.
when trying to encrypt the password please use the following :
when trying to encypt a string with "!" ,,, please use 'yourpassword!!!'
please use ' ' insted of " "
Use Version 1.9.3
java -cp ~/.m2/repository/org/jasypt/jasypt/1.9.3/jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input='Aa$$#123456!' password=secret algorithm=PBEWithMD5AndDES
and add this to your pom :
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
I hope it helped .
How can I check, in Java code, if the current JVM have unlimited strength cryptography available?
In the same spirit as the answer of Dan Cruz, but with a single line of code and without going trough exceptions:
boolean limit = Cipher.getMaxAllowedKeyLength("RC5")<256;
So a complete program might be:
import javax.crypto.Cipher;
public class TestUCE {
public static void main(String args[]) throws Exception {
boolean unlimited =
Cipher.getMaxAllowedKeyLength("RC5") >= 256;
System.out.println("Unlimited cryptography enabled: " + unlimited);
}
}
If you are on Linux and you have installed the JDK (but Beanshell is not available), you can check with the runscript command provided with the JDK.
jrunscript -e 'exit (javax.crypto.Cipher.getMaxAllowedKeyLength("RC5") >= 256 ? 0 : 1);'; echo $?
This returns a 0 status code if the Unlimited Cryptography is available, or 1 if not available. Zero is the correct 'success' return value for shell functions, and non-zero indicates a failure.
I think you could probably use Cipher.getMaxAllowedKeyLength(), while also comparing the cypher you're using to known lists of "good", secure cyphers, such as AES.
Here's a reference article that lists maximum key size jurisdiction limitations that were current as of Java 1.4 (these likely haven't changed, unless the law has also changed - see below).
If you are operating in a nation that has cryptographic export/import restrictions, you'd have to consult the law in your nation, but it's probably safe to assume in these situations that you don't have unlimited strength cryptography available (by default) in your JVM. Putting it another way, assuming you're using the official JVM from Oracle, and you happen to live in a nation against which the U.S. has leveled export restrictions for cryptography (and since Oracle is a United States company, it would be subject to these restrictions), then you could also assume in this case that you don't have unlimited strength available.
Of course, that doesn't stop you from building your own, and thereby granting yourself unlimited strength, but depending on your local laws, that might be illegal.
This article outlines the restrictions on export to other nations, from the Unites States.
The way how to check if restrictions apply is documented in the method Cipher.getMaxAllowedKeyLength:
If JCE unlimited strength jurisdiction policy files are installed, Integer.MAX_VALUE will be returned.
This means that if any value other than (or indeed lower than) Integer.MAX_VALUE is returned that restrictions do apply.
Even more information is in the JavaDoc of the method below:
/**
* Determines if cryptography restrictions apply.
* Restrictions apply if the value of {#link Cipher#getMaxAllowedKeyLength(String)} returns a value smaller than {#link Integer#MAX_VALUE} if there are any restrictions according to the JavaDoc of the method.
* This method is used with the transform <code>"AES/CBC/PKCS5Padding"</code> as this is an often used algorithm that is an implementation requirement for Java SE.
*
* #return <code>true</code> if restrictions apply, <code>false</code> otherwise
*/
public static boolean restrictedCryptography() {
try {
return Cipher.getMaxAllowedKeyLength("AES/CBC/PKCS5Padding") < Integer.MAX_VALUE;
} catch (final NoSuchAlgorithmException e) {
throw new IllegalStateException("The transform \"AES/CBC/PKCS5Padding\" is not available (the availability of this algorithm is mandatory for Java SE implementations)", e);
}
}
Note that since Java 9 the unlimited crypto policies are installed by default (with those affected by import / export regulations having to install the limited crypto policies instead). So this code would mainly be required for backwards compatibility and/or other runtimes.
This is a complete copy paste version to allow for testing
import javax.crypto.Cipher;
import java.security.NoSuchAlgorithmException;
class Test {
public static void main(String[] args) {
int allowedKeyLength = 0;
try {
allowedKeyLength = Cipher.getMaxAllowedKeyLength("AES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
System.out.println("The allowed key length for AES is: " + allowedKeyLength);
}
}
To run
javac Test.java
java Test
If JCE is not working output: 128
JCE is working something like: 2147483647
If you are using Linux, you can check it easily with this command
java -version ; \
echo 'System.err.println(javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding").getMaxAllowedKeyLength("AES"));' \
| java -cp /usr/share/java/bsh-*.jar bsh.Interpreter >/dev/null
If the output is something like that, unlimited strength cryptography is not available
java version "1.7.0_76"
Java(TM) SE Runtime Environment (build 1.7.0_76-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.76-b04, mixed mode)
128
You can check it in one step from the command line by using groovy :
groovysh -e 'javax.crypto.Cipher.getMaxAllowedKeyLength("AES")'
If the result is 2147483647, you have unlimited cryptography.
On older version of groovy, you have to remove the -e :
groovysh 'javax.crypto.Cipher.getMaxAllowedKeyLength("AES")'
NOTE: Please use jefflunt's answer or KonstantinSpirov's answer. This answer is not a valid answer since it will always return true. I am leaving this answer here only because it is referenced elsewhere in answers and comments and is useful as a reference only.
You could use the following to initialize a static final boolean somewhere that you can then use for testing unlimited crypto support (since AES 256-bit is only supported if the unrestricted policy is installed).
boolean isUnlimitedSupported = false;
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES", "SunJCE");
kgen.init(256);
isUnlimitedSupported = true;
} catch (NoSuchAlgorithmException e) {
isUnlimitedSupported = false;
} catch (NoSuchProviderException e) {
isUnlimitedSupported = false;
}
System.out.println("isUnlimitedSupported=" + isUnlimitedSupported);
// set static final variable = isUnlimitedSupported;
I recently had to do add a JCE check and my solution evolved to the following snippet. This was a groovy script, but it should be easy to convert to standard java method with a try catch. This has been tested with Java 7 & Java 8.
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.SecretKey;
// Make a blank 256 Bit AES Key
final SecretKey secretKey = new SecretKeySpec(new byte[32], "AES");
final Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// This line will throw a invalid key length exception if you don't have
// JCE Unlimited strength installed
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey);
// If it makes it here, you have JCE installed
I'm facing a VerifyError while creating a lot of xml-transformers (javax.xml.transform.Transformer) with fairly complex XSLT document (2000 conditions). Please see example:
public class XsltVerifyErrorTest {
private static final int MAX_ITERATIONS_COUNT = 1000000;
public static void main(String[] args) throws Exception {
final byte[] xslBytes = Files.readAllBytes(new File(args[0]).toPath());
for (int i = 0; i < MAX_ITERATIONS_COUNT; i++) {
System.out.println(String.format("Iteration %d", i));
final StreamSource xslSource = new StreamSource(new ByteArrayInputStream(xslBytes));
final Transformer transformer = TransformerFactory.newInstance().newTransformer(xslSource);
}
}
}
m49216#ubuntu:~/xslt-verify-error-test$ javac XsltVerifyErrorTest.java
m49216#ubuntu:~/xslt-verify-error-test$ java -showversion XsltVerifyErrorTest XsltVerifyErrorTest.xsl
openjdk version "1.8.0_162"
OpenJDK Runtime Environment (build 1.8.0_162-8u162-b12-0ubuntu0.16.04.2-b12)
OpenJDK 64-Bit Server VM (build 25.162-b12, mixed mode)
Iteration 0
Iteration 1
Iteration 2
...
Iteration 79
Iteration 80
Iteration 81
Exception in thread "main" java.lang.VerifyError: (class: GregorSamsa, method: TestTemplate signature: (Lcom/sun/org/apache/xalan/internal/xsltc/DOM;Lcom/sun/org/apache/xml/internal/dtm/DTMAxisIterator;Lcom/sun/org/apache/xml/internal/serializer/SerializationHandler;ILjava/lang/Object;)V) Illegal target of jump or branch
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
at java.lang.Class.getConstructor0(Class.java:3075)
at java.lang.Class.newInstance(Class.java:412)
at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getTransletInstance(TemplatesImpl.java:455)
at com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer(TemplatesImpl.java:486)
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTransformer(TransformerFactoryImpl.java:762)
at XsltVerifyErrorTest.main(XsltVerifyErrorTest.java:25)
Full example with test data can be found here.
The issue can be reproduced on many versions of jdk: 8u101, 8u121, 8u152, 8u161, 8u162.
Has anyone run into this problem? Does it look like a jvm bug?
Edit 1: JDK 9 is also affected, but it's much harder to reproduce the issue - it takes ~20 minutes and 660 iterations on my machine.
java version "9.0.4"
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)
Iteration 0
Iteration 1
Iteration 2
...
Iteration 658
Iteration 659
Iteration 660
Exception in thread "main" java.lang.VerifyError: (class: die/verwandlung/GregorSamsa, method: TestTemplate signature: (Lcom/sun/org/apache/xalan/internal/xsltc/DOM;Lcom/sun/org/apache/xml/internal/dtm/DTMAxisIterator;Lcom/sun/org/apache/xml/internal/serializer/SerializationHandler;ILjava/lang/Object;)V) Illegal target of jump or branch
at java.base/java.lang.Class.getDeclaredConstructors0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredConstructors(Class.java:3110)
at java.base/java.lang.Class.getConstructor0(Class.java:3315)
at java.base/java.lang.Class.newInstance(Class.java:530)
at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.getTransletInstance(TemplatesImpl.java:552)
at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.newTransformer(TemplatesImpl.java:583)
at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTransformer(TransformerFactoryImpl.java:817)
at XsltVerifyErrorTest.main(XsltVerifyErrorTest.java:19)
Edit 2: Works fine on JDK 10.
I got a chance to look at the problem deeper and finally solved this puzzle.
This is indeed a bug in JDK's BCEL library.
TransformerFactory generates the bytecode basing on the source XSLT. One of the bytecode generation steps is to remove temporary NOPs and relocate their targeters (branch instructions pointing to them).
Targeters are maintained in a HashSet. And here is the problem. Instruction class does not define hashCode, and its equals method works totally wrong for branches: two branch instructions are considered equal if their targets are the same. Of course, this is not true.
But the problem does not happen as long as branch hashCodes are different. Since these are actually default identity hashCodes, their collision chance is quite small. But after many iterations, given that generated method is very large, it finally happens: two different branch instructions with the same target obtain the same identity hashCodes, and one overwrites another due to collision.
Run the program with -XX:hashCode=2 (this will force degenerated identity hashCodes), and it will crash immediately.
The bug was fixed in BCEL-195 and integrated into JDK 10 in JDK-8163121.
Earlier JDK versions still have this bug, but fortunately you can use the following workaround. Just call Instruction.setComparator sometime at the application startup:
import com.sun.org.apache.bcel.internal.generic.*;
...
Instruction.setComparator((i1, i2) -> {
if (i1 instanceof BranchInstruction) {
return i1 == i2;
}
return InstructionComparator.DEFAULT.equals(i1, i2);
});
I installed netbeans 8.2 on Centos 7.
I get this error:
java.lang.RuntimeException: failed to load system cursor: DnD.Cursor.CopyDrop : cannot load system cursor: CopyDrop.32x32
at java.awt.dnd.DragSource.load(DragSource.java:135)
at java.awt.dnd.DragSource.<clinit>(DragSource.java:148)
Java version :
openjdk version "1.8.0_111"
OpenJDK Runtime Environment (build 1.8.0_111-b15)
OpenJDK 64-Bit Server VM (build 25.111-b15, mixed mode)
How can I fix this?
I had the problem on Kali in virtualbox.
If your OS is in virtualbox, the solotion is shutdown the OS.
Then turn off "Enable 3D Acceleration" under Machine -> Settings -> Dispaly.
Start your OS and enjoy!
It seems the bug is solved with java 8u152 b05.
The following code passes 8u152, but throws the mentioned exception using Java 8u131:
public static void main(String[] args) {
DragSource.getDefaultDragSource();
}
Currently 8u152 is available in "JDK 8 Updates Early-Access Builds":
http://jdk.java.net/8/
My Java code uses Drag&Drop in JTree, which get broken after upgrade from CentOS 6 to CentOS 7. Same hardware, same OpenJDK, same Java code, but different graphic driver. The workaround with kernel command line setting "nomodeset" helps, but causes poor graphic & flickering.
Here is a pure Java workaround:
//workaround for used Drag&Drop cursors which are unsupported by graphics driver
public static void initUnsupportedCursors() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException
{
String cursors[] = new String[]{
"DnD.Cursor.CopyDrop",
"DnD.Cursor.MoveDrop",
"DnD.Cursor.LinkDrop",
"DnD.Cursor.CopyNoDrop",
"DnD.Cursor.MoveNoDrop",
"DnD.Cursor.LinkNoDrop"
};
List <String> unsupportedCursors = new ArrayList <String>();
for (String c : cursors)
{
try
{
if (Toolkit.getDefaultToolkit().getDesktopProperty(c) == null)
{
throw new Exception("Can't find cursor " + c);
}
}
catch (Exception e)
{
unsupportedCursors.add(c);
}
}
if (!unsupportedCursors.isEmpty())
{
Field propsFiled = Toolkit.class.getDeclaredField("desktopProperties");
propsFiled.setAccessible(true);
Map props = (Map) propsFiled.get(Toolkit.getDefaultToolkit());
for (String unsupportedCursor : unsupportedCursors)
{
System.out.println("Replacing unsupported " + unsupportedCursor + " by " + Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
props.put(unsupportedCursor, Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
}
This has been reported as a bug : Bug 257554 - RuntimeException: failed to load system cursor: DnD.Cursor.CopyDrop : cannot load system cursor: CopyDrop.32x32
It turns out that it is linked to a reported bug in Unity-Mir : Java applications are missing X11 resources - XQueryBestCursor return 0,0.
From the comments , the JDK version along with the old XMir (which is not supported anymore) was responsible of that .
Anyway, it is fixed by the last XMir versions.
This would be a bug in Java, where it is unable to deal with the Xorg
software cursor. Which is a problem unrelated to Mir really. Mir just
puts X in a (valid) mode where the bug is triggered.
Although, we could work around the Java bug by implementing full
hardware cursor support in XMir...
and
XMir 1.0 (the old Xorg extension) is now deprecated and is not being
maintained or fixed. It is replaced by the new 'Xmir' binary (package
'xmir') introduced in Ubuntu 15.10 wily.
and
Note: The new Xmir uses the hardware cursor (where available on
desktop). So if this bug still exists at all, it would only be on
mobile (Android Mir platform).
You should consider upgrading to the "new" version.
I found the solution.
1- Edit following file:
nano /etc/default/grub
2- Replace rhgb quiet to nomodeset.
3- Run on terminal grub2-mkconfig -o /boot/grub2/grub.cfg
4- Reboot.
Actually this not solve the problem. It's only ignore it.
I have a simple Xades/BES implementation and two situations.
On Windows 7 32Bit
with java
java version "1.7.0_25"
Java(TM) SE Runtime Environment (build 1.7.0_25-b17)
Java HotSpot(TM) Client VM (build 23.25-b01, mixed mode)
On Windows 2008 Server 64 Bit, and with the same JVM.
My application works perfectly fine on 32 bit Windows 7, however when I try to run the compiled code in Windows 2008 Server I get an error:
javax.crypto.BadPaddingException: Data must start with zero
at sun.security.rsa.RSAPadding.unpadV15(Unknown Source)
at sun.security.rsa.RSAPadding.unpad(Unknown Source)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:349)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:382)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
Problematic code field is as follows:
public static byte[] getDecryptedSignatureValue(XMLSignature signature) throws XadesElementException, InvalidKeyException
{
byte[] signatureValue = null;
try {
KeyInfo keyInfo = signature.getKeyInfo();
PublicKey key = keyInfo.getPublicKey();
Cipher cipher = getCipher("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
signatureValue = signature.getSignatureValue();
byte[] cipherData = cipher.doFinal(signatureValue);
return cipherData;
} catch (KeyResolverException | XMLSignatureException | IllegalBlockSizeException | BadPaddingException ex) {
Logger.getLogger(KeyUtils.class.getName()).log(Level.SEVERE, null, ex);
Logger.getLogger(KeyUtils.class.getName()).log(Level.SEVERE, null, "SignatureValue:"+ BaseUtils.toBase64String(signatureValue));
} finally {
}
return null;
}
The only thing I can come up with is the architecture difference. Am I missing something here? What can be the problem?
Thanks in advance.
EDIT:
Here are my new findings.
1. I have tested my application on Windows 7 64 bit and there was no problem, while signing and verifying.
2. More interestingly, I have tested the application on another Windows 2008 Server 64 bit and it worked with a success.
I think there is a configuration setting for something but I could not figure it out what.
This is likely due to the chosen provider and/or provider implementation. Note that there is a difference between PKCS#1 padding for encryption (EME-PKCS1-v1_5 decoding) and PKCS#1 padding for signature verification (EMSA-PKCS1-v1_5 encoding). Some providers will choose a padding depending on the key type (public or private), others will keep to a single padding scheme depending if you are using Cipher or Signature.
If possible try and use Signature for signature verification, not Cipher decryption with a public key. Otherwise check which providers are chosen (using e.g. Cipher.getProvider() and try to find one that works. Note that - as you may already have discovered - it depends on the implementation, not on the interface specification if decryption succeeds or fails.
So currently it is trying to decode this:
EM = 0x00 || 0x02 || PS || 0x00 || M
with a random, nonzero PS and message M
You expect however to verify this:
EM = 0x00 || 0x01 || PS || 0x00 || T
with a PS with values FF, and T being an ASN.1 DER encoded algorithm OID and hash value.