This java code works on Windows system with an acceptable speed (around 1 sec), but it takes up to 1 minute on Linux system.
After some investigation, I found it is also down to slow SecureRandom issue on Linux.
The workaround is easy, use the switch -Djava.security.egd=file:/dev/./urandom if you are using JRE 1.5+.
I did a test on CentOS(an ESXi VM), see how different the results are!
java -classpath .:bcprov.jar KeyPairCost ---- test start ---- Generate KeyPair takes 176 msec Store takes 58923 msec ---- test end ---- java -Djava.security.egd=file:/dev/./urandom -classpath .:bcprov.jar KeyPairCost ---- test start ---- Generate KeyPair takes 297 msec Store takes 404 msec ---- test end ----
Java Code
import java.io.ByteArrayOutputStream;
import java.util.*;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.Security;
import java.math.BigInteger;
import java.security.cert.X509Certificate;
import org.bouncycastle.x509.X509V1CertificateGenerator;
import org.bouncycastle.jce.X509Principal;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class KeyPairCost
{
static X509V1CertificateGenerator v1CertGen = new X509V1CertificateGenerator();
public static void generateKeyPairCost() throws Exception
{
// signers name
String issuer = "KeyPairCost";
// subjects name - the same as we are self signed.
String subject = "KeyPairCost";
java.util.Date date1 = new java.util.Date();
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024); //default SecureRandom
KeyPair keypair = keyGen.genKeyPair();
PrivateKey privKey = keypair.getPrivate();
PublicKey pubKey = keypair.getPublic();
java.util.Date date2 = new java.util.Date();
long diff = date2.getTime()-date1.getTime();
System.out.println("Generate KeyPair takes " + diff + " msec");
// create the certificate - version 1
v1CertGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
v1CertGen.setIssuerDN(new X509Principal(issuer));
v1CertGen.setNotBefore(new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24 * 30)); // one month
v1CertGen.setNotAfter(new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 30 * 1200 ))); // 10 years
v1CertGen.setSubjectDN(new X509Principal(subject));
v1CertGen.setPublicKey(pubKey);
v1CertGen.setSignatureAlgorithm("SHA1WithRSAEncryption");
X509Certificate cert = v1CertGen.generate(privKey,"BC");
// now write it to key store
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null, "changeit".toCharArray());
Certificate[] chain = new Certificate[1];
chain[0] = cert;
ks.setKeyEntry("dualidp", privKey, "changeit".toCharArray(), chain);
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
ks.store(bOut, "changeit".toCharArray());
java.util.Date date3 = new java.util.Date();
diff = date3.getTime()-date2.getTime();
System.out.println("Store takes " + diff + " msec");
}
public static void main(String[] args)
{
Security.addProvider(new BouncyCastleProvider());
System.out.println("---- test start ----");
try {
generateKeyPairCost();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("---- test end ----");
}
}
1 comment:
Thanks for your article.
I have the same problem.
Post a Comment