【实用工具系列】(7)使用OpenSSL创建证书


前言

最近在做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节设置字段每个字段的策略,否则在签署的证书中将不包含未指定策略的字段。


总结

因为脚本执行的过程中不需要然后输入,可以自动化的快速创建测试需要的各个证书。当然也可以修改上面的脚本以符合其他使用的目的,希望能抛砖引玉。如能对你有所帮助也不胜荣幸。


仅供参考,如有帮助不胜荣幸,如需转载请注明出处。
请关注、点赞、收藏。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值