i am trying to put a basic digital signature on a pdf file. i am trying to use the code provided on the itext website.The code is as follows-
public class DigiSign {
public static void main(String a[])
{
try {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream("C:\\WSR\\keystore.ks"), "password".toCharArray());
String alias = (String) ks.aliases().nextElement();
PrivateKey key = (PrivateKey) ks.getKey(alias, "password".toCharArray());
java.security.cert.Certificate[] chain = ks.getCertificateChain(alias);
PdfReader reader = new PdfReader("C:\\WSR\\a.pdf");
FileOutputStream fout = new FileOutputStream("C:\\WSR\\signed.pdf");
PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');
PdfSignatureAppearance sap = stp.getSignatureAppearance();
sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
sap.setReason("arpit");
sap.setLocation("arpit");
// comment next line to have an invisible signature
sap.setVisibleSignature(new Rectangle(10, 10, 20, 20), 1, null);
stp.close();
} catch (Exception ex) {
Logger.getLogger(DigiSign.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
i created the key using
keytool -genkey -keyalg RSA -alias myname -keypass password -keystore keystore.ks -dname "cn=Paulo Soares, c=PT"
and set abc123 as my password.
Now when i run this code i get this exception
Exception in thread "main" java.lang.NoClassDefFoundError: org/bouncycastle/asn1/DEREncodable
at com.lowagie.text.pdf.PdfSignatureAppearance.getAppearance(Unknown Source)
at com.lowagie.text.pdf.PdfSignatureAppearance.preClose(Unknown Source)
at com.lowagie.text.pdf.PdfSignatureAppearance.preClose(Unknown Source)
at com.lowagie.text.pdf.PdfStamper.close(Unknown Source)
at DigiSign.main(DigiSign.java:42)
Caused by: java.lang.ClassNotFoundException: org.bouncycastle.asn1.DEREncodable
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
What am i doing wrong?
(Just to formulate the cause as an answer which has been presented as a comment before:)
For security low level operations iText is based on the BouncyCastle libraries. This especially concerns creation and verification of integrated PDF signatures but also handling of encrypted documents. In these use cases, therefore, the appropriate BouncyCastle provider libs are required on the class path of the application.
The primary exception information
java.lang.NoClassDefFoundError: org/bouncycastle/asn1/DEREncodable
indicates that this requirement is not fullfilled, either BouncyCastle is not present at all or at least not present in the required version. This meanwhile has been confirmed by #user1946152 for his configuration.
P.S.: Obviously in the case at hand the OP still uses a pre-5.x version of iText. While there are certain conditions enforcing this (e.g. a management not being willing to decide when to buy a license sigh), you should definitively update to a current version of iText. There meanwhile have been many big changes, especially in the fields of electronic signatures, content parsing, and creation of PDF/A documents.
Related
I generated a keystore with the following command:
keytool -genkeypair -keystore test.ks -storetype pkcs12
Then I run the following test (base64 represents that keystore I created):
private static final String KEYSTORE_BASE64 = "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";
#Test
public void testWithoutBouncyCastle() throws Exception {
doTest();
}
private void doTest() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException {
byte[] keyStoreBytes = Base64.getDecoder().decode(KEYSTORE_BASE64);
KeyStore keystore = KeyStore.getInstance("jks");
keystore.load(new ByteArrayInputStream(keyStoreBytes), "secret".toCharArray());
Key key = keystore.getKey("mykey", "secret".toCharArray());
assertThat(key, is(notNullValue()));
}
The test passes.
Now I do the same, but first I add BouncyCastle provider at position 2 (1-based):
#Test
public void testWithBouncyCastle() throws Exception {
Security.insertProviderAt(new BouncyCastleProvider(), 2);
doTest();
}
The test fails:
java.io.IOException: keystore password was incorrect
at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2059)
at sun.security.provider.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:238)
at sun.security.provider.JavaKeyStore$DualFormatJKS.engineLoad(JavaKeyStore.java:70)
at java.security.KeyStore.load(KeyStore.java:1445)
at PBETest.doTest(PBETest.java:43)
at PBETest.testWithBouncyCastle(PBETest.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.security.UnrecoverableKeyException: failed to decrypt safe contents entry: javax.crypto.BadPaddingException: pad block corrupted
... 28 more
A couple of side notes on store type
Please note that the keystore is a PKCS12 store and I try to load it as a JKS. A library I have to use does the same, hence the code. Also, JDK seems to be prepared: for getInstance("jks") KeyStoreDelegator class is used which first tries to load the 'thing' it was given as a JKS store, then it falls back to PKCS12 path.
Another observation is that getInstance("pkcs12") works correctly in both cases (without and with BouncyCastle). The code used in this case (not KeyStoreDelegator) is different from the pkcs12-related path of JKS scenario, and probably because of that it runs successfully.
Back to the subject
The problem occurs when the PKCS12-related branch tries to decrypt something using the keystore password. It does so by first converting the keystore password to a PBE key
private SecretKey getPBEKey(char[] var1) throws IOException {
SecretKey var2 = null;
try {
PBEKeySpec var3 = new PBEKeySpec(var1);
SecretKeyFactory var4 = SecretKeyFactory.getInstance("PBE");
var2 = var4.generateSecret(var3);
var3.clearPassword();
return var2;
} catch (Exception var5) {
throw new IOException("getSecretKey failed: " + var5.getMessage(), var5);
}
}
and then using this key (along with algorithm parameters) to decrypt:
SecretKey key = this.getPBEKey(var2);
Cipher cipher = Cipher.getInstance(var27.toString());
cipher.init(2, key, var28);
var38 = cipher.doFinal(var38);
Sorry for horrible variable names, this is what IDE gives me. var2 is a char[] representing keystore password, var27.toString() gives '1.2.840.113549.1.12.1.6', var28 contains algorithm parameters.
doFinal() is the call that fails.
In the 'without BC' scenario, Cipher instance is from SunJCE provider (and works correctly); in the 'with BC' scenario, Cipher instance is provided by BC and fails.
Here is the list of providers after the BouncyCastle is installed:
SUN
BC
SunRsaSign
SunEC
SunJSSE
SunJCE
SunJGSS
SunSASL
XMLDSig
SunPCSC
So BC is before SunJCE, hence it wins the contest and provides a Cipher.
Unfortunatly, it is nearly impossible to avoid that 'load PKCS12 as JKS' course of action; also I would like to avoid moving BouncyCastle provider to the end of the providers list as this might break some other code.
The questions are:
Is this a bug in BouncyCastle?
Is there any way to work around the problem?
Java is Oracle JDK 1.8.0_161, BouncyCastle version is 1.54 (I also tried 1.57 which seems to be the most recent version, but I get the same results).
I am learning Bouncycastle and facing some problems.
Is it possible to combine multiple security provider, such as I have modified my java.security like:
security.provider.11=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
security.provider.12=org.bouncycastle.jce.provider.BouncyCastleProvider
security.provider.13=org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider
Then in my server side I have written:
...
SSLContext sslContext = SSLContext.getInstance("TLS", "BCJSSE");
KeyManagerFactory keyMgrFact = KeyManagerFactory.getInstance(
"PKIX", "BCJSSE");
keyMgrFact.init(Utils.createServerKeyStore(), Utils.SERVER_PASSWORD);
...
It will throw an error in:
public static KeyPair generateRootKeyPair()
throws Exception {
KeyFactory kFact = KeyFactory.getInstance("RSA", "BC");
return new KeyPair(
kFact.generatePublic(new X509EncodedKeySpec(rootPublicKey)),
kFact.generatePrivate(new PKCS8EncodedKeySpec(rootPrivateKey)));
}
Error msg:
Exception in thread "main" java.lang.NoSuchFieldError: id_hmacWithSHA3_224
at org.bouncycastle.jcajce.provider.digest.SHA3$Mappings.configure(Unknown Source)
at org.bouncycastle.jce.provider.BouncyCastleProvider.loadAlgorithms(Unknown Source)
at org.bouncycastle.jce.provider.BouncyCastleProvider.setup(Unknown Source)
at org.bouncycastle.jce.provider.BouncyCastleProvider.access$000(Unknown Source)
at org.bouncycastle.jce.provider.BouncyCastleProvider$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at org.bouncycastle.jce.provider.BouncyCastleProvider.<init>(Unknown Source)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at sun.security.jca.ProviderConfig$2.run(ProviderConfig.java:221)
at sun.security.jca.ProviderConfig$2.run(ProviderConfig.java:206)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.jca.ProviderConfig.doLoadProvider(ProviderConfig.java:206)
at sun.security.jca.ProviderConfig.getProvider(ProviderConfig.java:187)
at sun.security.jca.ProviderList.getProvider(ProviderList.java:233)
at sun.security.jca.ProviderList.getIndex(ProviderList.java:263)
at sun.security.jca.ProviderList.getProviderConfig(ProviderList.java:247)
at sun.security.jca.ProviderList.getProvider(ProviderList.java:253)
at sun.security.jca.GetInstance.getService(GetInstance.java:81)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:206)
at java.security.KeyFactory.getInstance(KeyFactory.java:211)
at Utils.generateRootKeyPair(Utils.java:103)
at Utils.createRootCredential(Utils.java:199)
at Utils.createServerKeyStore(Utils.java:273)
at TLSServerExample.main(TLSServerExample.java:19)
I have researched it for couples of days, I thought the reason for this problem is there is some collisions between packages:
bc-fips-1.0.0
bcprov-jdk15on-158.jar
bctls-fips-1.0.2.jar
How to fix that?
Thx in advancee!
It is mostly because when your application is starting up, the old version of bouncy castle classes are loaded based on the class loading sequence in java.
You can check from which jar bouncy castle classes are loading by adding -verbose:class to command line as mentioned in https://stackoverflow.com/a/6686792 when you start your app. It will print a lot of lines so you will have to search for terms like bcp, com.bouncycastle etc.
For me, it was because of bouncy castle related jars were present in java lib directory (/path/to/java/jdk/jre/lib/ext/). Go to /path/to/java/jdk/jre/ and run below command on terminal if you are using linux.
find . -type f -name "*.jar*" | grep bcp
which will tell us if bouncy castle jars are present or not.
If present you will see below output
./lib/ext/bcprov-jdk15on-1.50.jar
You can either upgrade it or remove it (if it does not affect your/other services on the same box)
I was getting similar error with bouncycastle, my case was mismatch or its version
In 2007 I wrote a tiny java application that would digitally sign several different PDF documents (with image of my signature). I has been working great until I upgraded to Java 8.
I am now getting errors:
IOException: Unable to read private key from keystore
e: java.io.IOException: unsupported PKCS12 secret value type 48
I seems now that Java 8 PKCS12 cannot store secret key entries. This is a critical application for me. I use it hundreds of times a day.
How can I work around this issue?
Here is an abridged version of the critical code:
String appPath = SignPDF.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String keytype = "pkcs12";
String keyfile = appPath + "DanVokt.pfx";
String keyimage = appPath + "DanVokt.png";
String keypass = "xxxxxxxxx";
KeyStore ks = KeyStore.getInstance(keytype);
ks.load(new FileInputStream(keyfile), keypass.toCharArray());
String alias = (String)ks.aliases().nextElement();
PrivateKey key = (PrivateKey)ks.getKey(alias, keypass.toCharArray());
Certificate[] chain = ks.getCertificateChain(alias);
PdfReader reader = new PdfReader(ifile);
FileOutputStream fout = new FileOutputStream(ofile);
PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');
PdfSignatureAppearance sap = stp.getSignatureAppearance();
sap.setCrypto(key, chain, null, PdfSignatureAppearance.SELF_SIGNED);
// allow only printing
stp.setEncryption(null, keypass.getBytes(), PdfWriter.ALLOW_PRINTING,
PdfWriter.STANDARD_ENCRYPTION_128);
stp.close();
Here is a stack tace:
$ signpdf "Timelog*" 1
Processing File: "Timelog - Current Week.pdf" 1
IOException: Unable to read private key from keystore
java.io.IOException: unsupported PKCS12 secret value type 48
at sun.security.pkcs12.PKCS12KeyStore.loadSafeContents(PKCS12KeyStore.java:2197)
at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2025)
at java.security.KeyStore.load(KeyStore.java:1445)
at SignPDF.main(SignPDF.java:61)
Here is the version and build:
$ java -version
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
Attempt to use keytool to view PKCS12 (.pfx) file:
$ keytool -list -keystore DanVokt.pfx -storepass XXXXXXXX -storetype PKCS12 -v
keytool error: java.io.IOException: unsupported PKCS12 secret value type 48
java.io.IOException: unsupported PKCS12 secret value type 48
at sun.security.pkcs12.PKCS12KeyStore.loadSafeContents(PKCS12KeyStore.java:2197)
at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2025)
at java.security.KeyStore.load(KeyStore.java:1445)
at sun.security.tools.keytool.Main.doCommands(Main.java:795)
at sun.security.tools.keytool.Main.run(Main.java:343)
at sun.security.tools.keytool.Main.main(Main.java:336)
I did a bit of digging. The change appears to have happened as part of some Keystore API enhancements. (They were committed in January 2013)
The specific test is this:
} else if (bagId.equals((Object)SecretBag_OID)) {
DerInputStream ss = new DerInputStream(bagValue.toByteArray());
DerValue[] secretValues = ss.getSequence(2);
ObjectIdentifier secretId = secretValues[0].getOID();
if (!secretValues[1].isContextSpecific((byte)0)) {
throw new IOException(
"unsupported PKCS12 secret value type "
+ secretValues[1].tag);
}
where !(isContextSpecific() is checking the "tag" of the DERvalue to make sure that it doesn't have the CONTEXT bit set. This test is failing.
It would seem that the work-around would be to store these secret keys as DER values with a tag type that doesn't have bit 0x80 set.
See also:
PKCS12KeyStore.java - https://github.com/frohoff/jdk8u-jdk/blob/master/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java
DERValue.java - https://github.com/frohoff/jdk8u-jdk/blob/master/src/share/classes/sun/security/util/DerValue.java
[RESOLVED]
I created a java keystore (JKS) file:
keytool -genkey -keyalg RSA -keysize 2048 -keystore danv_keystore.jks -alias danv
Of course this created a new private key and new certificate but that is currently not an issue since it is self-signed. I am a bit confused on how to use my own private key and certificate. Any examples?
I then simply changed the keytype and keyfile:
// String keytype = "pkcs12";
String keytype = "JKS";
// String keyfile = appPath + "DanVokt.pfx";
String keyfile = appPath + "danv_keystore.jks";
And voila! It is now working again.
I compiled it under J8 and J7 and it works in both environments.
Thanks!
I need a .p12 file in order to authenticate with Apple's notification servers, and I have found some problems. As I understand, I need to generate the .csr and my private key identifying my machine. So I need to execute a command like this in my local machine:
*$:~/Escritorio/curro/certificados$ openssl req -out CSR.csr -new -newkey rsa:2048 -nodes -keyout privateKey.key
Generating a 2048 bit RSA private key
writing new private key to 'privateKey.key'
Now, with my CSR.csr file, I need to login in to:
https://developer.apple.com/account/ios/certificate/certificateCreate.action?formID=62653259
then I provide the .csr file generated before and the system
gives me a .cer file (aps_development.cer) . Now, with this .cer file I have to generate it .p12 equivalent file. In order to do that, I need to make a .pem file starting from that .cer generated file from Apple. This is the command:
#Ubuntu:~/Escritorio/curro/certificados$ openssl pkcs12 -export -inkey privateKey.key -in developer_identity.pem -out iphone_dev.p12
Enter Export Password:
Verifying
Enter Export Password:
After that I have a .p12 file and I need to initialize an ApnsService instance,
#Component
public class NotificationServer implements Runnable, BeanFactoryAware {
#Autowired
// APNS channel
private ApnsService serviceApns;
private String apns_payload;
#PostConstruct
public void init() {
// build apns service path_to_apns_certificate, absolute path .p12 file
String path_to_apns_certificate = config.getProperty("a-path");
//pass used to generate the .p12 file
String password_apns_cert = config.getProperty("a-path");
log.debug("path_to_apns_certificate: " + path_to_apns_certificate);
//keep an eye with this!, this builder is non thread safe!
ApnsServiceBuilder apnsbuilder = new ApnsServiceBuilder();
String sMaxConections = config.getProperty("maxConections");
log.debug("sMaxConections: " + sMaxConections);
int maxConections = Integer.parseInt(sMaxConections);
apnsbuilder.asPool(maxConections );
String connectWithAppleApns = config.getProperty("apns.production");
log.debug("connectWithAppleApns: " + connectWithAppleApns);
apnsbuilder.withAppleDestination(new Boolean(connectWithAppleApns));
//here the exception is launched!
apnsbuilder.withCert(path_to_apns_certificate, password_apns_cert);
serviceApns =apnsbuilder.build();
}
}
Here is the error message:
Caused by: com.notnoop.exceptions.InvalidSSLConfig: java.io.IOException: failed to decrypt safe contents entry: javax.crypto.BadPaddingException: Given final block not properly padded
at com.notnoop.apns.internal.Utilities.newSSLContext(Utilities.java:88)
at com.notnoop.apns.ApnsServiceBuilder.withCert(ApnsServiceBuilder.java:167)
at com.notnoop.apns.ApnsServiceBuilder.withCert(ApnsServiceBuilder.java:134)
at com.*****.agenda.utils.NotificationServer.init(NotificationServer.java:122)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:346)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:299)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:132)
... 164 more
Caused by: java.io.IOException: failed to decrypt safe contents entry: javax.crypto.BadPaddingException: Given final block not properly padded
at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1304)
at java.security.KeyStore.load(KeyStore.java:1214)
at com.notnoop.apns.internal.Utilities.newSSLContext(Utilities.java:85)
... 174 more
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.PKCS12PBECipherCore.implDoFinal(PKCS12PBECipherCore.java:355)
at com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndRC2_40.engineDoFinal(PKCS12PBECipherCore.java:462)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:1295)
... 176 more
Can anyone give my any perspective on this?
I response myself. That error involves an error with the pass or the user, in my case the pass that was saved with quotes!! days without seen that mistake.
I'm currently working on getting a Java application (JRE 1.5+) to talk to a Windows 2008 OCSP Responder, and I'm getting a strange error on trying to read the Responder's signing cert.
I get the following exception on trying to perform an OCSP validation.
Caused by: java.security.cert.CertificateParsingException: java.io.IOException: short read on DerValue buffer
at sun.security.x509.X509CertInfo.<init>(Unknown Source)
at sun.security.x509.X509CertImpl.parse(Unknown Source)
at sun.security.x509.X509CertImpl.<init>(Unknown Source)
at sun.security.provider.certpath.OCSPResponse.<init>(Unknown Source)
at sun.security.provider.certpath.OCSPChecker.check(Unknown Source)
... 6 more
Caused by: java.io.IOException: short read on DerValue buffer
at sun.security.util.DerValue.getOctetString(Unknown Source)
at sun.security.x509.Extension.<init>(Unknown Source)
at sun.security.x509.CertificateExtensions.init(Unknown Source)
at sun.security.x509.CertificateExtensions.<init>(Unknown Source)
at sun.security.x509.X509CertInfo.parse(Unknown Source)
... 11 more
This suggested there was a problem reading the signing cert, so I tried importing that separately using a method similar to the below:
public static List<Certificate> readCerts(String certFile,
CertificateFactory cf, boolean withCRL) throws Exception {
FileInputStream fis = new FileInputStream(certFile);
BufferedInputStream bis = new BufferedInputStream(fis);
List<Certificate> certs = new LinkedList<Certificate>();
while (bis.available() > 0) {
Certificate cert = cf
.generateCertificate(bis);
X509Certificate cx509 = (X509Certificate) cert;
certs.add(cert);
}
return certs;
}
which gave me the same error. This only seems to happen with certificates generated from the OCSP Signing template, user certificates can be read fine.
Has anyone else encountered similar problems with X509 support in Java?
Regards,
Tom
UPDATE: The cert I'm having trouble with is as below:
-----BEGIN CERTIFICATE-----
MIIDzDCCArSgAwIBAgIKYQWrDAAAAAAABjANBgkqhkiG9w0BAQUFADBFMRMwEQYK
CZImiZPyLGQBGRYDaW50MRUwEwYKCZImiZPyLGQBGRYFbG9ucWExFzAVBgNVBAMT
DmxvbnFhLVRFLUNBLUNBMB4XDTA5MDkyMTE2NDIxNloXDTA5MTAwNTE2NDIxNlow
GjEYMBYGA1UEAxMPdGUtY2EubG9ucWEuaW50MIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEA6rYO7X/PztBE2Do9u95ws3Ob86cySJ1iLrHLSF+VjvTQkZ3J
e0uKxoK4doSikqCZH9zXZ6qFFVMZlzq/FnIP9TLhv3uFom0y+Z0HmPAW7RtrZ8R6
1EAmcQDGpyRhzCWJqrEzgbW1v1QtF854kium97GwUWnVijGv3jQqT3hbmD7++9lh
9ILaLXMAKdTFpL1ao2eHWYf2mChRpuAox2juO1g4xjot9GXsEMhTwAg9F/pZnbKE
hhpeo1c0kgP3uus7ULlwdRnZ4O+tp79GeVKsdJbphmnC6Fc/PdT0KuHSk9Q0v192
Ger5nTQaZk/dmsyGBd8g4Q+0g0Ri+wgpUUsykQIDAQABo4HoMIHlMDYGCSsGAQQB
gjcVBwQpMCcGHysGAQQBgjcVCIHPgWyXxQ2ChYcyg8LhMoWky3ppASACAWUCAQAw
EwYDVR0lBAwwCgYIKwYBBQUHAwkwDgYDVR0PAQH/BAQDAgeAMBsGCSsGAQQBgjcV
CgQOMAwwCgYIKwYBBQUHAwkwDQYJKwYBBQUHMAEFBAAwHQYDVR0OBBYEFNblspp7
Hu07mraeMSyuBUTUnbl3MB8GA1UdIwQYMBaAFK/r521FB+GNls/fe8hrNE8UpQhv
MBoGA1UdEQQTMBGCD3RlLWNhLmxvbnFhLmludDANBgkqhkiG9w0BAQUFAAOCAQEA
FASEVcUJQlrmCD/ysycOxAIAoc2BVLhteOMoZ7V65a5/+Q5JM7Od+gKqoxLVrjb2
BDLlDFp5U8CirQ4lyWV5i1gQpLFTDcjgonp9Ky50KA0Ginn5CmTELB2THwFSQwfm
OFenSaV1mAcEzdyp/hi2xSuMqhveSanQFD0r6y45oZsd9ubdFEWI6nBRrj4hhfw0
Wo2GKUgslXqAqEezdin5JNgsPdj3qsi4+U4llyrd3gG20eoWzGHF4h7wfFiQV+fs
yEPY06Rg9G9m3GlIv+7Gp3sixb+cvZe+e0gO32mVRydTXMaAZu7ZiFk3M6AqxfDw
dO//eCu2dZCLTw6xTbUc9A==
-----END CERTIFICATE-----
I assume you get your factory like this,
cf = CertificateFactory.getInstance("X509");
The default X509 factory has many limitations. It looks like your cert contains an extension the factory doesn't know how to parse. If you post the cert, I can help you to identify the offending extension.
EDIT: The offending extension is
1.3.6.1.5.5.7.48.1.5 - id-pkix-ocsp-nocheck
The only option is to remove this from the cert with Java built-in JCE. You can also try another JCE like BouncyCastle.