如何在 Java KeyStore 中存储一个简单的密钥字符串?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6243446/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to store a simple key string inside Java KeyStore?
提问by Roy Tsabari
I have a file on my FS (a S3 AWS key) that contains a string that is a key I use for encryption process.
我的 FS 上有一个文件(一个 S3 AWS 密钥),其中包含一个字符串,该字符串是我用于加密过程的密钥。
I would like to move it a Java KeyStore.
我想将它移动到 Java KeyStore。
I know how to import a certificate into a KeyStore with keytool but I can't find the way to import a simple string key.
我知道如何使用 keytool 将证书导入 KeyStore,但我找不到导入简单字符串密钥的方法。
Can you help?
你能帮我吗?
采纳答案by Charlie
I don't see a way to do it with keytool, but some poking about, I wonder if you could store and retrieve it in code as a PasswordBasedEncryption (PBE) SecretKey. (Disclaimer: I haven't tried this myself).
我没有看到用 keytool 来做这件事的方法,但有些人想知道你是否可以在代码中存储和检索它作为 PasswordBasedEncryption (PBE) SecretKey。(免责声明:我自己没有尝试过)。
The resources that drove this thought: PBEKeySpec javadocand CryptoSpec - Using Password Based Encryption example
推动这种想法的资源: PBEKeySpec javadoc和CryptoSpec - Using Password Based Encryption example
回答by JasonG
You can do this with PBE and JCEKS. I don't think you can do it with JKS. Solution:
您可以使用 PBE 和 JCEKS 来做到这一点。我认为你不能用 JKS 做到这一点。解决方案:
Create a keystore to store and get entries from:
创建一个密钥库来存储和获取条目:
keytool -keystore clientkeystore -genkey -alias client -storetype jceks
Now some code to test it out.
现在一些代码来测试它。
public static String getPasswordFromKeystore(String entry, String keystoreLocation, String keyStorePassword) throws Exception{
KeyStore ks = KeyStore.getInstance("JCEKS");
ks.load(null, keyStorePassword.toCharArray());
KeyStore.PasswordProtection keyStorePP = new KeyStore.PasswordProtection(keyStorePassword.toCharArray());
FileInputStream fIn = new FileInputStream(keystoreLocation);
ks.load(fIn, keyStorePassword.toCharArray());
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBE");
KeyStore.SecretKeyEntry ske =
(KeyStore.SecretKeyEntry)ks.getEntry(entry, keyStorePP);
PBEKeySpec keySpec = (PBEKeySpec)factory.getKeySpec(
ske.getSecretKey(),
PBEKeySpec.class);
char[] password = keySpec.getPassword();
return new String(password);
}
public static void makeNewKeystoreEntry(String entry, String entryPassword, String keyStoreLocation, String keyStorePassword)
throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBE");
SecretKey generatedSecret =
factory.generateSecret(new PBEKeySpec(
entryPassword.toCharArray()));
KeyStore ks = KeyStore.getInstance("JCEKS");
ks.load(null, keyStorePassword.toCharArray());
KeyStore.PasswordProtection keyStorePP = new KeyStore.PasswordProtection(keyStorePassword.toCharArray());
ks.setEntry(entry, new KeyStore.SecretKeyEntry(
generatedSecret), keyStorePP);
FileOutputStream fos = new java.io.FileOutputStream(keyStoreLocation);
ks.store(fos, keyStorePassword.toCharArray());
}
回答by Ziferius
I know this is old; but I came across this same use case.
我知道这是旧的;但我遇到了同样的用例。
https://docs.oracle.com/javase/9/tools/keytool.htm#JSWOR-GUID-5990A2E4-78E3-47B7-AE75-6D1826259549
https://docs.oracle.com/javase/9/tools/keytool.htm#JSWOR-GUID-5990A2E4-78E3-47B7-AE75-6D1826259549
keystores have an importpass options that stores a KeyStore.SecretKeyEntry identified by alias.
密钥库有一个 importpass 选项,用于存储由别名标识的 KeyStore.SecretKeyEntry。
So there's that and you could store your string in an alias.
就是这样,您可以将字符串存储在别名中。
回答by Alex
I had to do this this afternoon, the solution of @JasonG works but not the keytool options.
我今天下午必须这样做,@JasonG 的解决方案有效,但 keytool 选项无效。
Since Java 8 you can use the -importpass
option with Keytool, which will help you achieve what you need.
从 Java 8 开始,您可以将该-importpass
选项与 Keytool 一起使用,这将帮助您实现所需。
Let's suppose I want to save the sensitive password foobar
in the mypass
alias in the keystore named myks.jceks
protected with the password password
here, do the following:
假设我想将敏感密码保存在名为protected的密钥库foobar
中的mypass
别名中,请执行以下操作:myks.jceks
password
$ keytool -importpass -storetype pkcs12 -alias mypass -keystore myks.p12
Enter keystore password: <password>
Re-enter new password: <password>
Enter the password to be stored: <foobar>
Re-enter password: <foobar>
Enter key password for <mypass>
(RETURN if same as keystore password): <password>
Re-enter new password: <password>
And then you're good to go to use the same code as @JasonG, I have this in my code:
然后你很高兴去使用与@JasonG 相同的代码,我的代码中有这个:
private Try<String> loadKey(Resource path, String pw) {
return Try.of(() -> {
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(path.getInputStream(), pw.toCharArray());
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBE");
SecretKeyEntry ske = (SecretKeyEntry) ks.getEntry("mypass",
new PasswordProtection(pw.toCharArray()));
PBEKeySpec keySpec = (PBEKeySpec) factory.getKeySpec(
ske.getSecretKey(), PBEKeySpec.class);
return new String(keySpec.getPassword());
});
}
Note that I have used PKCS12 since JCEKS uses a proprietary format, and it is recommended to migrate to PKCS12 which is an industry standard format.
请注意,我使用了 PKCS12,因为 JCEKS 使用专有格式,建议迁移到行业标准格式 PKCS12。
Besides we had some problems with some Windows machine (running Java 8) being stuck while trying to load the JCEKS store, throwing exceptions. PKCS12 seems a better choice.
此外,我们在尝试加载 JCEKS 存储时遇到一些 Windows 机器(运行 Java 8)卡住的问题,抛出异常。PKCS12 似乎是更好的选择。
回答by Op De Cirkel
You can not import in the key store arbitrary strings. In the key store you import certification keys that java libraries are using for authentication of remote hosts.
您不能在密钥库中导入任意字符串。在密钥库中,您导入 Java 库用于远程主机身份验证的证书密钥。