#!/bin/bash
function error() {
    echo "执行失败，请查看上方执行日志！"
    exit 1
}

OPENSSL_ROOT_CONF="config/openssl-ca-root.cnf"
OPENSSL_INTER_CONF="config/openssl-ca-inter.cnf"
WORK_DIR="./demoCA"

KEY_DIR="$WORK_DIR/private"
CSR_DIR="$WORK_DIR/newcerts"
CRT_DIR="$WORK_DIR/certs"
SERIAL_FILE="$WORK_DIR/serial"
INDEX_FILE="$WORK_DIR/index.txt"
INDEX_ATTR_FILE="$WORK_DIR/index.txt.attr"

CA_CRT_CHAIN_FILE="$WORK_DIR/cacert.pem"

ROOT_CA_KEY_FILE="$KEY_DIR/cakey-root.pem"
ROOT_CA_CSR_FILE="$WORK_DIR/careq-root.pem"
ROOT_CA_CRT_FILE="$WORK_DIR/cacert-root.pem"
ROOT_CA_SUBJ="/C=CN/ST=Sichuan/L=Chengdu/O=Chengdu Xugu Weiye Technology CO., Ltd/OU=Development/CN=Xugu Root CA"

INTER_CA_KEY_FILE="$KEY_DIR/cakey-inter.pem"
INTER_CA_CSR_FILE="$WORK_DIR/careq-inter.pem"
INTER_CA_CRT_FILE="$WORK_DIR/cacert-inter.pem"
INTER_CA_SUBJ="/C=CN/ST=Sichuan/L=Chengdu/O=Chengdu Xugu Weiye Technology CO., Ltd/OU=Development/CN=Xugu Imtermediate CA"

DATABASE_SIGN_KEY_FILE="$KEY_DIR/database-sign.key"
DATABASE_SIGN_CSR_FILE="$CSR_DIR/database-sign.csr"
DATABASE_SIGN_CRT_FILE="$CRT_DIR/database-sign.crt"
DATABASE_SIGN_SUBJ="/C=CN/ST=Sichuan/L=Chengdu/O=Chengdu Xugu Weiye Technology CO., Ltd/OU=Development/CN=Xugu Database Signature"

DATABASE_ENC_KEY_FILE="$KEY_DIR/database-enc.key"
DATABASE_ENC_CSR_FILE="$CSR_DIR/database-enc.csr"
DATABASE_ENC_CRT_FILE="$CRT_DIR/database-enc.crt"
DATABASE_ENC_SUBJ="/C=CN/ST=Sichuan/L=Chengdu/O=Chengdu Xugu Weiye Technology CO., Ltd/OU=Development/CN=Xugu Database Encryption"

DRIVER_SIGN_KEY_FILE="$KEY_DIR/driver-sign.key"
DRIVER_SIGN_CSR_FILE="$CSR_DIR/driver-sign.csr"
DRIVER_SIGN_CRT_FILE="$CRT_DIR/driver-sign.crt"
DRIVER_SIGN_SUBJ="/C=CN/ST=Sichuan/L=Chengdu/O=Chengdu Xugu Weiye Technology CO., Ltd/OU=Development/CN=Xugu Driver Signature"

DRIVER_ENC_KEY_FILE="$KEY_DIR/driver-enc.key"
DRIVER_ENC_CSR_FILE="$CSR_DIR/driver-enc.csr"
DRIVER_ENC_CRT_FILE="$CRT_DIR/driver-enc.crt"
DRIVER_ENC_SUBJ="/C=CN/ST=Sichuan/L=Chengdu/O=Chengdu Xugu Weiye Technology CO., Ltd/OU=Development/CN=Xugu Driver Encryption"

if test ! -e $WORK_DIR; then mkdir $WORK_DIR; fi
if test ! -e $KEY_DIR; then mkdir $KEY_DIR; fi
if test ! -e $CSR_DIR; then mkdir $CSR_DIR; fi
if test ! -e $CRT_DIR; then mkdir $CRT_DIR; fi
if test ! -e $SERIAL_FILE; then
    SERIAL_NUMBER=`openssl rand -hex 20`
    echo ${SERIAL_NUMBER^^} >$SERIAL_FILE
fi
if test ! -e $INDEX_FILE; then touch $INDEX_FILE; fi
if test ! -e $INDEX_ATTR_FILE; then echo "unique_subject = yes" >$INDEX_ATTR_FILE; fi

echo "======== 注意事项 ========"
echo
echo "当前根证书颁发机构使用配置文件：$OPENSSL_ROOT_CONF"
echo "当前中间证书颁发机构使用配置文件：$OPENSSL_INTER_CONF"
echo "当前脚本工作目录：$WORK_DIR"
echo "请确保脚本 WORK_DIR 参数与配置文件中 dir 参数一致"
echo
echo "======== 根证书颁发机构 ========"
echo
openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:sm2 -out "$ROOT_CA_KEY_FILE" || error
echo "已生成根证书颁发机构私钥文件：$ROOT_CA_KEY_FILE"
openssl req -new -sm3 -nodes -key "$ROOT_CA_KEY_FILE" -out "$ROOT_CA_CSR_FILE" -subj "$ROOT_CA_SUBJ" -config "$OPENSSL_ROOT_CONF" || error
echo "已生成根证书颁发机构请求文件：$ROOT_CA_CSR_FILE"
openssl ca -batch -selfsign -md sm3 -days 11688 -in "$ROOT_CA_CSR_FILE" -outdir "$WORK_DIR" -keyfile "$ROOT_CA_KEY_FILE" -extensions v3_ca -config "$OPENSSL_ROOT_CONF" || error
SERIAL_NUMBER=$(<$SERIAL_FILE.old) || error
mv $WORK_DIR/$SERIAL_NUMBER.pem $ROOT_CA_CRT_FILE || error
echo "已生成根证书颁发机构证书文件：$ROOT_CA_CRT_FILE"
echo
echo "======== 中间证书颁发机构 ========"
echo
openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:sm2 -out "$INTER_CA_KEY_FILE" || error
echo "已生成中间证书颁发机构私钥文件：$INTER_CA_KEY_FILE"
openssl req -new -sm3 -nodes -key "$INTER_CA_KEY_FILE" -out "$INTER_CA_CSR_FILE" -subj "$INTER_CA_SUBJ" -config "$OPENSSL_ROOT_CONF" || error
echo "已生成中间证书颁发机构请求文件：$INTER_CA_CSR_FILE"
openssl ca -batch -selfsign -md sm3 -days 11688 -in "$INTER_CA_CSR_FILE" -outdir "$WORK_DIR" -keyfile "$INTER_CA_KEY_FILE" -extensions v3_intermediate_ca -config "$OPENSSL_ROOT_CONF" || error
SERIAL_NUMBER=$(<$SERIAL_FILE.old) || error
mv $WORK_DIR/$SERIAL_NUMBER.pem $INTER_CA_CRT_FILE || error
echo "已生成中间证书颁发机构证书文件：$INTER_CA_CRT_FILE"
echo
echo "======== 数据库 ========"
echo
openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:sm2 -out "$DATABASE_SIGN_KEY_FILE" || error
echo "已生成数据库签名私钥文件：$DATABASE_SIGN_KEY_FILE"
openssl req -new -sm3 -nodes -key "$DATABASE_SIGN_KEY_FILE" -out "$DATABASE_SIGN_CSR_FILE" -subj "$DATABASE_SIGN_SUBJ" -config "$OPENSSL_INTER_CONF" || error
echo "已生成数据库签名请求文件：$DATABASE_SIGN_CSR_FILE"
openssl ca -batch -md sm3 -days 4383 -in "$DATABASE_SIGN_CSR_FILE" -outdir "$CRT_DIR" -keyfile "$INTER_CA_KEY_FILE" -cert "$INTER_CA_CRT_FILE" -extensions server_sign_req -config "$OPENSSL_INTER_CONF" || error
SERIAL_NUMBER=$(<$SERIAL_FILE.old) || error
mv $CRT_DIR/$SERIAL_NUMBER.pem $DATABASE_SIGN_CRT_FILE || error
echo "已生成数据库签名证书文件：$DATABASE_SIGN_CRT_FILE"
echo
openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:sm2 -out "$DATABASE_ENC_KEY_FILE" || error
echo "已生成数据库加密私钥文件：$DATABASE_ENC_KEY_FILE"
openssl req -new -sm3 -nodes -key "$DATABASE_ENC_KEY_FILE" -out "$DATABASE_ENC_CSR_FILE" -subj "$DATABASE_ENC_SUBJ" -config "$OPENSSL_INTER_CONF" || error
echo "已生成数据库加密请求文件：$DATABASE_ENC_CSR_FILE"
openssl ca -batch -md sm3 -days 4383 -in "$DATABASE_ENC_CSR_FILE" -outdir "$CRT_DIR" -keyfile "$INTER_CA_KEY_FILE" -cert "$INTER_CA_CRT_FILE" -extensions server_enc_req -config "$OPENSSL_INTER_CONF" || error
SERIAL_NUMBER=$(<$SERIAL_FILE.old) || error
mv $CRT_DIR/$SERIAL_NUMBER.pem $DATABASE_ENC_CRT_FILE || error
echo "已生成数据库加密证书文件：$DATABASE_ENC_CRT_FILE"
echo
echo "======== 驱动 ========"
echo
openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:sm2 -out "$DRIVER_SIGN_KEY_FILE" || error
echo "已生成驱动签名私钥文件：$DRIVER_SIGN_KEY_FILE"
openssl req -new -sm3 -nodes -key "$DRIVER_SIGN_KEY_FILE" -out "$DRIVER_SIGN_CSR_FILE" -subj "$DRIVER_SIGN_SUBJ" -config "$OPENSSL_INTER_CONF" || error
echo "已生成驱动签名请求文件：$DRIVER_SIGN_CSR_FILE"
openssl ca -batch -md sm3 -days 4383 -in "$DRIVER_SIGN_CSR_FILE" -outdir "$CRT_DIR" -keyfile "$INTER_CA_KEY_FILE" -cert "$INTER_CA_CRT_FILE" -extensions client_sign_req -config "$OPENSSL_INTER_CONF" || error
SERIAL_NUMBER=$(<$SERIAL_FILE.old) || error
mv $CRT_DIR/$SERIAL_NUMBER.pem $DRIVER_SIGN_CRT_FILE || error
echo "已生成驱动签名证书文件：$DRIVER_SIGN_CRT_FILE"
echo
openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:sm2 -out "$DRIVER_ENC_KEY_FILE" || error
echo "已生成驱动加密私钥文件：$DRIVER_ENC_KEY_FILE"
openssl req -new -sm3 -nodes -key "$DRIVER_ENC_KEY_FILE" -out "$DRIVER_ENC_CSR_FILE" -subj "$DRIVER_ENC_SUBJ" -config "$OPENSSL_INTER_CONF" || error
echo "已生成驱动加密请求文件：$DRIVER_ENC_CSR_FILE"
openssl ca -batch -md sm3 -days 4383 -in "$DRIVER_ENC_CSR_FILE" -outdir "$CRT_DIR" -keyfile "$INTER_CA_KEY_FILE" -cert "$INTER_CA_CRT_FILE" -extensions client_enc_req -config "$OPENSSL_INTER_CONF" || error
SERIAL_NUMBER=$(<$SERIAL_FILE.old) || error
mv $CRT_DIR/$SERIAL_NUMBER.pem $DRIVER_ENC_CRT_FILE || error
echo "已生成驱动加密证书文件：$DRIVER_ENC_CRT_FILE"
echo
echo "脚本执行成功，相关文件已生成。"
exit 0