java网络学习之 KeyTool 和openssl学习以及 证书操作(11)

本文详细介绍了keytool命令的各种操作,包括创建、查看、导入和导出证书等。还提供了多个示例,帮助理解如何管理和维护证书库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 keytool 命令选项如下所示:

 可以看出 功能基本分为  四类:

1 生成证书请求,生成证书,生成秘钥,生成秘钥对(证书库)

2 导出证书,导入口令,导入证书或者证书链,导入秘钥库的条目

3 更改条目别名,删除条目,更改条目秘钥口令,更改秘钥库口令

4 列出秘钥库条目,打印证书内容,打印证书请求内容,打印CRL文件内容。

 

 1 创建秘钥对:

keytool -genkeypair -help 可以查看生成秘钥对可用的选项。其中加密算法必须是非对称加密算法,签名算法也要和非对称加密算法配套才可以。

这几个选项默认值如下:
-alias "mykey"
-keyalg "DSA"
-keysize 1024
-validity 90


keytool -genkeypair -alias "test1" -keyalg "RSA" -keystore "test.keystore"   这样就可以生成一个秘钥对

复杂一点的例子 如下:

keytool -genkeypair -alias "tomcat" -keyalg "RSA" -keystore "d:\mykeystore.keystore"  -dname "CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN" -keypass "123456" -storepass "changeit" -validity 180 

 

keytool -genkeypair -alias "test1" -keyalg "RSA" -storetype JKS -keystore "test.jks"

storetype 一共有JKS    PCKS12     JCEKS    BKS   UBER 五种类型

 

2 查看证书库内容

 keytool -list -keystore test.keystore

返回:

输入密钥库口令:  

 

密钥库类型: JKS

密钥库提供方: SUN

 

您的密钥库包含 1 个条目

 

test, 2019-3-23, PrivateKeyEntry, 

证书指纹 (SHA1): 37:0E:D4:C0:EA:5E:0F:68:8B:53:2E:38:C0:F7:19:BF:32:7E:E0:97

 

3 导出证书库中的别名为test的证书

keytool -export -alias test -file test.crt -keystore test.keystore 

这个命令需要交互输入秘钥库的密码,如果不想交互可以直接这样写

keytool -export -alias tomcat -keystore d:\mykeystore -file d:\mycerts.cer -storepass 123456

 

export 有一个选项是  "-rfc"   表示以base64输出文件,否则以二进制输出。

keytool -export -alias test  -file test2.crt -rfc  -keystore test1.keystore

这样导出的文件内容如下

-----BEGIN CERTIFICATE-----

MIIDdzCCAl+gAwIBAgIEfKCA9DANBgkqhkiG9w0BAQsFADBsMRAwDgYDVQQGEwdVbmtub3duMRAw

DgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYDVQQKEwdVbmtub3duMRAwDgYD

-----END CERTIFICATE-----

 

4 导入证书到证书库

首先按照刚才步骤创建一个新的证书库keytool -genkeypair -alias "test1" -keyalg "RSA" -keystore "test1.keystore"

然后使用  keytool -import -keystore test1.keystore -file test.crt 就把证书导入到了test1.keystore 中。

这之后再次查看新的证书库发现变成了2个条目:

 

5 查看证书信息

keytool -printcert -file "test.crt"

返回 :

所有者: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown

发布者: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown

序列号: 7ca080f4

有效期开始日期: Sat Mar 23 23:09:08 CST 2019, 截止日期: Fri Jun 21 23:09:08 CST 2019

证书指纹:   //这是当前证书用不同的算法获得的不同签名结果

MD5: B6:B3:F5:F1:E3:72:DD:0D:C9:CB:05:E9:4A:C7:D4:63

SHA1: 06:4E:16:62:2F:A6:2B:CB:14:FD:77:9C:60:3B:6A:F2:2C:75:6A:EB

SHA256: E0:97:95:A5:D6:08:E9:80:78:CB:D7:BE:A8:15:24:D8:13:17:03:52:B3:13:F5:DC:E3:01:03:6C:15:A0:17:E6

签名算法名称: SHA256withRSA    //这是证书的默认签名算法

版本: 3

 

扩展: 

 

#1: ObjectId: 2.5.29.14 Criticality=false

SubjectKeyIdentifier [

KeyIdentifier [

0000: 93 76 E3 A5 6B 3E C9 51   F1 77 38 3E 62 2A 3F 76  .v..k>.Q.w8>b*?v

0010: 26 26 EB A8                                        &&..

]

]

 

6 修改秘钥库中某个条目的秘钥口令

keytool -keypasswd -alias test -keystore test.keystore

7 修改条目的别名

keytool -changealias -keystore test.keystore -alias test -destalias newone

 

8 删除秘钥库中的条目

