國密開發總結
國密開發環境搭建及雙證書生成
GMSSL
GmSSL是一個開放源代碼加密工具包,它提供對GM / T串行標准中指定的中國國家加密算法和協議的第一級支持。作為OpenSSL項目的一個分支,GmSSL提供與OpenSSL的API級別兼容性並維護所有功能。在此感謝貢獻,該項目地址:(https://github.com/guanzhi/GmSSL)
1. 代碼下載及配置變量
# 通過git下載
$ git clone https://github.com/guanzhi/GmSSL gmssl
# 如果嫌下載速度慢,也可下載代碼壓縮包
$ wget https://github.com/guanzhi/GmSSL/archive/master.zip
$ unzip master.zip
2. 編譯與安裝
$ cd 你解壓的目錄
$ ./config --prefix=/usr/local/gmssl
$ make
$ make install
$ cd /usr/local/gmssl
# tree:顯示目錄樹 -d:只顯示目錄 -L:選擇顯示的目錄深度 /usr/local/gmssl目錄樹如下
$ tree -L 2
.
|-- bin
| |-- c_rehash
| |-- gmssl
| `-- openssl -> gmssl
|-- include
| `-- openssl
|-- lib
| |-- engines-1.1
| |-- libcrypto.a
| |-- libcrypto.so -> libcrypto.so.1.1
| |-- libcrypto.so.1.1
| |-- libssl.a
| |-- libssl.so -> libssl.so.1.1
| |-- libssl.so.1.1
| `-- pkgconfig
|-- share
| |-- doc
| `-- man
`-- ssl
|-- certs
|-- misc
|-- openssl.cnf
|-- openssl.cnf.dist
`-- private
-
config貌似動態編譯、靜態編譯也會有一定的影響,(no-shared 不去編譯動態庫,編譯出來的 gmssl不再依賴 libssl.so ,避免因缺少動態庫出錯)這塊我也不是很了解,等日后我有了提升再來說說。
-
openssl.cnf位於/usr/local/gmssl/ssl下,可以按需修改生成各種文件位置、信息等等,需要注意的是生成證書、私鑰的位置、名稱要與openssl中保持一致。
3. 配置環境變量及檢測
如果不配置,就會出現找不到gmssl命令的情況
# 配置安裝路徑 在已有的PATH等變量前面添加路徑‘:’號為分隔符,這種只是臨時生效,關閉shell即失效
PATH=/usr/local/gmssl/bin:$PATH
LD_LIBRARY_PATH=/usr/local/gmssl/lib:$LD_LIBRARY_PATH
- 在/etc/profile文件中添加變量對所有用戶生效(永久的)
vim /etc/profile
#編輯
export PATH=/usr/local/gmssl/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/gmssl/lib:$LD_LIBRARY_PATH
source /etc/profile
4.初始化目錄
這是我openssl.cnf的部分配置,詳細配置可以參考
OpenSSL主配置文件
# 創建根目錄
mkdir -p /home/gmssl/demoCA
cd /home/gmssl/demoCA
mkdir certs crl newcerts private
# 在此路徑下要創建好/usr/local/gmssl/ssl/openssl.cnf中需要的certs, crl ,new_certs_dir和private_key的子目錄,默認是newcerts和private
touch index.txt
echo '01' > serial
5.生成國密證書
- 生成根證書
# 生成 私鑰key
gmssl ecparam -genkey -name sm2p256v1 -text -out CA.key -config /usr/local/gmssl/ssl/openssl.cnf
# 生成證書簽名請求
gmssl req -new -key CA.key -out Root.req
# 生成根證書
gmssl x509 -req -days 3650 -sm3 -in Root.req -signkey Root.key -out RootCA.crt
- 生成服務端證書
# 生成私鑰
gmssl ecparam -genkey -name sm2p256v1 -text -out Server.key
#證書項說明
C-----國家(Country Name)
ST----省份(State or Province Name)
L----城市(Locality Name)
O----公司(Organization Name)
OU----部門(Organizational Unit Name)
CN----產品名(Common Name)
emailAddress----郵箱(Email Address)
#證書請求
gmssl req -new -key Server.key -out Server.csr -subj /C=CN/ST=Beijing/L=Beijing/O=CSG/OU=WangAn (GM)/CN=*.vpn.test.cn -config /usr/local/gmssl/ssl/openssl.cnf
#簽發證書
gmssl x509 -req -sm3 -days 3650 -CA RootCA.crt -CAkey Root.key -CAcreateserial -in Server.req -out ServerCA.crt
# 證書驗證
gmssl verify -CAfile RootCA.crt ServerCA.crt
.crt ServerCA.crt
ServerCA.crt: OK
$ tree
.
|-- certs
|-- crl
|-- index.txt
|-- newcerts
|-- private
| `-- Root.key
|-- RootCA.crt
|-- RootCA.srl
|-- Root.key
|-- Root.req
|-- serial
|-- ServerCA.crt
|-- Server.csr
`-- Server.key
- 生成客戶端證書
# 生成私鑰
gmssl ecparam -genkey -name sm2p256v1 -text -out Client.key -config /usr/local/gmssl/ssl/openssl.cnf
# 生成客戶證書請求
gmssl req -new -key Client.key -out Client.req -subj /C=CN/ST=Beijing/L=Beijing/O=CSG/OU=WangAn (GM)/CN=*.vpn.test.cn -config /usr/local/gmssl/ssl/openssl.cnf
# 簽發證書
gmssl x509 -req -sm3 -days 3650 -CA RootCA.crt -CAkey demoCA/private/Root.key -CAcreateserial -in Client.req -out Client.crt
# 證書驗證
gmssl verify -CAfile RootCA.crt Client.crt
6.生成腳本
不過像我這種懶人,上面僅限於學習明白過程即可,實際中是不會這樣干的。
#!/bin/sh
# gen GM certificate files
CurPath=`dirname $(readlink -f $0)`
GmsslRootPath=/usr/local/gmssl
LdPath=/usr/local/gmssl/lib
GmsslBin=gmssl
DemoCaDir=${GmsslRootPath}/apps/demoCA/
CertDir=${DemoCaDir}/certs/
KeyDir=${CertDir}/keys/
CrlDir=${DemoCaDir}/crl/
ReqDir=${DemoCaDir}/reqs/
CertDays=1500
CACertFile=CA.cert.pem
CAKeyFile=CA.key.pem
CA_DN_STRING=" /C=CN/ST=Beijing/L=Beijing/O=CSG/OU=WangAn (GM)/CN=*.vpn.test.cn"
CAReqFile=CA.req
SSCertFile=SS.cert.pem
SSKeyFile=SS.key.pem
SS_DN_STRING=" /C=CN/ST=Beijing/L=Beijing/O=CSG/OU=WangAn (GM)/CN=*.vpn.test.cn"
SSReqFile=SS.req
SECertFile=SE.cert.pem
SEKeyFile=SE.key.pem
SE_DN_STRING=" /C=CN/ST=Beijing/L=Beijing/O=CSG/OU=WangAn (GM)/CN=*.vpn.test.cn"
SEReqFile=SE.req
CSCertFile=CS.cert.pem
CSKeyFile=CS.key.pem
CS_DN_STRING=" /C=CN/ST=Beijing/L=Beijing/O=CSG/OU=vpn.test.cn/CN=WangAn (GM)"
CSReqFile=CS.req
CECertFile=CE.cert.pem
CEKeyFile=CE.key.pem
CE_DN_STRING=" /C=CN/ST=Beijing/L=Beijing/O=CSG/OU=WangAn (GM)/CN=*.vpn.test.cn"
CEReqFile=CE.req
if [ ! -d "${GmsslRootPath}" ];then
echo "GmSSL path DONOT exist!"
exit 2
fi
export LD_LIBRARY_PATH=${LdPath}
rm -rf "${GmsslRootPath}/apps/demoCA/"
mkdir -p "${CertDir}"
mkdir -p "${KeyDir}"
mkdir -p "${CrlDir}"
mkdir -p "${ReqDir}"
echo "#######################################################################################################"
echo "Generate CA certificate file..."
${GmsslBin} ecparam -name sm2p256v1 -out "${DemoCaDir}/SM2.pem"
${GmsslBin} req -config "${GmsslRootPath}/apps/openssl.cnf" -nodes -subj "${CA_DN_STRING}" \
-keyout "${KeyDir}/${CAKeyFile}" -newkey "ec:${DemoCaDir}/SM2.pem" \
-new -out "${ReqDir}/${CAReqFile}"
#Sign CA certificate with CAKeyFile
${GmsslBin} x509 -sm3 -req -days ${CertDays} -in "${ReqDir}/${CAReqFile}" \
-extfile "${GmsslRootPath}/apps/openssl.cnf" -extensions v3_ca -signkey "${KeyDir}/${CAKeyFile}" \
-CAcreateserial -out "${CertDir}/${CACertFile}"
#Print CA certificate file
${GmsslBin} x509 -in "${CertDir}/${CACertFile}" -noout -text
echo "#######################################################################################################"
echo "Generate Server sign certificate file..."
${GmsslBin} req -config "${GmsslRootPath}/apps/openssl.cnf" -nodes -subj "${SS_DN_STRING}" \
-keyout "${KeyDir}/${SSKeyFile}" -newkey "ec:${DemoCaDir}/SM2.pem" \
-new -out "${ReqDir}/${SSReqFile}"
#Sign SS certificate with CAKeyFile
${GmsslBin} x509 -sm3 -req -days ${CertDays} -in "${ReqDir}/${SSReqFile}" \
-CA "${CertDir}/${CACertFile}" -CAkey "${KeyDir}/${CAKeyFile}" \
-extfile "${GmsslRootPath}/apps/openssl.cnf" -extensions v3_req \
-CAcreateserial -out "${CertDir}/${SSCertFile}"
#Print SS certificate file
${GmsslBin} x509 -in "${CertDir}/${SSCertFile}" -noout -text
echo "#######################################################################################################"
echo "Generate Server encrypt certificate file..."
${GmsslBin} req -config "${GmsslRootPath}/apps/openssl.cnf" -nodes -subj "${SE_DN_STRING}" \
-keyout "${KeyDir}/${SEKeyFile}" -newkey "ec:${DemoCaDir}/SM2.pem" \
-new -out "${ReqDir}/${SEReqFile}"
#Sign SE certificate with CAKeyFile
${GmsslBin} x509 -sm3 -req -days ${CertDays} -in "${ReqDir}/${SEReqFile}" \
-CA "${CertDir}/${CACertFile}" -CAkey "${KeyDir}/${CAKeyFile}" \
-extfile "${GmsslRootPath}/apps/openssl.cnf" -extensions v3_req\
-CAcreateserial -out "${CertDir}/${SECertFile}"
#Print SE certificate file
${GmsslBin} x509 -in "${CertDir}/${SECertFile}" -noout -text
echo "#######################################################################################################"
echo "Generate Client sign certificate file..."
${GmsslBin} req -config "${GmsslRootPath}/apps/openssl.cnf" -nodes -subj "${CS_DN_STRING}" \
-keyout "${KeyDir}/${CSKeyFile}" -newkey "ec:${DemoCaDir}/SM2.pem" \
-new -out "${ReqDir}/${CSReqFile}"
#Sign CS certificate with CAKeyFile
${GmsslBin} x509 -sm3 -req -days ${CertDays} -in "${ReqDir}/${CSReqFile}" \
-CA "${CertDir}/${CACertFile}" -CAkey "${KeyDir}/${CAKeyFile}" \
-extfile "${GmsslRootPath}/apps/openssl.cnf" -extensions v3_req \
-CAcreateserial -out "${CertDir}/${CSCertFile}"
#Print CS certificate file
${GmsslBin} x509 -in "${CertDir}/${CSCertFile}" -noout -text
echo "#######################################################################################################"
echo "Generate Client encrypt certificate file..."
${GmsslBin} req -config "${GmsslRootPath}/apps/openssl.cnf" -nodes -subj "${CE_DN_STRING}" \
-keyout "${KeyDir}/${CEKeyFile}" -newkey "ec:${DemoCaDir}/SM2.pem" \
-new -out "${ReqDir}/${CEReqFile}"
#Sign CE certificate with CAKeyFile
${GmsslBin} x509 -sm3 -req -days ${CertDays} -in "${ReqDir}/${CEReqFile}" \
-CA "${CertDir}/${CACertFile}" -CAkey "${KeyDir}/${CAKeyFile}" \
-extfile "${GmsslRootPath}/apps/openssl.cnf" -extensions v3_req\
-CAcreateserial -out "${CertDir}/${CECertFile}"
#Print CE certificate file
${GmsslBin} x509 -in "${CertDir}/${CECertFile}" -noout -text
每次demoCA目錄結構都會刪除重新創建,下面是/usr/local/gmssl/apps下的目錄結構:
$ tree -L 4
.
|-- demoCA
| |-- certs
| | |-- CA.cert.pem
| | |-- CA.srl
| | |-- CE.cert.pem
| | |-- CS.cert.pem
| | |-- keys
| | | |-- CA.key.pem
| | | |-- CE.key.pem
| | | |-- CS.key.pem
| | | |-- SE.key.pem
| | | `-- SS.key.pem
| | |-- SE.cert.pem
| | `-- SS.cert.pem
| |-- crl
| |-- reqs
| | |-- CA.req
| | |-- CE.req
| | |-- CS.req
| | |-- SE.req
| | `-- SS.req
| `-- SM2.pem
`-- openssl.cnf
7.生成證書注銷列表
腳本代碼:
#certificate crl file
CurPath=`dirname $(readlink -f $0)`
GmsslRootPath=/usr/local/gmssl
GmsslBin=gmssl
DemoCaDir=${GmsslRootPath}/apps/demoCA
CertDir=${DemoCaDir}/certs
KeyDir=${CertDir}/keys
CrlDir=${DemoCaDir}/crl
ReqDir=${DemoCaDir}/reqs/
if [ -z "$1" ]; then
echo "Usage: "`basename "$0"`" cert0 [cert1 cert2 ...]"
fi
touch "${DemoCaDir}/index.txt"
touch "${DemoCaDir}/index.txt.attr"
if [ ! -e "${DemoCaDir}/crlnumber" ]; then
echo 01 > "${DemoCaDir}/crlnumber"
fi
cd "${DemoCaDir}/.."
until [ $# -eq 0 ]
do
${GmsslBin} ca -revoke "${CertDir}/$1" -keyfile "${KeyDir}/CA.key.pem" -cert "${CertDir}/CA.cert.pem"
shift
done
${GmsslBin} ca -gencrl -keyfile "${KeyDir}/CA.key.pem" -cert "${CertDir}/CA.cert.pem" -out "${CrlDir}/gm_cert.crl"
生成之后/usr/local/gmssl/apps的目錄:
$ tree
.
|-- demoCA
| |-- certs
| | |-- CA.cert.pem
| | |-- CA.srl
| | |-- CE.cert.pem
| | |-- CS.cert.pem
| | |-- keys
| | | |-- CA.key.pem
| | | |-- CE.key.pem
| | | |-- CS.key.pem
| | | |-- SE.key.pem
| | | `-- SS.key.pem
| | |-- SE.cert.pem
| | `-- SS.cert.pem
| |-- crl
| | `-- gm_cert.crl
| |-- crlnumber
| |-- crlnumber.old
| |-- index.txt
| |-- index.txt.attr
| |-- reqs
| | |-- CA.req
| | |-- CE.req
| | |-- CS.req
| | |-- SE.req
| | `-- SS.req
| `-- SM2.pem
`-- openssl.cnf