Skip to content

Instantly share code, notes, and snippets.

@hsellik
Last active February 2, 2021 08:13
Show Gist options
  • Save hsellik/eeeebca9cea50ee124bcb45d32de0e73 to your computer and use it in GitHub Desktop.
Save hsellik/eeeebca9cea50ee124bcb45d32de0e73 to your computer and use it in GitHub Desktop.
Example on how to use YubiHSM 2 with Java
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
public class PKCS11 {
// Use -Djava.security.debug=sunpkcs11,pkcs11keystore if you want to get better debug information
public static void main(String[] args) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, UnrecoverableKeyException {
// See if the required environment variable is set
System.out.println("YUBIHSM_PKCS11_CONF: " + System.getenv("YUBIHSM_PKCS11_CONF"));
// Create a configuration
String name = "YubiHSM";
String library = "/home/hendrig/yubihsm_pkcs11.so";
String slotListIndex = "0";
String pkcs11Config = "name=" + name + "\nlibrary=" + library + "\nslot=" + slotListIndex;
java.io.ByteArrayInputStream pkcs11ConfigStream = new java.io.ByteArrayInputStream(pkcs11Config.getBytes());
// Load the provider using configuration and add it
Provider provider = new sun.security.pkcs11.SunPKCS11(pkcs11ConfigStream);
Security.addProvider(provider);
// This is not necessary, but shows how to load a provider if you use different HSM-s
Provider provider1 = Security.getProvider("SunPKCS11-YubiHSM");
// Construct KeyStore PIN which consists of the authentication key id + password
// 15494 is integer representation for 3c86.
String id = Integer.toHexString(15494);
String password = "k9fo5lsotks7";
char[] pin = (id + password).toCharArray();
// Load the KeyStore using the pin
KeyStore ks = KeyStore.getInstance("PKCS11", provider);
ks.load(null, pin);
// Print all the aliases to see if ours exists on the device
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) { // token has a single certificate
String alias = aliases.nextElement();
System.err.println(alias);
}
// Load private key from the KeyStore
PrivateKey privateKey = (PrivateKey) (ks.getKey("my_key_alias", null));
// get the certificate
X509Certificate cert = (X509Certificate) ks.getCertificate("my_key_alias");
// get the public key from the certificate
PublicKey publicKey = cert.getPublicKey();
// Encrypt the data
byte[] encrypted = encrypt("Test string to encrypt".getBytes(), publicKey);
// Decrypt the data
byte[] decrypted = decrypt(encrypted, privateKey);
}
// Helper function to perform RSA functions in Java
private static byte[] rsa(byte[] data, int mode, Key key) {
Cipher cipher = null;
byte[] result = null;
try {
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
System.out.println("Failed to create RSA cipher.");
}
try {
assert cipher != null;
cipher.init(mode, key);
} catch (InvalidKeyException e) {
System.out.println("Invalid RSA key.");
}
try {
result = cipher.doFinal(data);
} catch (IllegalBlockSizeException | BadPaddingException e) {
System.out.println("Error while performing RSA cryptographic function.");
e.printStackTrace();
}
return result;
}
// Perform RSA encryption
private static byte[] encrypt(byte[] data, PublicKey publicKey) {
return rsa(data, Cipher.ENCRYPT_MODE, publicKey);
}
// Perform decryption
public static byte[] decrypt(byte[] data, PrivateKey privateKey) {
return rsa(data, Cipher.DECRYPT_MODE, privateKey);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment