Digital Signature for Acrobat - java

Trying to get an authenticated digital signature onto a PDF in Acrobat, by using iText. The way we want to grab someone digital signature is through there cert, which in our case we would be getting the user cert through their CAC's. Having issue with the ks.load() where I am getting an error: "Invalid key store format". Wonder if it is even possible without using any cmd? Would prefer a solution that involves Java.
String KEYSTORE = ReadConfig.get("WebRoot")+"mods/Reports/sources/t_cert.jks";
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(KEYSTORE), null);
String alias = (String) ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, null);
Certificate[] chain = ks.getCertificateChain(alias);

Related

Java JKS API: keyStore is empty

I'm trying to get my PKI material using KeyStore API. The content of my keystore is:
My code is:
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(this.getClass().getResourceAsStream(this.boConfiguration.getUiPortalAdminKeyStore()),
this.boConfiguration.getUiPortalAdminKeyPassword().toCharArray()
);
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
LOG.debug(aliases.nextElement());
}
Key pK = ks.getKey(
"gestio",
this.boConfiguration.getUiPortalAdminKeyStorePassword().toCharArray()
);
Key pKey = ks.getKey("gestio", this.boConfiguration.getUiPortalAdminKeyStorePassword().toCharArray());
Certificate[] certs = ks.getCertificateChain("gestio");
Certificate cert = ks.getCertificate("gestio");
My problem is that all ks.get* returns me null. However, keystore is not empty. Also, getAlias method returns me an empty enumeration.
Any ideas?
This is the content according keystore explorer:

Signing a X509Certificate with another Self Signed x509Certificate [acting as CA]

I have created a self-signed certificate and encoded it successfully. But I want to sign this certificate with another self signed certificate, which will act as a Certification Authority.
The code is below:
X509Certificate caCert;
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(null, null);
CertAndKeyGen keypair = new CertAndKeyGen("RSA", "SHA1WithRSA", null);
X500Name x500Name = new X500Name(commonName, organizationalUnit, organization, city, state, country);
keypair.generate(keysize);
PrivateKey privKey = keypair.getPrivateKey();
X509Certificate[] chain = new X509Certificate[1];
chain[0] = keypair.getSelfCertificate(x500Name, new Date(), (long) validity * 24 * 60 * 60);
keypair.getCertRequest(x500Name);
keyStore.setKeyEntry(alias, privKey, keyPass, chain);
keyStore.store(new FileOutputStream("test.keystore"), keyPass);
caCert = (X509Certificate) keyStore.getCertificate(alias);
File crtFile = new File("saif.der");
writeCertificate(new FileOutputStream(crtFile), caCert);
Create the user certificate using X509V3CertificateGenerator class of bouncycastle. Then finally use the X509V3CertificateGenerator.generateX509Certificate(privateKey) method to generate the X509Certificate. Here the privateKey will be the self signed certificate's private key from PKCS12. Save the user certificate in PKCS12 format.

java.security.UnrecoverableKeyException: Get Key failed: null while reading .p12 file in Java

I am trying to extract the private key from a .p12 file downloaded from Google Service Account Console.
I am reading this .p12 from the folder location and creating the KeyStore object.
KeyStore myStore = null;
FileInputStream in_cert = new FileInputStream(
"D://Google Analytics//login//GA//6aa55af54232dfa60b60a908ff0138bba1147d63-privatekey.p12");
myStore = KeyStore.getInstance("PKCS12");
myStore.load(in_cert, null); // if i give "changeit" as the password(hopefully the default keystore password) gets the exception "java.security.UnrecoverableKeyException: Get Key failed: Given final block not properly padded. If null is passed as an argument the program runs fine with output as "privatekey""
Enumeration<String> aliases = myStore.aliases();
String alias = "";
System.out.println(myStore.aliases());
while (aliases.hasMoreElements()) {
System.out.println(aliases.nextElement()); // prints privatekey
}
java.security.PrivateKey privateKey = (PrivateKey) myStore.getKey("privatekey", null); // gives exception "java.security.UnrecoverableKeyException: Get Key failed: null"
What's wrong that I am doing?
I need the private key as a signer for creating Google JSON Web Token.
Just in case somebody lands here, as mentioned by #prathamesh_mb, you need to provide the password while loading the key.
PrivateKey privateKey = (PrivateKey) myStore.getKey("privatekey", "yourpasswordhere".toCharArray());

My Signature Provider - something wrong happens

I have method in order to sign document.
public static void sign(String src, String dest,
java.security.cert.Certificate[] chain, PrivateKey pk,
String digestAlgorithm, String provider, CryptoStandard subfilter,
String reason, String location) throws GeneralSecurityException,
IOException, DocumentException, com.itextpdf.text.DocumentException {
// Creating the reader and the stamper
PdfReader reader = new PdfReader(src);
FileOutputStream os = new FileOutputStream(dest);
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
// Creating the appearance
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
appearance.setVisibleSignature(new Rectangle(0, 100, 50, 300), 1, "sig");
// Creating the signature
ExternalDigest digest = new BouncyCastleDigest();
ExternalSignature signature = new PrivateKeySignature(pk, digestAlgorithm, provider);
MakeSignature.signDetached(appearance, digest, signature, chain, null,null, null, 0, subfilter);
}
When I use BouncyCastleProvider everything works well.
BouncyCastleProvider provider = new BouncyCastleProvider();
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(new FileInputStream(KEYSTORE), PASSWORD);
String alias = (String) ks.aliases().nextElement();
PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
java.security.cert.Certificate[] chain = ks.getCertificateChain(alias);
for (int i = 0; i < chain.length; i++) {
System.out.println(("Public Key"+chain[i].getPublicKey()));
}
System.out.println("Priate Key:"+ Arrays.toString(pk.getEncoded()));
System.out.println("Lengh of key is:"+ Arrays.toString(pk.getEncoded()).length());
sign(SRC, String.format(DEST, 1), chain, pk,DigestAlgorithms.SHA256, provider.getName(),CryptoStandard.CMS, "Test 1", "Ghent" );
it signs well, and the result is that:
Public Key Sun RSA public key, 2048 bits. I have only Self Sign sertificate here. Created By Key tool.
modulus: 19757623340732442247234242 ... and etc
public exponent: 65537
Priate Key:[48, -126, 4, -66, 2, 1, ... and etc ]
Lengh of key is:5618
Wen I use My provider. I have No Runtime Error or exceptipon but when i open pdf file , I have singature error. adobe reader have that allert ":At least one signature is invalid:. When I try to see the certificate, I have that alert "Error during signature verification. Error encountered while validating. Internal Cryptographic library error. Error Code: 0x2726""
A is root CA. B is Children of A. C is signer certificate. I have also T certificate, Children of A A
MyProvider provider= newMyProvider();
CallbackHandler console= new com.sun.security.auth.callback.TextCallbackHandler();
provider.setCallbackHandler(console);
Security.addProvider(provider);
KeyStore ks = KeyStore.getInstance("KeyStore");
ks.load(null, new char[] {});
List < java.security.cert.Certificate > chainList = new ArrayList< java.security.cert.Certificate>();
System.out.println("My Certificates in chain:");
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
if( alias.equalsIgnoreCase("T")
continue;
if (ks.isCertificateEntry(alias)) {
X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
if(!chainList.contains(ks.getCertificate(alias))){
chainList.add(ks.getCertificate(alias));
}
System.out.println("Public Key"+(cert.getPublicKey()));
}
}
java.security.cert.Certificate[] chain = new java.security.cert.Certificate[chainList.size()];
chainList.toArray(chain);
enter code here
PrivateKey pk = (PrivateKey) ks.getKey("C", null);
System.out.println("Priate Key:"+ Arrays.toString(pk.getEncoded()));
System.out.println("Lengh of key is:"+ Arrays.toString(pk.getEncoded()).length());
sign(SRC, String.format(DEST, 1), chain, pk, DigestAlgorithms.SHA256, provider.getName(), CryptoStandard.CMS, "Test sign", "testing");
Result of command line is that:
My Certificates in chain. First is Main CA .
Public Key Sun RSA public key, 4096 bits
modulus: 7233349847339212226486269.... and etc
public exponent: 65537
Public Key Sun RSA public key, 4096 bits
modulus: 8191375554227623097382171... and etc
public exponent: 65537
Public Key Sun RSA public key, 4096 bits
modulus: 8221477538578824228200634... and etc
public exponent: 65537
Priate Key:[66, 69, 105, 106, 105, 192 ... and etc]
Lengh of key is:306
When I open PDF file, I have singature error, if I use my provider.
:At least one signature is invalid:.
When I try to see the certificate, I have that alert "Error during signature verification. Error encountered while validating. Internal Cryptographic library error. Error Code: 0x2726"
Looking into the signature (using an ASN.1 dump) reveals that:
It includes in its certificates CertificateSet the certificates issued for
C = GE,O = Ministry of Justice of Georgia,OU = Civil Registry Agency,CN = GEO Root CA
C = GE,O = Ministry of Justice of Georgia,OU = Civil Registry Agency,CN = GEO Signing CA
C = GE,O = Ministry of Justice of Georgia,OU = Civil Registry Agency,CN = GEO Authentication CA
It claims in its SignerInfo's sid SignerIdentifier to have used the private key associated with the "GEO Root CA" certificate to sign
Looking at your code, issue 1 indicates that your key store contents are different from what you think. On the one hand "GEO Authentication CA" is present in it at least once with an alias not equal to "T", and on the other hand your signer certificate does not seem to be included (or has alias "T" and is ignored due to that). Your private key is included, though, as "C".
Issue 2 is due to the fact that iText expects the first entry of the certificates array to be the signer certificate. As "GEO Root CA" seems to be the first certificate found in your key store, it is the first certificate in your chainList, so also in your chain, and therefore assumed by iText to be the signer certificate.
To resolve your issue you have to
inspect your key store and make sure it also contains your signer certificate, not merely the associated private key, and
make sure your signer certificate is first in your chain certificate array.
BTW, have you yet tried using
Certificate[] chain = ks.getCertificateChain("C");
to retrieve the certificate chain? This is generally used in Digital Signatures for PDF documents...

How to store and load keys using java.security.KeyStore class

After creating secret keys, how do I store them using the Keystore class' methods and how do I load the keys?
Storing:
KeyStore ks = KeyStore.getInstance("JKS");
ks.setKeyEntry("keyAlias", key, passwordForKeyCharArray, certChain);
OutputStream writeStream = new FileOutputStream(filePathToStore);
ks.store(writeStream, keystorePasswordCharArray);
writeStream.close();
Note thet certChain might be null, unless you are passing PrivateKey
Loading:
KeyStore ks = KeyStore.getInstance("JKS");
InputStream readStream = new FileInputStream(filePathToStore);
ks.load(readStream, keystorePasswordCharArray);
Key key = ks.getKey("keyAlias", passwordForKeyCharArray);
readStream.close();
Read the javadocs
EDIT:
Note that if you are storing a SecretKey or using any part of the SunJCE provider (Java Cryptography Extension), you will need to set your KeyStore type to JCEKS.
KeyStore ks = KeyStore.getInstance("JCEKS");
I had a situation where I didn't know the key alias name, but I knew there was only one key was there in the keystore. I used the following code to load the key (after loading the keystore as shown above):
Enumeration<String> aliases = keyStore.aliases();
String alias = aliases.nextElement();
KeyStore.PrivateKeyEntry keyEnt = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias,
new KeyStore.PasswordProtection(keystorePass.toCharArray()));
PrivateKey privateKey = keyEnt.getPrivateKey();
I have added a post on my blog with details of how to load the private key, public key and how to use them.

Categories

Resources