keytool -delete -keystore test.keystore -alias test

 

9不同类型的秘钥库之间的转化

jks类型秘钥库转化为 pcks12 类型秘钥库

keytool -importkeystore -srckeystore test.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore test.p12

pcks12 类型秘钥库转化为 jks类型秘钥库

keytool -importkeystore -srckeystore test.p12 -srcstoretype PKCS12 -deststoretype JKS -destkeystore test.jks

pcks12 类型秘钥库转化为 jce 类型秘钥库

keytool -importkeystore -srckeystore test.p12 -srcstoretype PKCS12 -deststoretype JCEKS -destkeystore test.jce

 

jks类型秘钥库转化为 jce类型秘钥库

keytool -importkeystore -srckeystore test.jks -srcstoretype JKS -deststoretype JCEKS -destkeystore test.jce

 

keytool -importkeystore -srckeystore test.p12 -srcstoretype PKCS12 -deststoretype BKS -destkeystore test.bks

keytool 错误: java.security.KeyStoreException: BKS not found

 

keytool -importkeystore -srckeystore test.p12 -srcstoretype PKCS12 -deststoretype UBER -destkeystore test.ubr

keytool 错误: java.security.KeyStoreException: UBER not found

 

not found 的错误是因为本机没有安装必要的组件。

 

证书编码格式

同样的X.509证书,可能有不同的编码格式,目前有以下两种编码格式.

PEM - Privacy Enhanced Mail,打开看文本格式,以"-----BEGIN..."开头, "-----END..."结尾,内容是BASE64编码.
查看PEM格式证书的信息:openssl x509 -in certificate.pem -text -noout
Apache和*NIX服务器偏向于使用这种编码格式.

DER - Distinguished Encoding Rules,打开看是二进制格式,不可读.
查看DER格式证书的信息:openssl x509 -in certificate.der -inform der -text -noout
Java和Windows服务器偏向于使用这种编码格式.

 

证书编码的转换

PEM转为DER openssl x509 -in cert.crt -outform der -out cert.der

DER转为PEM openssl x509 -in cert.crt -inform der -outform pem -out cert.pem

(提示:要转换KEY文件也类似,只不过把x509换成rsa,要转CSR的话,把x509换成req...)

 

相关的文件扩展名

这是比较误导人的地方,虽然我们已经知道有PEM和DER这两种编码格式,但文件扩展名并不一定就叫"PEM"或者"DER",常见的扩展名除了PEM和DER还有以下这些,它们除了编码格式可能不同之外,内容也有差别,但大多数都能相互转换编码格式.

CRT - CRT应该是certificate的三个字母,其实还是证书的意思,常见于*NIX系统,有可能是PEM编码,也有可能是DER编码,大多数应该是PEM编码,相信你已经知道怎么辨别.

CER - 还是certificate,还是证书,常见于Windows系统,同样的,可能是PEM编码,也可能是DER编码,大多数应该是DER编码.

KEY - 通常用来存放一个公钥或者私钥,并非X.509证书,编码同样的,可能是PEM,也可能是DER.
查看KEY的办法:openssl rsa -in mykey.key -text -noout
如果是DER格式的话,同理应该这样了:openssl rsa -in mykey.key -text -noout -inform der

CSR - Certificate Signing Request,即证书签名请求,这个并不是证书,而是向权威证书颁发机构获得签名证书的申请,其核心内容是一个公钥(当然还附带了一些别的信息),在生成这个申请的时候,同时也会生成一个私钥,私钥要自己保管好.做过iOS APP的朋友都应该知道是怎么向苹果申请开发者证书的吧.
查看的办法:openssl req -noout -text -in my.csr (如果是DER格式的话照旧加上-inform der,这里不写了)

PFX/P12 - predecessor of PKCS#12,对*nix服务器来说,一般CRT和KEY是分开存放在不同文件中的,但Windows的IIS则将它们存在一个PFX文件中,(因此这个文件包含了证书及私钥)这样会不会不安全?应该不会,PFX通常会有一个"提取密码",你想把里面的东西读取出来的话,它就要求你提供提取密码,PFX使用的时DER编码,如何把PFX转换为PEM编码?
openssl pkcs12 -in for-iis.pfx -out for-iis.pem -nodes
这个时候会提示你输入提取代码. for-iis.pem就是可读的文本.
生成pfx的命令类似这样:openssl pkcs12 -export -in certificate.crt -inkey privateKey.key -out certificate.pfx -certfile CACert.crt

其中CACert.crt是CA(权威证书颁发机构)的根证书,有的话也通过-certfile参数一起带进去.这么看来,PFX其实是个证书密钥库.

