前言
最近在做PDF签名相关的功能,其中需要使用证书来签名。于是参考OpenSSL和其他网络文章,作成了一些方便的脚本文件来创建CA证书和终端证书。
一、OpenSSL简介
关于证书相关的概念可以自行搜索相关文章,这里就不赘述了。OpenSSL命令的使用可以参数其官方网站,其中包含各个命令及其参数的详细说明。
二、作成证书脚本文件
首先安装OpenSSL,可以从https://slproweb.com/download/Win64OpenSSL_Light-3_1_3.msi下载安装程序。
下面的脚本假设OpenSSL的安装目录为: D:\opts\OpenSSL-Win64\bin
,可以根据自己的情况调整。
1. 生成根证书
代码如下(示例):
@echo off
path D:\opts\OpenSSL-Win64\bin;%PATH%
setlocal enabledelayedexpansion
rem 设置CA的根目录
set CATOP=%~dp0
set OPENSSL_CONF=%CATOP%openssl.cnf
for /f "tokens=1 delims= " %%i in (ca-list) do (
set ca_name=%%i
set ca_dir=%CATOP%!ca_name!
set ca_crt=!ca_dir!\cacert.pem
set ca_key=!ca_dir!\private\cakey.pem
if not exist !ca_crt! if not exist !ca_key! (
mkdir !ca_dir!
mkdir !ca_dir!\private
openssl req ^
-new ^
-keyout !ca_key! ^
-out !ca_crt! ^
-passout "pass:mycap@ss" ^
-subj "/C=CN/ST=ShanngXi/O=Test/CN=!ca_name!" ^
-x509 -days 1095 -extensions v3_ca
)
)
文件ca-list
内容如下:
Test-Root-CA
2. 生成终端用户证书
代码如下(示例):
@echo off
path D:\opts\OpenSSL-Win64\bin;%PATH%
setlocal enabledelayedexpansion
rem 设置CA的根目录
set CATOP=%~dp0
set OPENSSL_CONF=%CATOP%openssl.cnf
for /f "tokens=1-4 delims= " %%i in (target-list) do (
set common_name=%%i
set ca_name=%%j
set ext_section=%%k
set expire_days=%%l
set ca_dir=%CATOP%!ca_name!
if not exist !ca_dir!\certs mkdir !ca_dir!\certs >nul
if not exist !ca_dir!\newcerts mkdir !ca_dir!\newcerts >nul
if not exist !ca_dir!\serial echo 1000 >!ca_dir!\serial
if not exist !ca_dir!\index.txt type nul >!ca_dir!\index.txt
set new_key=!ca_dir!\certs\!common_name!.key.pem
set new_csr=!ca_dir!\certs\!common_name!.csr.pem
set new_crt=!ca_dir!\certs\!common_name!.crt.pem
set new_p12=!ca_dir!\certs\!common_name!.p12
if not exist !new_key! (
openssl genrsa -out !new_key! 2048
)
if not exist !new_csr! (
openssl req -new -key !new_key! -out !new_csr! -subj "/title=Title1/street=Street1/initials=F.K./SN=LastName1/GN=FirstName1/name=!common_name!/emailAddress=test@necas.com/CN=!common_name!/O=Test/ST=ShanngXi/C=CN"
)
if not exist !new_crt! (
openssl ca ^
-batch ^
-extensions !ext_section! ^
-out !new_crt! ^
-days !expire_days! ^
-passin pass:mycap@ss ^
-in !new_csr!
)
rem openssl x509 -in Test-Root-CA\certs\alice.crt.pem -noout -text
rem openssl x509 -in Test-Root-CA\certs\alice.crt.pem -noout -nameopt RFC2253 -text
openssl pkcs12 ^
-export ^
-in !new_crt! -inkey !new_key! -chain -CAfile !ca_dir!\cacert.pem ^
-name !common_name! ^
-out !new_p12! ^
-password pass:password
)
endlocal
文件 target-list
内容如下:
Alice Test-Root-CA v3_sign_user 1095
Bob Test-Root-CA v3_sign_user 1095
Carol Test-Root-CA v3_sign_user 1095
3. 撤销终端用户证书
代码如下(示例):
@echo off
path D:\opts\OpenSSL-Win64\bin;%PATH%
setlocal enabledelayedexpansion
rem 设置CA的根目录
set CATOP=%~dp0
set OPENSSL_CONF=%CATOP%openssl.cnf
for /f "tokens=1-2 delims= " %%i in (revoke-list) do (
rem 在这里定义的变量需要使用!访问
set common_name=%%i
set ca_name=%%j
set ca_dir=%CATOP%!ca_name!
set crt_file=!ca_dir!\certs\!common_name!.crt.pem
if exist !crt_file! (
openssl ca ^ -revoke !crt_file! -passin pass:mycap@ss
)
)
endlocal
文件 revoke-list
内容如下:
Carol NECAS-Root-CA
4. 更新撤销列表(CRL)
代码如下(示例):
@echo off
path D:\opts\OpenSSL-Win64\bin;%PATH%
setlocal enabledelayedexpansion
rem 设置CA的根目录
set CATOP=%~dp0
set OPENSSL_CONF=%CATOP%openssl.cnf
for /f "tokens=1 delims= " %%i in (ca-list) do (
set ca_name=%%i
set ca_dir=%CATOP%!ca_name!
set crl_file=!ca_dir!\crl\crl.pem
echo !crl_file!
if not exist !ca_dir!\crl mkdir !ca_dir!\crl
if not exist !ca_dir!\crlnumber echo 00 >!ca_dir!\crlnumber
openssl ca -gencrl -crldays 365 -out !crl_file! -passin pass:mycap@ss
)
endlocal
5. OpenSSL的配置文件
其内容如下:
dir=.
CA_DIR=.\demoCA
[ ca ]
default_ca = CA_default
[ CA_default ]
prompt = no
dir = $ENV::CA_DIR
certs = $dir/certs
crl_dir = $dir/crl
database = $dir/index.txt
new_certs_dir=$dir/newcerts
certificate=$dir/cacert.pem
serial=$dir/serial
crlnumber=$dir/crlnumber
crl=$dir/crl.pem
private_key=$dir/private/cakey.pem
default_days=365
default_crl_days=30
default_md=default
#preserve=no
policy=policy_match
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
name = optional
givenName = optional
surname = optional
initials = optional
streetAddress = optional
title = optional
[ req ]
default_bits=2048
default_keyfile=privkey.pem
distinguished_name=req_distinguished_name
attributes=req_attributes
x509_extensions=v3_ca
# input_password=myp@ss
# output_password=myp@ss
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = CN
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = ShanngXi
localityName = Locality Name (eg, city)
organizationName = Organization Name (eg, company)
organizationName_default = Test
# we can do this but it is not needed normally :-)
#1.organizationName = Second Organization Name (eg, company)
#1.organizationName_default = World Wide Web Pty Ltd
organizationalUnitName = Organizational Unit Name (eg, section)
#organizationalUnitName_default =
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64
emailAddress = Email Address
emailAddress_default = test@test.com
emailAddress_max = 64
# SET-ex3 = SET extension number 3
name=Name
name_default=Name1
givenName=FirstName
givenName_default=FirstName1
surname=LastName
surname_default=LastName1
initials=Initials
initials_default=F.K.
streetAddress=Street
streetAddress_default=Street1
title=Title
title_default=Title1
[ req_attributes ]
[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = CA:true
keyUsage = cRLSign, keyCertSign
[ v3_sign_user ]
basicConstraints = CA:false
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
subjectAltName = @SubjectAlternativeName
crlDistributionPoints=@crl_section
authorityInfoAccess=@ocsp_section
[ SubjectAlternativeName ]
IP.1 = 127.0.0.1
DNS.1 = localhost
[ crl_section ]
URI.0 = http://localhost:8080/crl.pem
[ ocsp_section ]
caIssuers;URI.0 = http://localhost:8080/cacert.pem
OCSP;URI.0 = http://localhost:8080/ocsp
关于配置需要特别说明的是req_distinguished_name
节点中DN的字段还需要在policy-match
节设置字段每个字段的策略,否则在签署的证书中将不包含未指定策略的字段。
总结
因为脚本执行的过程中不需要然后输入,可以自动化的快速创建测试需要的各个证书。当然也可以修改上面的脚本以符合其他使用的目的,希望能抛砖引玉。如能对你有所帮助也不胜荣幸。
仅供参考,如有帮助不胜荣幸,如需转载请注明出处。
请关注、点赞、收藏。