I am trying to sign a pdf document in java using a USB e-token.I want to read the signature from USB token safenet (alladin etoken pro 72 k(Java)) and attach to pdf using java code.I have done digital signature signing using a key stored in my local machine.But i want to know how the same can be done using a USB e-token.
The whole point of a USB token for signing is, that nobody can read the secret key from that device. So you sent the hash to the token and the token will send you the signature back.
For this to work you need a JCE provider which can talk to the token. This is typically done either by PKCS#11 (the token delivers a library for this) or the token delivers a MSCAPI driver (under windows).
Both can be used under Java, the PKCS#11 way might be a bit more complicated to setup, but in my experience it is better for automated signing because in the MSCAPI case you often need to enter the token PIN manually.
If your token is recognized by windows the following command should see and list its key:
keytool -list -storetype Windows-MY
The Windows Keystore can then be used to get a handle of the key for signing, but you can also use it to export a copy of the public key.
You can use SUN PKCS11 provider to refer the keys in the Etoken.You can just try the below code
String pkcs11Config = "name=eToken\nlibrary=C:\\Windows\\System32\\eps2003csp11.dll";
java.io.ByteArrayInputStream pkcs11ConfigStream = new java.io.ByteArrayInputStream(pkcs11Config.getBytes());
sun.security.pkcs11.SunPKCS11 providerPKCS11 = new sun.security.pkcs11.SunPKCS11("pkcs11Config");
java.security.Security.addProvider(providerPKCS11);
// Get provider KeyStore and login with PIN
String pin = "12345678";
java.security.KeyStore keyStore = java.security.KeyStore.getInstance("PKCS11", providerPKCS11);
KeyStore keyStore=KeyStore.getInstance("PKCS11",providerPKCS11);
keyStore.load(null, pin.toCharArray());
// Enumerate items (certificates and private keys) in the KeyStore
java.util.Enumeration<String> aliases = keyStore.aliases();
String alias = null;
while (aliases.hasMoreElements()) {
alias = aliases.nextElement();
System.out.println(alias);
}
Try this code
import com.lowagie.text.pdf.*;
import com.lowagie.text.Rectangle;
//import com.lowagie.text.pdf.pdfSignatureAppearance;
//import com.lowagie.text.pdf.pdfStamper;
import java.security.*;
import java.io.*;
import java.awt.*;
import java.security.cert.*;
import java.lang.*;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.CertPath;
import java.security.cert.CertificateFactory;
import java.util.ArrayList;
import java.util.List;
public class pdfsign1{
public static void main(String args[]) {
try {
KeyStore ks = KeyStore.getInstance("pkcs12");
ks.load(new FileInputStream("my_private_key.pfx"), "my_password".toCharArray());
String alias = (String)ks.aliases().nextElement();
PrivateKey key = (PrivateKey)ks.getKey(alias, "my_password".toCharArray());
Certificate[] chain = ks.getCertificateChain(alias);[/b]
PdfReader reader = new PdfReader("original.pdf");
FileOutputStream fout = new FileOutputStream("signed.pdf");
PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');
PdfSignatureAppearance sap = stp.getSignatureAppearance();
//sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
sap.setReason("I'm the author");
sap.setLocation("Lisbon");
// comment next line to have an invisible signature
sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
stp.close();
}
catch(Exception e) {}
}
}
Related
I have .cer certificate. When I'm opening it, it shows me certificate chain.
Using this code, I read the certificate to x509certificate file.
File certificateFile = new File("C:\\Users\\grish\\Desktop\\certificateForValidation.cer");
InputStream inputStream = new FileInputStream(certificateFile);
X509Certificate certificate = new X509CertImpl(inputStream);
I want to get certificate chain from that file ! (end-entity, CA, Root)
How can I do that programmatically in java.
With C#, this is much more easy
X509Chain ch = new X509Chain();
ch.ChainPolicy.RevocationMode = X509RevocationMode.Online;
ch.Build (certificate);
And then I can get all certificates from ch.
First of all make sure you are using the java.security.cert package; see JDK 17 API doc for java.security.cert.
Avoid using javax.security.cert. The package is marked as deprecated an will be removed in future releases; see JDK 17 API doc for javax.security.cert.
The following code will return a collection of java.security.cert.X509Certificate objects. In the case of your example with the certificate of medium.com the list will contain three items; one for every certificate in the chain.
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.List;
public static void main(String[] args) {
try (InputStream inStream = new FileInputStream("C:\\Users\\grish\\Desktop\\Coding Space\\Certificates\\certificateForValidation.p7b")) {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
List<X509Certificate> certs = (List<X509Certificate>) cf.generateCertificates(inStream);
} catch (Exception ex) {
ex.printStackTrace();
}
}
I tested it with a PEM formated chain but it should work with PCKS#7 (.p7b file extension) as well; see the documentation of the generateCertificates(InputStream inStream) method.
Find more information about x.509 encoding and conversion here
I've written java program which connect to Azure blob storage that I've created and downloads file content using below program but my real prod scenario is different, client has shared ThumbPrint,ClientId,AzureKeyVaultUrl,SecretId and containerName and certficate. My program works well on account I've created which has trial period. But don't understand how to create account with certificate based authentication n use that while connecting using java program.
package com;
import com.microsoft.azure.storage.CloudStorageAccount;
import com.microsoft.azure.storage.OperationContext;
import com.microsoft.azure.storage.StorageException;
import com.microsoft.azure.storage.blob.*;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.Scanner;
public class ConnectToAzureToExistingContainer {
public static final String storageConnectionString =
"DefaultEndpointsProtocol=https;AccountName=xxx;AccountKey=yyy;EndpointSuffix=zzzz";
public static void main( String[] args )
{
CloudStorageAccount storageAccount;
CloudBlobClient blobClient = null;
CloudBlobContainer container=null;
try {
storageAccount = CloudStorageAccount.parse(storageConnectionString);
blobClient = storageAccount.createCloudBlobClient();
container = blobClient.getContainerReference("revenuestream");
CloudBlockBlob blob = container.getBlockBlobReference("revenuestreams.csv");
System.out.println(blob.downloadText());
System.out.println("Done...");
}
catch (StorageException ex){
System.out.println(String.format("Error returned from the service. Http code: %d and error code: %s", ex.getHttpStatusCode(), ex.getErrorCode()));
}
catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
}
As #Thomas said, you can use Azure AD to get an access token to access your storage files. The main mechanism you can refer to this doc.
You need to get an access token to call storage APIs to access your storage service.
And you want to use certificate to get this access token to access storage service. You can follow the steps below.
Prepare your .cer certificate and .pfx certificate and upload your .cer to your Azure AD app :
Run this ps to get x5t value of your .pfx file , we will need it while signing jwt token:
$cer = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cer.Import("path of your .pfx file","password of your .pfx file",'Exportable')
$x5t = [System.Convert]::ToBase64String($cer.GetCertHash())
$x5t
Convert .pfx file to .der file so that we can use it easily in Java:
1)Convert Pem file from pfx :
openssl pkcs12 -in "your .pfx file path" -out "new .pem file path" -clcerts
2)Convert Pem to der so that java can read it easily :
openssl pkcs8 -topk8 -inform PEM -outform DER -in "pem file path" -out "new der file path" -nocrypt
Pls follow the code below to get access token from Azure AD :
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Date;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.naming.ServiceUnavailableException;
import com.microsoft.aad.adal4j.AuthenticationContext;
import com.microsoft.aad.adal4j.AuthenticationResult;
import com.microsoft.aad.adal4j.ClientAssertion;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
public class PublicClient {
private final static String TENANT_ID = "your tanant id";
private final static String AUTHORITY = "https://login.microsoftonline.com/" + TENANT_ID;
private final static String CLIENT_ID = "your Azure AD app ID";
private final static String X5TVALUE_STRING = "x5t value we get from step2 ";
private final static String DERFILE_PATH_STRING = "der file path";
public static void main(String args[]) throws Exception {
// Request access token from AAD
AuthenticationResult result = getAccessToken();
System.out.print(result.getAccessToken());
}
public static PrivateKey getPrivateKey() throws Exception {
byte[] keyBytes = Files.readAllBytes(Paths.get(DERFILE_PATH_STRING));
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
private static AuthenticationResult getAccessToken() throws Exception {
AuthenticationContext context;
AuthenticationResult result;
ExecutorService service = null;
try {
service = Executors.newFixedThreadPool(1);
context = new AuthenticationContext(AUTHORITY, false, service);
PrivateKey key = getPrivateKey();
String jwt = Jwts.builder().setHeaderParam("typ", "JWT").setHeaderParam("alg", "RS256")
.setHeaderParam("x5t",X5TVALUE_STRING).setSubject(CLIENT_ID)
.setExpiration(new Date(System.currentTimeMillis() + 200000)).setIssuer(CLIENT_ID)
.setNotBefore(new Date())
.setAudience("https://login.microsoftonline.com/" + TENANT_ID + "/oauth2/token")
.setId(UUID.randomUUID().toString()).signWith(SignatureAlgorithm.RS256, key).compact();
ClientAssertion clientAssertion = new ClientAssertion(jwt);
Future<AuthenticationResult> future = context.acquireToken("https://storage.azure.com/", clientAssertion,
null);
result = future.get();
} finally {
service.shutdown();
}
if (result == null) {
throw new ServiceUnavailableException("authentication result was null");
}
return result;
}
}
With this token we can call storage REST API , please note that "x-ms-version: 2017-11-09" is required in request header if you use Azure AD auth to access your storage :
I'm writing a program in Java that generates RSA keys using Crt parameters. I'm able to export the key in a .pem file, but I need to export it in a pkcs12 file. How can I do that in Java?
Java contains native support for PKCS#12 key stores through KeyStore.getInstance("PKCS12"). However, generally the key stores require you to offer a matching private key / certificate pair. Just providing a public key instead of a certificate is not enough. You must create a certificate, for instance a self signed certificate to be able to use the PKCS#12 key store provider.
I've tried to create my own Certificate instance using an anonymous type, but the PKCS#12 key store only seems to allow X.509 certificates (but it will only tell you when you store the key store, i.e. it is not fail fast.
Here's some code to create the self signed certificate and store the private key and resulting self signed certificate:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Date;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.CertIOException;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.util.encoders.Hex;
public class StoreRSAKeyPairInPKCS12 {
public static void main(String[] args) throws Exception {
// --- generate a key pair (you did this already it seems)
KeyPairGenerator rsaGen = KeyPairGenerator.getInstance("RSA");
final KeyPair pair = rsaGen.generateKeyPair();
// --- create the self signed cert
Certificate cert = createSelfSigned(pair);
// --- create a new pkcs12 key store in memory
KeyStore pkcs12 = KeyStore.getInstance("PKCS12");
pkcs12.load(null, null);
// --- create entry in PKCS12
pkcs12.setKeyEntry("privatekeyalias", pair.getPrivate(), "entrypassphrase".toCharArray(), new Certificate[] {cert});
// --- store PKCS#12 as file
try (FileOutputStream p12 = new FileOutputStream("mystore.p12")) {
pkcs12.store(p12, "p12passphrase".toCharArray());
}
// --- read PKCS#12 as file
KeyStore testp12 = KeyStore.getInstance("PKCS12");
try (FileInputStream p12 = new FileInputStream("mystore.p12")) {
testp12.load(p12, "p12passphrase".toCharArray());
}
// --- retrieve private key
System.out.println(Hex.toHexString(testp12.getKey("privatekeyalias", "entrypassphrase".toCharArray()).getEncoded()));
}
private static X509Certificate createSelfSigned(KeyPair pair) throws OperatorCreationException, CertIOException, CertificateException {
X500Name dnName = new X500Name("CN=publickeystorageonly");
BigInteger certSerialNumber = BigInteger.ONE;
Date startDate = new Date(); // now
Calendar calendar = Calendar.getInstance();
calendar.setTime(startDate);
calendar.add(Calendar.YEAR, 1);
Date endDate = calendar.getTime();
ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WithRSA").build(pair.getPrivate());
JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(dnName, certSerialNumber, startDate, endDate, dnName, pair.getPublic());
return new JcaX509CertificateConverter().getCertificate(certBuilder.build(contentSigner));
}
}
You will need at least the PKIX library (bcpkix-jdk15on.jar) from Bouncy Castle and possibly the library of the Bouncy Castle provider. Installing the Bouncy Castle provider is not required.
i am working on MQTT protocol. i configured its server and performed the communication in java using its mosquitto library on port 1883.
now i want to make this communication secure.What i know is port 8883 is reserved for its tls based secure communication.
It requires X.509 certiicates.
I found the following tutorial for this purpose.
http://www.embedded101.com/Blogs/PaoloPatierno/entryid/366/mqtt-over-ssl-tls-with-the-m2mqtt-library-and-the-mosquitto-broker
But my question are
1.how can we generate these certificates in java code?
2.how can we use multiple certificates at a time.As according to above tutorial we can specify only one set of ceritificates at a time in mosquitto.conf file of server.And then we need to restart the server.(that i dont want to do.)
3.how can we let a running server know about these newly generated certificates. Is there anyother way to do this except to specify in conf file of server?
OK, I think you've miss understood how Certificate authentication works.
There are 2 parts to it (Proving the broker is who it says it is and then proving who the client connecting is)
Firstly the broker will have 1 certificate that identifies it to the world. You configure Mosquitto to use this certificate at startup and never need to change it. This certificate will be signed by a CA.
The sensors (clients) will have a copy of the CA cert which they will use when they connect to the broker to ensure it is who it claims to be.
Secondly if you want to use client certificates to identify the separate sensors then they will each need a certificate as well. Normally this will be signed by the same CA as the Broker certificate so the broker can verify the clients are who they claim to be. Mosquitto can be set up to use the CN from the certificates (use_identity_as_username true) as the username for the connecting clients and then you can use the mosquitto_auth_plugin to keep track of the CN's in the certificates and apply ACLs to control who can use what topics.
As for creating certificates in java I suggest you look at this question
There is no need to restart Mosquitto when you issue a new cert.
//add bcpkix-jdk15on-161, bcprov-jdk15on-1.52 and eclips pago-mqtt3.1
//lib in build path
import java.io.*;
import java.nio.file.*;
import java.security.*;
import java.security.cert.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.net.ssl.*;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jce.provider.*;
import org.bouncycastle.openssl.*;
import org.bouncycastle.openssl.PasswordFinder;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
public class SslUtil
{
#SuppressWarnings("deprecation")
//It will return SSLSocketFactory
public static SSLSocketFactory getSocketFactory (final String
caCrtFile, final String crtFile, final String keyFile,
final String password) throws Exception
{
try{
Security.addProvider(new BouncyCastleProvider());
X509Certificate caCert =
(X509Certificate)SslUtil.getCertificate(caCrtFile);
X509Certificate cert =
(X509Certificate)SslUtil.getCertificate(crtFile);
FileReader fileReader = new FileReader(keyFile);
PEMParser parser = new PEMParser(fileReader);
PEMKeyPair kp = (PEMKeyPair) parser.readObject();
PrivateKeyInfo info = kp.getPrivateKeyInfo();
PrivateKey rdKey = new JcaPEMKeyConverter().setProvider("BC")
.getPrivateKey(info);
// CA certificate is used to authenticate server
KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType());
caKs.load(null, null);
caKs.setCertificateEntry("ca-certificate", caCert);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(caKs);
// client key and certificates are sent to server so it can authenticate us
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
ks.setCertificateEntry("certificate", cert);
ks.setKeyEntry("private-key", rdKey, password.toCharArray(), new java.security.cert.Certificate[]{cert});
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, password.toCharArray());
// finally, create SSL socket factory
SSLContext context = SSLContext.getInstance("TLSv1");
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
return context.getSocketFactory();
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
//Get MqttClient for Subscripe Pulish
public static void mqttClient(String caCrtFile,String clientCrtFilePath,String clientKeyFilePath,String password){
try{
String serverUrl = "ssl://serverip:8883";
MqttClient client = new MqttClient(serverUrl, "consumerId" , null);
//this MyCallback class extends mqtt there we have to override some function //like message arriver etc
client.setCallback(new MyCallback());
MqttConnectOptions options = new MqttConnectOptions();
options.setConnectionTimeout(60);
options.setKeepAliveInterval(60);
options.setSocketFactory(SslUtil.getSocketFactory(caCrtFile, clientCrtFilePath, clientKeyFilePath, password));
client.connect(options);
client.subscribe("topic", 0);
}catch (Exception e) {
System.out.println("#Exception :"+e.getMessage());
}
}
//start execution
public static void main(String[] args) throws Exception {
String caCrtFile = "path Certification Authority";
String clientCrtFilePath ="path for client crt file";
String clientKeyFilePath ="path of client key";
String password = "password while generating files";
mqttClient(caCrtFile,clientCrtFilePath,clientKeyFilePath,password);
// getCertificate(caCrtFile);
}
//return certificate
public static java.security.cert.X509Certificate getCertificate(String pemfile) throws Exception
{
java.security.cert.X509Certificate cert = null;
try {
FileReader fRd = new FileReader(pemfile);
final PemReader certReader = new PemReader(fRd);
final PemObject certAsPemObject = certReader.readPemObject();
if (!certAsPemObject.getType().equalsIgnoreCase("CERTIFICATE")) {
throw new Exception("Certificate file does not contain a certificate but a " + certAsPemObject.getType());
}
final byte[] x509Data = certAsPemObject.getContent();
final CertificateFactory fact = CertificateFactory.getInstance("X509");
cert = (X509Certificate) fact.generateCertificate(new ByteArrayInputStream(x509Data));
if (!(cert instanceof X509Certificate)) {
throw new Exception("Certificate file does not contain an X509 certificate");
}
} catch (FileNotFoundException e) {
throw new IOException("Can't find file " + pemfile);
}catch (Exception e) {
System.out.println("#Exceotion :"+e.getMessage());
}
return cert;
}
//retuen keyPair Object form client key
public KeyPair decodeKeys(byte[] privKeyBits,byte[] pubKeyBits)
throws InvalidKeySpecException, NoSuchAlgorithmException {
KeyFactory keyFactory=KeyFactory.getInstance("RSA");
PrivateKey privKey=keyFactory.generatePrivate(new
PKCS8EncodedKeySpec(privKeyBits));
PublicKey pubKey=keyFactory.generatePublic(new
X509EncodedKeySpec(pubKeyBits));
return new KeyPair(pubKey,privKey);
}
}
I try to get Key from KeyStore.
I created a keystore by Keytool:
keytool -genkeypair -dname "cn=Mark Jones, ou=JavaSoft, o=Sun, c=US" -alias business2 -keypass abcdtest -keystore C:\workspace\XMLSample\keystore\mykeystore.jks -storepass 123456
And the following is GenerateXML.java
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import javax.xml.crypto.dsig.XMLSignContext;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
public class GenerateXML {
public static void main(String[] args) throws Exception {
try {
char[] passwd = "123456".toCharArray();
//Load the KeyStore and get the signing key and certificate
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("C:\\workspace\\XMLSample\\keystore\\mykeystore.jks"), passwd);
KeyStore.PrivateKeyEntry keyEnt = (KeyStore.PrivateKeyEntry)ks.getEntry("business2", new KeyStore.PasswordProtection(passwd)); // -> ERROR IN THIS ROW
X509Certificate cert = (X509Certificate)keyEnt.getCertificate();
//Create a DOMSignContext
XMLSignContext context = new DOMSignContext(keyEnt.getPrivateKey(), doc.getDocumentElement()) ;
//Create a DOM XMLSignatureFactory
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
} catch(Exception e) {
e.printStackTrace();
throw new Exception(e.toString());
}
}
}
I run on Java 1.6
But have error:
java.security.UnrecoverableKeyException: Cannot recover key
at sun.security.provider.KeyProtector.recover(KeyProtector.java:311)
at sun.security.provider.JavaKeyStore.engineGetKey(JavaKeyStore.java:121)
at sun.security.provider.JavaKeyStore$JKS.engineGetKey(JavaKeyStore.java:38)
at java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:456)
at java.security.KeyStore.getEntry(KeyStore.java:1261)
at xml.generate.GenerateXML.main(GenerateXML.java:31)
I've run accross the similar issue. The root of the problem was that I used a different password for the key than for the whole keystore.
The code is similar to the one in the JSSE article. It looks like this:
serverKeyStore.load(new FileInputStream("resource/server.jks"), passphrase.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(serverKeyStore);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(serverKeyStore, keyphrase.toCharArray());
I use the keystore pass in the first line and the key pass in the last.
This basically means 2 things,
You had a bad password.
Your keystore is corrupted somehow.
I suspect it's #1. Double check your password. Try if you can list the key in keytool with the same password.
In the ks.getEntry line, you're giving it the store password. Should be the key password instead. Replace the line with this and it will work:
char[] keypwd = "abcdtest".toCharArray();
KeyStore.PrivateKeyEntry keyEnt = (KeyStore.PrivateKeyEntry) ks.getEntry("business2", new KeyStore.PasswordProtection(keypwd));