I am trying to save a DES key to a file using KeyStore for later use. Here is my code:
// Generate a DES key.
KeyGenerator kg = KeyGenerator.getInstance("DES");
SecretKey k = kg.generateKey();
// Store it in a file.
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
char[] pw = "moon".toCharArray();
KeyStore.SecretKeyEntry sk = new KeyStore.SecretKeyEntry(k);
ks.setEntry("k1", sk, new KeyStore.PasswordProtection(pw));
// store away the keystore
FileOutputStream fos = null;
try {
fos = new FileOutputStream("DESKey.jks");
ks.store(fos, pw);
} finally {
if (fos != null) {
fos.close();
}
}
However, when I try to use the KeyStore.setEntry() method I receive errors stating that DES is an unrecognized algorithm. The exception stack is here:
Exception in thread "main" java.security.KeyStoreException: Key protection algorithm not found: java.security.NoSuchAlgorithmException: unrecognized algorithm name: DES
at java.base/sun.security.pkcs12.PKCS12KeyStore.setKeyEntry(PKCS12KeyStore.java:688)
at java.base/sun.security.pkcs12.PKCS12KeyStore.engineSetEntry(PKCS12KeyStore.java:1423)
at java.base/sun.security.util.KeyStoreDelegator.engineSetEntry(KeyStoreDelegator.java:173) at java.base/java.security.KeyStore.setEntry(KeyStore.java:1591) at CipherClient.main(CipherClient.java:27)
Caused by: java.security.NoSuchAlgorithmException: unrecognized algorithm name: DES
at java.base/sun.security.x509.AlgorithmId.get(AlgorithmId.java:448)
at java.base/sun.security.pkcs12.PKCS12KeyStore.setKeyEntry(PKCS12KeyStore.java:656)
... 4 more
While debugging I narrowed the issue down to the function java.base/sun.security.x509.AlgorithmID.get(AlgorithmID.java:448)
This is a wrapper function for algOID(algname)
in the AlgorithmID class. It is essentially just a series of if statements checking the name of the algorithm used to generate the key being saved. A snippet of this method is included here:
// See if algname is in printable OID ("dot-dot") notation
if (name.indexOf('.') != -1) {
if (name.startsWith("OID.")) {
return new ObjectIdentifier(name.substring("OID.".length()));
} else {
return new ObjectIdentifier(name);
}
}
// Digesting algorithms
if (name.equalsIgnoreCase("MD5")) {
return AlgorithmId.MD5_oid;
}
if (name.equalsIgnoreCase("MD2")) {
return AlgorithmId.MD2_oid;
}
if (name.equalsIgnoreCase("SHA") || name.equalsIgnoreCase("SHA1")
|| name.equalsIgnoreCase("SHA-1")) {
return AlgorithmId.SHA_oid;
}
if (name.equalsIgnoreCase("SHA-256") ||
name.equalsIgnoreCase("SHA256")) {
return AlgorithmId.SHA256_oid;
}
if (name.equalsIgnoreCase("SHA-384") ||
name.equalsIgnoreCase("SHA384")) {
return AlgorithmId.SHA384_oid;
}
if (name.equalsIgnoreCase("SHA-512") ||
name.equalsIgnoreCase("SHA512")) {
return AlgorithmId.SHA512_oid;
}
if (name.equalsIgnoreCase("SHA-224") ||
name.equalsIgnoreCase("SHA224")) {
return AlgorithmId.SHA224_oid;
}
if (name.equalsIgnoreCase("SHA-512/224") ||
name.equalsIgnoreCase("SHA512/224")) {
return AlgorithmId.SHA512_224_oid;
}
if (name.equalsIgnoreCase("SHA-512/256") ||
name.equalsIgnoreCase("SHA512/256")) {
return AlgorithmId.SHA512_256_oid;
}
// Various public key algorithms
if (name.equalsIgnoreCase("RSA")) {
return AlgorithmId.RSAEncryption_oid;
}
if (name.equalsIgnoreCase("RSASSA-PSS")) {
return AlgorithmId.RSASSA_PSS_oid;
}
if (name.equalsIgnoreCase("RSAES-OAEP")) {
return AlgorithmId.RSAES_OAEP_oid;
}
if (name.equalsIgnoreCase("Diffie-Hellman")
|| name.equalsIgnoreCase("DH")) {
return AlgorithmId.DH_oid;
}
if (name.equalsIgnoreCase("DSA")) {
return AlgorithmId.DSA_oid;
}
if (name.equalsIgnoreCase("EC")) {
return EC_oid;
}
if (name.equalsIgnoreCase("ECDH")) {
return AlgorithmId.ECDH_oid;
}
// Secret key algorithms
if (name.equalsIgnoreCase("AES")) {
return AlgorithmId.AES_oid;
}
// Common signature types
if (name.equalsIgnoreCase("MD5withRSA")
|| name.equalsIgnoreCase("MD5/RSA")) {
return AlgorithmId.md5WithRSAEncryption_oid;
}
if (name.equalsIgnoreCase("MD2withRSA")
|| name.equalsIgnoreCase("MD2/RSA")) {
return AlgorithmId.md2WithRSAEncryption_oid;
}
DES, a symmetric key algorithm, should be included in the secret key algorithms section along with AES, but it isn't listed. I understand DES is an older algorithm, but did they really remove support for it?
I would appreciate any assistance, whether to make the keystore work or other methods of writing the DES key to a file where it can be read again later. Thanks!
Which JDK version you are using?
The DES algorithm is known to be weak and as such it has been removed from a bunch of places in JDK 14: https://bugs.openjdk.java.net/browse/JDK-8233607
In short, you shouldn't use it.
That said, [I tried to rewrite your example in Clojure][1] (sorry, I don't use Java these days) and it worked well - using Java 17.0.2:
(ns clojure-experiments.security.keystore
(:import (javax.crypto KeyGenerator)
(java.security KeyStore
KeyStore$SecretKeyEntry
KeyStore$PasswordProtection)))
;; https://stackoverflow.com/questions/71754646/java-saving-a-des-key-using-keystore
(comment
;; https://docs.oracle.com/javase/7/docs/api/javax/crypto/KeyGenerator.html
(def my-kg (KeyGenerator/getInstance "DES"))
(def my-key (.generateKey my-kg))
;; https://docs.oracle.com/javase/7/docs/api/java/security/KeyStore.html
(def my-keystore (KeyStore/getInstance (KeyStore/getDefaultType)))
(.load my-keystore nil nil) ; passing nil input stream to create a new KeyStore
(def my-password (char-array "changeit"))
;; save the key in the keystore
(def my-key-entry (KeyStore$SecretKeyEntry. my-key))
(def my-key-alias "myKeyAlias")
(def my-key-password (KeyStore$PasswordProtection. my-password))
(.setEntry my-keystore my-key-alias my-key-entry my-key-password)
;; save the keystore
(def keystore-path "/Users/jumar/my-key-store.jks")
(.store my-keystore (java.io.FileOutputStream. keystore-path) my-password)
;; now read the key from the saved keystore
(def read-keystore (KeyStore/getInstance (KeyStore/getDefaultType)))
(.load read-keystore (java.io.FileInputStream. keystore-path) my-password)
(.getEntry read-keystore my-key-alias my-key-password)
;; => #object[java.security.KeyStore$SecretKeyEntry 0x58b80b62 "Secret key entry with algorithm DES/CBC"]
,)
And btw. I also copy-pasted your code to IntelliJ to try it quickly and it all worked - again, using OpenJDK 17.