Skip to content

Instantly share code, notes, and snippets.

@spicydog
Created December 24, 2015 09:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save spicydog/84fa0e74d8524fba1fbb to your computer and use it in GitHub Desktop.
Save spicydog/84fa0e74d8524fba1fbb to your computer and use it in GitHub Desktop.
#!/bin/sh
openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER
openssl x509 -in chain.pem -inform PEM -out chain.der -outform DER
openssl pkcs8 -topk8 -nocrypt -in privkey.pem -inform PEM -out privkey.der -outform DER
cat cert.der chain.der > chained_certificate.der
#javac ImportKey.java
java ImportKey privkey.der chained_certificate.der
import java.security.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.DataInputStream;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.security.spec.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Collection;
import java.util.Iterator;
/**
* ImportKey.java
*
* <p>This class imports a key and a certificate into a keystore
* (<code>$home/keystore.ImportKey</code>). If the keystore is
* already present, it is simply deleted. Both the key and the
* certificate file must be in <code>DER</code>-format. The key must be
* encoded with <code>PKCS#8</code>-format. The certificate must be
* encoded in <code>X.509</code>-format.</p>
*
* <p>Key format:</p>
* <p><code>openssl pkcs8 -topk8 -nocrypt -in YOUR.KEY -out YOUR.KEY.der
* -outform der</code></p>
* <p>Format of the certificate:</p>
* <p><code>openssl x509 -in YOUR.CERT -out YOUR.CERT.der -outform
* der</code></p>
* <p>Import key and certificate:</p>
* <p><code>java comu.ImportKey YOUR.KEY.der YOUR.CERT.der</code></p><br />
*
* <p><em>Caution:</em> the old <code>keystore.ImportKey</code>-file is
* deleted and replaced with a keystore only containing <code>YOUR.KEY</code>
* and <code>YOUR.CERT</code>. The keystore and the key has no password;
* they can be set by the <code>keytool -keypasswd</code>-command for setting
* the key password, and the <code>keytool -storepasswd</code>-command to set
* the keystore password.
* <p>The key and the certificate is stored under the alias
* <code>importkey</code>; to change this, use <code>keytool -keyclone</code>.
*
* Created: Fri Apr 13 18:15:07 2001
* Updated: Fri Apr 19 11:03:00 2002
*
* @author Joachim Karrer, Jens Carlberg
* @version 1.1
**/
/**
* NOTES AND INSTRUCTIONS
*
* 1 convert all public keys including intermediate and root CA with .crt or pem to .der with
* "openssl x509 -in [in.crt] -inform PEM -out [out.der] -outform DER"
* 2. convert private key of .crt or .pem to .der with
* "openssl pkcs8 -topk8 -nocrypt -in [in.crt] -inform PEM -out [out.der] -outform DER"
* 3. use cat to merge certificate .der files (not a private key) into one file from server to root certificate
* 4. compile this file with "javac ImportKey.java", then you will get ImportKey.class
* (no need to compile again if you have already compiled once)
* 5. run "java ImportKey [privatekey.der] [chained_certificate.der]"
* 6. the keystore file will be written as https.keystore
* 7. check keystore with command "keytool -list -v -keystore [keystore]"
* 8. check "Certificate chain length: ", it should have value more than 1 if you add chain to it
*
* Edited from source: http://www.agentbob.info/agentbob/79-AB.html
* Modification[1]: Comment of Barry Simons on 4/5/07 2:28:36 AM
* Modification[2]: Comment of johann renck on 9/3/07 3:31:49 PM
* Modification[3]: Add note by spicydog on 2015-10-05T17:53:29Z+0700
* Modification[4]: Modify script for Let's Encrypt by spicydog on 2015-12-24 16:02:01Z+0700
*
**/
public class ImportKey {
/**
* <p>Creates an InputStream from a file, and fills it with the complete
* file. Thus, available() on the returned InputStream will return the
* full number of bytes the file contains</p>
* @param fname The filename
* @return The filled InputStream
* @exception IOException, if the Streams couldn't be created.
**/
private static InputStream fullStream ( String fname ) throws IOException {
FileInputStream fis = new FileInputStream(fname);
DataInputStream dis = new DataInputStream(fis);
byte[] bytes = new byte[dis.available()];
dis.readFully(bytes);
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
return bais;
}
/**
* <p>Takes two file names for a key and the certificate for the key,
* and imports those into a keystore. Optionally it takes an alias
* for the key.
* <p>The first argument is the filename for the key. The key should be
* in PKCS8-format.
* <p>The second argument is the filename for the certificate for the key.
* <p>If a third argument is given it is used as the alias. If missing,
* the key is imported with the alias importkey
* <p>The name of the keystore file can be controlled by setting
* the keystore property (java -Dkeystore=mykeystore). If no name
* is given, the file is named <code>keystore.ImportKey</code>
* and placed in your home directory.
* @param args [0] Name of the key file, [1] Name of the certificate file
* [2] Alias for the key.
**/
public static void main ( String args[]) {
// change this if you want another password by default
String keypass = "password";
// change this if you want another alias by default
String defaultalias = "alias";
// change this if you want another keystorefile by default
String keystorename = System.getProperty("keystore");
if (keystorename == null)
keystorename = "keystore.ImportKey";
// parsing command line input
String keyfile = "";
String certfile = "";
if (args.length < 2 || args.length>3) {
System.out.println("Usage: java comu.ImportKey keyfile certfile [alias]");
System.exit(0);
} else {
keyfile = args[0];
certfile = args[1];
if (args.length>2)
defaultalias = args[2];
}
try {
// initializing and clearing keystore
KeyStore ks = KeyStore.getInstance("JKS", "SUN");
ks.load( null , keypass.toCharArray());
System.out.println("Using keystore-file : "+keystorename);
ks.store(new FileOutputStream ( keystorename ),
keypass.toCharArray());
ks.load(new FileInputStream ( keystorename ),
keypass.toCharArray());
// loading Key
InputStream fl = fullStream (keyfile);
byte[] key = new byte[fl.available()];
KeyFactory kf = KeyFactory.getInstance("RSA");
fl.read ( key, 0, fl.available() );
fl.close();
PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key );
PrivateKey ff = kf.generatePrivate (keysp);
// loading CertificateChain
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream certstream = fullStream (certfile);
Collection c = cf.generateCertificates(certstream) ;
Certificate[] certs = new Certificate[c.toArray().length];
if (c.size() == 1) {
certstream = fullStream (certfile);
System.out.println("One certificate, no chain.");
Certificate cert = cf.generateCertificate(certstream) ;
certs[0] = cert;
} else {
System.out.println("Certificate chain length: "+c.size());
/**
* Run for through chained certificates
**/
// certs = (Certificate[])c.toArray();
int i = 0;
Iterator it = c.iterator();
while (it.hasNext()) {
certs[i] = (Certificate)it.next();
i++;
}
}
// storing keystore
ks.setKeyEntry(defaultalias, ff,
keypass.toCharArray(),
certs );
System.out.println ("Key and certificate stored.");
System.out.println ("Alias:"+defaultalias+" Password:"+keypass);
ks.store(new FileOutputStream ( keystorename ),
keypass.toCharArray());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment