Last active
February 2, 2021 08:13
-
-
Save hsellik/eeeebca9cea50ee124bcb45d32de0e73 to your computer and use it in GitHub Desktop.
Example on how to use YubiHSM 2 with Java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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