JKS - 即Java Key Storage,这是Java的专利,跟OpenSSL关系不大,利用Java的一个叫"keytool"的工具,可以将PFX转为JKS,当然了,keytool也能直接生成JKS,不过在此就不多表了.

 

openssl 命令学习  

https://blog.youkuaiyun.com/liao20081228/article/details/77159039

 

PEM 转换 DER

 openssl x509 -outform der -in certificate.pem -out certificate.der  //红色部分指定out文件的编码方式

PEM 转换 P7B

openssl crl2pkcs7 -nocrl -certfile certificate.cer -out certificate.p7b -certfile CAcert.cer  //ca机构的根证书

 

PEM 转换 PFX

 openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CAcert.crt


DER 转换 PEM

 openssl x509 -inform der -in certificate.cer -out certificate.pem    //红色部分指定in文件的编码方式


P7B 转换 PEM

openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer

 

PFX 转换 PEM

$ openssl pkcs12 -in certificate.pfx -out certificate.cer -nodes

 

 

1如何加载秘钥库

public static KeyStore getKeyInfo(String pfxkeyfile, String keypwd,
			String type) throws IOException {
		LogUtil.writeLog("加载签名证书==>" + pfxkeyfile);
		FileInputStream fis = null;
		try {
			KeyStore ks = null;
			if ("JKS".equals(type)) {
				ks = KeyStore.getInstance(type);
			} else if ("PKCS12".equals(type)) {
				String jdkVendor = System.getProperty("java.vm.vendor");
				String javaVersion = System.getProperty("java.version");
				LogUtil.writeLog("java.vm.vendor=[" + jdkVendor + "]");
				LogUtil.writeLog("java.version=[" + javaVersion + "]");
//				Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
				if (null != jdkVendor && jdkVendor.startsWith("IBM")) {
					// 如果使用IBMJDK,则强制设置BouncyCastleProvider的指定位置,解决使用IBMJDK时兼容性问题
					Security.insertProviderAt(
							new org.bouncycastle.jce.provider.BouncyCastleProvider(),
							1);
					printSysInfo();
				}else{
					Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
				}
//				ks = KeyStore.getInstance(type, "BC");
				ks = KeyStore.getInstance(type);
			}
			LogUtil.writeLog("Load RSA CertPath=[" + pfxkeyfile + "],Pwd=["
					+ keypwd + "]");
			fis = new FileInputStream(pfxkeyfile);
			char[] nPassword = null;
			nPassword = null == keypwd || "".equals(keypwd.trim()) ? null
					: keypwd.toCharArray();
			if (null != ks) {
				ks.load(fis, nPassword);
			}
			return ks;
		} catch (Exception e) {
			if (Security.getProvider("BC") == null) {
				LogUtil.writeLog("BC Provider not installed.");
			}
			LogUtil.writeErrorLog("getKeyInfo Error", e);
			if ((e instanceof KeyStoreException) && "PKCS12".equals(type)) {
				Security.removeProvider("BC");
			}
			return null;
		}finally{
			if(null!=fis)
				fis.close();
		}
	}

2 如何从秘钥库中获取公钥证书

public static PublicKey getSignPublicKey() {
   try {
      Enumeration<String> aliasenum = keyStore.aliases();
      String keyAlias = null;
      if (aliasenum.hasMoreElements()) // we are readin just one
      // certificate.
      {
         keyAlias = (String) aliasenum.nextElement();
      }
      Certificate cert = keyStore.getCertificate(keyAlias);
      PublicKey pubkey = cert.getPublicKey();
      return pubkey;
   } catch (Exception e) {
      LogUtil.writeErrorLog(e.toString());
      return null;
   }
}

3 从秘钥库中获取私钥

PrivateKey privateKey = (PrivateKey) keystore.getKey(keyAlias, certPwd.toCharArray());

4: 从x509证书文件中读取获取证书对象

/**
 * 
 * @param path
 * @return
 */
private static X509Certificate initCert(String path) {
   X509Certificate encryptCertTemp = null;
   CertificateFactory cf = null;
   FileInputStream in = null;
   try {
      cf = CertificateFactory.getInstance("X.509");
      in = new FileInputStream(path);
      encryptCertTemp = (X509Certificate) cf.generateCertificate(in);
      // 打印证书加载信息,供测试阶段调试
      LogUtil.writeLog("[" + path + "][CertId="
            + encryptCertTemp.getSerialNumber().toString() + "]");
   } catch (CertificateException e) {
      LogUtil.writeErrorLog("InitCert Error", e);
   } catch (FileNotFoundException e) {
      LogUtil.writeErrorLog("InitCert Error File Not Found", e);
   } finally {
      if (null != in) {
         try {
            in.close();
         } catch (IOException e) {
            LogUtil.writeErrorLog(e.toString());
         }
      }
   }
   return encryptCertTemp;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值