java


How to store and reuse keypair in Java?


I am wanting generate a keypair once and reuse it.
public static KeyPair generateKeyPair() throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048, new SecureRandom());
KeyPair pair = generator.generateKeyPair();
return pair;
}
How do I go about this?
There is a bit of a problem here: Java's focus is almost entirely on TLS and the cryptography required to implement TLS. For TLS a private key and a certificate is required. So you get into a situation where you:
have to generate a (bogus) self signed certificate to go with your public key or;
have to find another way of storing the private key without a certificate.
However, with (2.) you quickly get a method that isn't very compatible. If you want to go that way, you could create a PKCS#8 encrypted private key that is encrypted using PBE / CBC.
So here's some code to create a self signed certificate and use that to store the key. Note the expiration date, you could set it to 100 years to be on the safe side (or you could actually do some key management).
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStore.Entry;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.UnrecoverableEntryException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Calendar;
import java.util.Date;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
public class StoreKeyPair {
public static KeyPair generateKeyPair() throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048, new SecureRandom());
KeyPair pair = generator.generateKeyPair();
return pair;
}
public static Certificate selfSign(KeyPair keyPair, String subjectDN)
throws OperatorCreationException, CertificateException, IOException
{
Provider bcProvider = new BouncyCastleProvider();
Security.addProvider(bcProvider);
long now = System.currentTimeMillis();
Date startDate = new Date(now);
X500Name dnName = new X500Name(subjectDN);
// Using the current timestamp as the certificate serial number
BigInteger certSerialNumber = new BigInteger(Long.toString(now));
Calendar calendar = Calendar.getInstance();
calendar.setTime(startDate);
// 1 Yr validity
calendar.add(Calendar.YEAR, 1);
Date endDate = calendar.getTime();
// Use appropriate signature algorithm based on your keyPair algorithm.
String signatureAlgorithm = "SHA256WithRSA";
SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(keyPair
.getPublic().getEncoded());
X509v3CertificateBuilder certificateBuilder = new X509v3CertificateBuilder(dnName,
certSerialNumber, startDate, endDate, dnName, subjectPublicKeyInfo);
ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithm).setProvider(
bcProvider).build(keyPair.getPrivate());
X509CertificateHolder certificateHolder = certificateBuilder.build(contentSigner);
Certificate selfSignedCert = new JcaX509CertificateConverter()
.getCertificate(certificateHolder);
return selfSignedCert;
}
public static void main(String[] args) throws Exception {
KeyPair generatedKeyPair = generateKeyPair();
String filename = "test_gen_self_signed.pkcs12";
char[] password = "test".toCharArray();
storeToPKCS12(filename, password, generatedKeyPair);
KeyPair retrievedKeyPair = loadFromPKCS12(filename, password);
// you can validate by generating a signature and verifying it or by
// comparing the moduli by first casting to RSAPublicKey, e.g.:
RSAPublicKey pubKey = (RSAPublicKey) generatedKeyPair.getPublic();
RSAPrivateKey privKey = (RSAPrivateKey) retrievedKeyPair.getPrivate();
System.out.println(pubKey.getModulus().equals(privKey.getModulus()));
}
private static KeyPair loadFromPKCS12(String filename, char[] password)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
FileNotFoundException, IOException, UnrecoverableEntryException {
KeyStore pkcs12KeyStore = KeyStore.getInstance("PKCS12");
try (FileInputStream fis = new FileInputStream(filename);) {
pkcs12KeyStore.load(fis, password);
}
KeyStore.ProtectionParameter param = new KeyStore.PasswordProtection(password);
Entry entry = pkcs12KeyStore.getEntry("owlstead", param);
if (!(entry instanceof PrivateKeyEntry)) {
throw new KeyStoreException("That's not a private key!");
}
PrivateKeyEntry privKeyEntry = (PrivateKeyEntry) entry;
PublicKey publicKey = privKeyEntry.getCertificate().getPublicKey();
PrivateKey privateKey = privKeyEntry.getPrivateKey();
return new KeyPair(publicKey, privateKey);
}
private static void storeToPKCS12(
String filename, char[] password,
KeyPair generatedKeyPair) throws KeyStoreException, IOException,
NoSuchAlgorithmException, CertificateException, FileNotFoundException,
OperatorCreationException {
Certificate selfSignedCertificate = selfSign(generatedKeyPair, "CN=owlstead");
KeyStore pkcs12KeyStore = KeyStore.getInstance("PKCS12");
pkcs12KeyStore.load(null, null);
KeyStore.Entry entry = new PrivateKeyEntry(generatedKeyPair.getPrivate(),
new Certificate[] { selfSignedCertificate });
KeyStore.ProtectionParameter param = new KeyStore.PasswordProtection(password);
pkcs12KeyStore.setEntry("owlstead", entry, param);
try (FileOutputStream fos = new FileOutputStream(filename)) {
pkcs12KeyStore.store(fos, password);
}
}
}
Note that I was too lazy to properly handle the exceptions.
This code uses a slightly altered version of this answer, see my comments for why I changed the code.
The public key can of course be stored separately as well. Just call getEncoded and store the resulting SubjectPublicKeyInfo structure.

Related Links

values in multiple tables spring validation prob
How do I execute a method every 1 Minute for the purpose of updating my App (Android Studio) [duplicate]
Unable to store analysis versions in sonarqube
Custom splash screen for Eclipse plugin (Non-RCP)
Is there any ways to add some gui to a netbeans plugin?
Refactoring by passing generic method
Spring bean initialization prior to everyting
Play 2.5 - Run a Java method at certain times of day (cron)
How to use main method to randomly generate a day in a month ? Any ideas? [closed]
Android studio organize-imports, will not remove unresolved imports
Spring Boot, Issue using Thymeleaf
Unable to read socket response C server to Java client
How to convert string representation of an ASCII value to character
ASM Bytecode - Get line numbers from label offset
Executable Jar in NetBeans not working
Support multiple webviews in one activity

Categories

HOME
deployment
react-virtualized
onedrive
indesign
bs4
awesome-wm
vifm
izpack
nstableview
ups
ghc
highlight.js
finite-automata
visjs
accessor
excel-2007
rundeck
fish
su
apache-commons-io
rst2pdf
elasticsearch-ruby
google-cloud-nl
microsoft-chart-controls
javascriptcore
google-cloud-endpoints-v2
airconsole
phpfreechat
normal-distribution
picasso
android-ble
restlet
retina-display
unspecified
sqlite2
impersonation
leading-zero
opshub
unoconv
ensembles
sfdc
node-gyp
nomethoderror
nxlog
password-encryption
typescript1.8
veracode
fancybox-2
forever
media-player
r-forge
ifs
pdfclown
zendesk-app
imanage
pintos
medium.com
azure-virtual-network
measures
contact-list
pagedlist
fadeout
freedesktop.org
wireshark-dissector
ibaction
ideamart
generic-programming
remobjects
dundas
pretty-print
rake-task
camanjs
bitcoinj
starcluster
doskey
.aspxauth
commoncrypto
file-locking
hungarian-algorithm
pushbackinputstream
comaddin
ember-app-kit
eventlistener
lcs
clipper
dmoz
chuck
coderush
word-processor
regsvr32
removeclass
subscript
vdsp
celltable
html-input
paster
xsdobjectgen
routedevent
ext3
compiler-specific
virtual-functions
privilege
spec#
zune
django-notification
paul-graham
uiq3

Resources

Database Users
RDBMS discuss
Database Dev&Adm
javascript
java
csharp
php
android
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App