如何将自签名证书正确导入默认情况下可供所有 Java 应用程序使用的 Java 密钥库?
Posted
技术标签:
【中文标题】如何将自签名证书正确导入默认情况下可供所有 Java 应用程序使用的 Java 密钥库?【英文标题】:How to properly import a selfsigned certificate into Java keystore that is available to all Java applications by default? 【发布时间】:2012-07-21 23:09:39 【问题描述】:我确实想将自签名证书导入 Java,因此任何尝试建立 SSL 连接的 Java 应用程序都会信任此证书。
到目前为止,我设法将它导入
keytool -import -trustcacerts -noprompt -storepass changeit -alias $REMHOST -file $REMHOST.pem
keytool -import -trustcacerts -noprompt -keystore cacerts -storepass changeit -alias $REMHOST -file $REMHOST.pem
不过,当我尝试运行 HTTPSClient.class
时,我仍然得到:
javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径
【问题讨论】:
我不一定会依赖该代码。像Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider())
这样的东西在第一部分是完全没有必要的。第二个不做任何证书验证。尝试使用普通的URLConnection
开始。您确定您已在 JRE 安装的 lib/security
中修改了 cacerts
吗?你试过trustmanager
debugging option吗?
【参考方案1】:
在 Windows 上最简单的方法是使用程序portecle。
-
下载并安装 portecle。
首先要 100% 确定您知道使用哪个 JRE 或 JDK 来运行您的程序。在 64 位 Windows 7 上可能有很多 JRE。 Process Explorer 可以为您提供帮助,或者您可以使用:
System.out.println(System.getProperty("java.home"));
将文件 JAVA_HOME\lib\security\cacerts 复制到另一个文件夹。
在 Portecle 中单击文件 > 打开密钥库文件
选择 cacerts 文件
输入此密码:changeit
单击工具 > 导入可信证书
浏览文件 mycertificate.pem
点击导入
单击“确定”以获取有关信任路径的警告。
在显示证书详细信息时单击“确定”。
单击“是”接受受信任的证书。
当它要求输入别名时,单击“确定”,当它说已导入证书时再次单击“确定”。
点击保存。不要忘记这一点,否则更改将被丢弃。
将文件 cacerts 复制回您找到它的位置。
在 Linux 上:
您可以像这样从已经在使用它的 Web 服务器下载 SSL 证书:
$ echo -n | openssl s_client -connect www.example.com:443 | \
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/examplecert.crt
可选择验证证书信息:
$ openssl x509 -in /tmp/examplecert.crt -text
将证书导入 Java cacerts 密钥库:
$ keytool -import -trustcacerts -keystore /opt/java/jre/lib/security/cacerts \
-storepass changeit -noprompt -alias mycert -file /tmp/examplecert.crt
【讨论】:
这里的主要思想不是portecle,而是将证书导入正确的密钥库。 这行得通,但我的 java 在不同的位置。我的密钥库位于 /usr/lib/jvm/java-openjdk/jre/lib/security/cacerts 我通过运行ps -ef | grep java
找到的,它告诉我我的 java 是从位于 /usr/lib/jvm/java 的 openjdk 运行的-openjdk/bin/java。此外,如果对于 web 应用程序,请记住重新启动。感谢您的帮助!
我没用过portecle,但我发现Keystore Explorer在Windows、Linux上运行得很好,(它也应该在OSX上运行)
2019 年,我们甚至可以使用 Lets encrypt 等服务免费获得 SSL 证书
仅供参考,按照 Linux 的步骤在 MacOS 上也能正常工作【参考方案2】:
我最终编写了一个小脚本,将证书添加到密钥库中,因此它更易于使用。
您可以从https://github.com/ssbarnea/keytool-trust获取最新版本
#!/bin/bash
# version 1.0
# https://github.com/ssbarnea/keytool-trust
REMHOST=$1
REMPORT=$2:-443
KEYSTORE_PASS=changeit
KEYTOOL="sudo keytool"
# /etc/java-6-sun/security/cacerts
for CACERTS in /usr/lib/jvm/java-8-oracle/jre/lib/security/cacerts \
/usr/lib/jvm/java-7-oracle/jre/lib/security/cacerts \
"/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/security/cacerts" \
"/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/MacOS/itms/java/lib/security/cacerts"
do
if [ -e "$CACERTS" ]
then
echo --- Adding certs to $CACERTS
# FYI: the default keystore is located in ~/.keystore
if [ -z "$REMHOST" ]
then
echo "ERROR: Please specify the server name to import the certificatin from, eventually followed by the port number, if other than 443."
exit 1
fi
set -e
rm -f $REMHOST:$REMPORT.pem
if openssl s_client -connect $REMHOST:$REMPORT 1>/tmp/keytool_stdout 2>/tmp/output </dev/null
then
:
else
cat /tmp/keytool_stdout
cat /tmp/output
exit 1
fi
if sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' </tmp/keytool_stdout > /tmp/$REMHOST:$REMPORT.pem
then
:
else
echo "ERROR: Unable to extract the certificate from $REMHOST:$REMPORT ($?)"
cat /tmp/output
fi
if $KEYTOOL -list -storepass $KEYSTORE_PASS -alias $REMHOST:$REMPORT >/dev/null
then
echo "Key of $REMHOST already found, skipping it."
else
$KEYTOOL -import -trustcacerts -noprompt -storepass $KEYSTORE_PASS -alias $REMHOST:$REMPORT -file /tmp/$REMHOST:$REMPORT.pem
fi
if $KEYTOOL -list -storepass $KEYSTORE_PASS -alias $REMHOST:$REMPORT -keystore "$CACERTS" >/dev/null
then
echo "Key of $REMHOST already found in cacerts, skipping it."
else
$KEYTOOL -import -trustcacerts -noprompt -keystore "$CACERTS" -storepass $KEYSTORE_PASS -alias $REMHOST:$REMPORT -file /tmp/$REMHOST:$REMPORT.pem
fi
fi
done
```
【讨论】:
"sudo keytool" NOPE【参考方案3】: D:\Java\jdk1.5.0_10\bin\keytool -import -file "D:\Certificates\SDS services\Dev\dev-sdsservices-was8.infavig.com.cer" -keystore "D:\Java\jdk1.5.0_10\jre\lib\security\cacerts" -alias "sds certificate"
【讨论】:
系统会提示您输入密钥库密码,默认为“changeit” 至少在 java 11 (sapmachine jre) 中,语法根据 manfile 略有变化:keytool.exe -importcert -file <path to cer file> -cacerts -alias "<your alias>"
【参考方案4】:
如果您使用的是 Java cacerts 文件中默认不包含的证书颁发机构签名的证书,则需要完成以下 HTTPS 连接配置。 要将证书导入 cacerts:
打开 Windows 资源管理器并导航到 cacerts 文件,该文件位于安装 AX Core 客户端的 jre\lib\security 子文件夹中。默认位置是 C:\Program Files\ACL Software\AX Core Client\jre\lib\security
在进行任何更改之前创建文件的备份副本。
根据您从所使用的证书颁发机构收到的证书,您可能需要将中间证书和/或根证书导入 cacerts 文件。使用以下语法导入证书:
keytool -import -alias <alias> -keystore <cacerts_file> -trustcacerts -file <certificate_filename>
如果您同时导入两个证书,则为每个证书指定的别名应该是唯一的。
在“密码”提示符处键入密钥库的密码,然后按 Enter。 cacerts 文件的默认 Java 密码是“changeit”。 在“信任此证书?”中键入“y”提示并按 Enter。
【讨论】:
使用这个命令 :-> keytool -import -alias -keystore不妨试试
keytool -import -trustcacerts -noprompt -keystore <full path to cacerts> -storepass changeit -alias $REMHOST -file $REMHOST.pem
如果你只写cacerts
,我真的不知道它把你的证书放在哪里,只是给它一个完整的路径
【讨论】:
【参考方案6】:这对我有用。 :)
sudo keytool -importcert -file filename.cer -alias randomaliasname -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit【讨论】:
请注意,您可以使用-cacerts
选项,而不是使用-keystore
提供路径。这很有用,因为确切的路径会根据您是否安装了 jdk 或 jre 而有所不同。
@not2savvy 另请注意 -cacerts 选项仅适用于 Java 9 及更高版本
@MuizzMahdy 没错,另见my detailed answer here。【参考方案7】:
简单的命令“keytool”也适用于 Windows 和/或 Cygwin。
如果您使用的是 Cygwin,这是我从“S.Botha's”答案底部使用的修改后的命令:
-
确保您在 JDK 中识别出您将使用的 JRE
以管理员身份启动您的提示/cygwin
进入该 JDK 的 bin 目录,例如cd /cygdrive/c/Program\ Files/Java/jdk1.8.0_121/jre/bin
在其中执行 keytool 命令,最后提供新证书的路径,如下所示:
./keytool.exe -import -trustcacerts -keystore ../lib/security/cacerts -storepass changeit -noprompt -alias myownaliasformysystem -file "D:\Stuff\saved-certs\ca.cert"
注意,因为如果这是在 Cygwin 下,您将给出一个非 Cygwin 程序的路径,所以该路径类似于 DOS 并用引号括起来。
【讨论】:
【参考方案8】:在 java linux 中安装证书
/opt/jdk(version)/bin/keytool -import -alias aliasname -file certificate.cer -keystore cacerts -storepass 密码
【讨论】:
【参考方案9】:首先从提供者那里获得证书。创建一个以 .cer 结尾的文件并粘贴证书。
复制文本文件或将其粘贴到您可以访问的地方,然后以管理员身份使用 cmd 提示符并 cd 到 jdk 的 bin;将使用的命令是:keytool
使用以下命令更改密钥库的密码:
keytool -storepasswd -keystore "path of the key store from c\ and down"
密码是:changeit
然后您将被要求输入两次新密码。然后输入以下内容:
keytool -importcert -file "C:\Program Files\Java\jdk-13.0.2\lib\security\certificateFile.cer" -alias chooseAname -keystore "C:\Program Files\Java\jdk-13.0.2\lib\security\cacerts"
【讨论】:
【参考方案10】:您可以在 Java 安装中使用 keytool
,并且应该在 $JAVA_HOME/bin
中。 Java 密钥库位于 $JAVA_HOME/lib/security/cacerts
或 $JAVA_HOME/jre/lib/security/cacerts
中,这取决于您是否安装了 JDK 或 JRE。
如果使用 Java 9 或更高版本,则无需知道确切位置。您可以使用-cacerts
选项作为快捷方式。
Java 9+
所以对于 Java 9(又名 Java 1.9)或更高版本,只需使用
keytool -importcert -trustcacerts -cacerts -file myCert.pem -alias myCert
早期的 Java 版本
对于 Java 8(又名 1.8)或更早版本,您必须像这样指定密钥库位置
keytool -importcert -trustcacerts $JAVA_HOME/lib/security/cacerts -file myCert.pem -alias myCert
对于 Java 5(又名 1.5)或更早版本,-importcert
选项不存在。它被称为-import
,但除此之外它是相同的。所以使用
keytool -import -trustcacerts $JAVA_HOME/lib/security/cacerts -file myCert.pem -alias myCert
其他选项
系统将要求您输入信任库密码,默认密码是 changeit。 如果需要无人值守运行导入,可以加-storepass changeit -noprompt
在某些较旧的 Java 版本(我不知道)中,-importcert
不存在,但您可以简单地使用 -import
,如果您偶然发现了这么旧的版本。
格式
keytool
可以导入 X.509 v1、v2 和 v3 证书,以及由该类型 (P7B) 证书组成的 PKCS#7 格式证书链。必须提供要导入的数据
-----BEGIN
和 -----END
行 (PEM) 中
注意:我不确定 PEM 格式的证书链是否真的有效。
奖励脚本
恐怕是 bash,所以没有适用于 Windows 用户的解决方案。
这个简单的脚本是由 *** 上的几个有用的问题和聪明的答案创建的,它检查 Java 版本并 - 如有必要 - 确定正确的密钥库位置,它可以在一个命令中导入多个证书。请注意,您必须在单引号中传递文件模式参数(请参阅用法)。
addcerts.sh
#!/bin/bash
# Add custom root certificates to Java trust store
if [ "$#" -ne 1 ]; then
SCRIPT=`basename "$0"`
echo "Usage: $SCRIPT 'path/to/certs/*'"
exit 1
fi
CERTFILES=$1
JAVA_VERSION=`java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1`
if (( $JAVA_VERSION >= 9 )); then
CACERTS="-cacerts"
else
# Check where cacerts are located
# differs depending or jdk or jre installed
if [ -d "$JAVA_HOME/jre" ]; then
CACERTS="$JAVA_HOME/jre"
else
CACERTS="$JAVA_HOME"
fi
CACERTS="-keystore $CACERTS/lib/security/cacerts"
fi
# Now add certificates
for CERTFILE in $CERTFILES; do
# Remove path, then suffix to derive alias from filename
ALIAS=$CERTFILE##*/
ALIAS=$ALIAS%.*
$JAVA_HOME/bin/keytool -importcert -file "$CERTFILE" -alias "$ALIAS" $CACERTS -trustcacerts -storepass changeit -noprompt
if [ $? -ne 0 ]; then
echo "Failed to add $CERTFILE as $ALIAS to $CACERTS"
exit 1
fi
done
【讨论】:
【参考方案11】:在 Windows 中,这些命令在命令行上运行:
cd C:\Program Files\Java\jre1.8.0_301\lib\security\
keytool -import -trustcacerts -alias cert_ssl -file C:\opt\esb-config\keystores\cert.cer -noprompt -storepass changeit -keystore cacerts
changeit
是信任库的默认密码。
【讨论】:
以上是关于如何将自签名证书正确导入默认情况下可供所有 Java 应用程序使用的 Java 密钥库?的主要内容,如果未能解决你的问题,请参考以下文章
如何将自签名 SSL 证书上传到 Elastic Beanstalk