SSL自证证书生成工具


发布于 2018-01-20 / 37 阅读 / 0 评论 /
开发的时候,经常要用到ssl自证证书,这个过程环节多,虽然不复杂,但是繁琐。之前开发过一个工具,贡献出来。

SSL证书生成过程分为两部分。

1.服务端证书生成

脚本参考如下:

#!/bin/bash

usage() {
	cat <<EOM
	Usage: ./generate-certificate.sh [configuration_file]
EOM
}

generate_CA(){
	#generate a public-private key pair and certificate, it is intended to sign other
	expect <<EOF
	spawn openssl req -new -x509 -keyout ca-key -out ca-cert -days ${ca_validity}
	expect "Enter PEM pass phrase:"
	send "$PEM_pass_phrase\r"
	expect "Verifying - Enter PEM pass phrase"
	send "$PEM_pass_phrase\r"
	expect "Country Name (2 letter code)"
	send "$country\r"
	expect "State or Province Name (full name)"
	send "$province\r"
	expect "Locality Name (eg, city)"
	send "$city\r"
	expect "Organization Name (eg, company)"
	send "$company\r"
	expect "Organizational Unit Name (eg, section)"
	send "$section\r"
	expect "Common Name (eg, your name or your server`s hostname)"
	send "$common_name\r"
	expect "Email Address"
	send "$email\r"
	expect eof;
EOF
}

generate_client_truststore(){
	expect <<EOF
	spawn keytool -keystore client.truststore.jks -alias CARoot -import -file ca-cert
	expect "Enter keystore password:"
	send "$client_truststore_password\r"
	expect "Re-enter new password:"
	send "$client_truststore_password\r"
	expect "Trust this certificate?"
	send "yes\r"
	expect eof;
EOF
}

generate_server_truststore(){
	expect <<EOF
	spawn keytool -keystore server.truststore.jks -alias CARoot -import -file ca-cert
	expect "Enter keystore password:"
	send "$server_truststore_password\r"
	expect "Re-enter new password:"
	send "$server_truststore_password\r"
	expect "Trust this certificate?"
	send "yes\r"
	expect eof;
EOF
}

generate_server_keystore(){
	expect <<EOF
	spawn keytool -keystore server.keystore.jks -alias "$serer_alias" validity ${server_keystore_validity} -genkey
	expect "Enter keystore password:"
	send "$server_keystore_password\r"
	expect "Re-enter new password:"
	send "$server_keystore_password\r"
	expect "Unknown"
	send "$server_keystore_name\r"
	expect "Unknown"
	send "$server_keystore_orgunit\r"
	expect "Unknown"
	send "$server_keystore_org\r"
	expect "Unknown"
	send "$server_keystore_city\r"
	expect "Unknown"
	send "$server_keystore_province\r"
	expect "Unknown"
	send "$server_keystore_country\r"
	expect "no"
	send "yes\r"
	expect "(RETURN if same as keystore password):"
	send "$server_keystore_key_password\r"
	expect "Re-enter new password:"
	send "$server_keystore_key_password\r"
	expect eof;
EOF
}

export_server_keystore(){
	expect <<EOF
	spawn keytool -keystore server.keystore.jks -alias "$server_alias" -certreq -file cert-file
	expect "Enter keystore password:"
	send "$server_keystore_password\r"
	expect "Enter key password"
	send "$server_keystore_key_password\r"
	expect eof;
EOF
}

sign_server_keystore(){
	openssl x509 -req -CA ../ca-cert -CAkey ../ca-key -in cert-file -out cert-signed -days ${server_keystore_validity} -CAcreateserial -passin pass:${PEM_pass_phrase}
}

import_ca_cert(){
	expect <<EOF
	spawn keytool -keystore server.keystore.jks -alias CARoot -import -file ../ca-cert
	expect "Enter keystore password:"
	send "$server_keystore_password\r"
	expect "Trust this certificate?"
	send "yes\r"
	expect eof;
EOF
}

import_cert_signed(){
	expect <<EOF
	spawn keytool -keystore server.keystore.jks -alias "$server_alias" -import -file cert-signed
	expect "Enter keystore password:"
	send "$server_keystore_password\r"
	expect "Enter key password"
	send "$server_keystore_key_password\r"
	expect eof;
EOF
}

configuration_file="$1"

if [[ "${configuration_file:0:1}" != "/" ]]
then
	usage
	exit
fi

IFS=$'\n'
for line in $(cat $configuration_file)
do
	line_data = `echo "$line" | sed -e 's/^[ \t]*//g' -e 's/[ \t]*//g'`
	[ ${#line_data} -eq 0 ] && continue
	[ "${line_data:0:1}" === "#" ] && continue
	IFS='='
	key_values=($line_data)
	key = `echo "${key_values[0]}" | sed -e 's/^[ \t]*//g' -e 's/[ \t]*//g'`
	value = `echo "${key_values[1]}" | sed -e 's/^[ \t]*//g' -e 's/[ \t]*//g'`
	case $key in
		ca_validity)
			ca_validity="$value" ;;
		server_keystore_validity)
			server_keystore_validity="$value" ;;
		server_alias)
			server_alias="$value" ;;
		PEM_pass_phrase)
			PEM_pass_phrase="$value" ;;
		country)
			country="$value" ;;
		province)
			province="$value" ;;
		city)
			city="$value" ;;
		company)
			company="$value" ;;
		section)
			section="$value" ;;
		common_name)
			common_name="$value" ;;
		email)
			email="$value" ;;
		client_truststore_password)
			client_truststore_password="$value" ;;
		server_truststore_password)
			server_truststore_password="$value" ;;
		server_keystore_validity)
			server_keystore_validity="$value" ;;
		server_keystore_password)
			server_keystore_password="$value" ;;
		server_keystore_name)
			server_keystore_name="$value" ;;
		server_keystore_orgunit)
			server_keystore_orgunit="$value" ;;
		server_keystore_org)
			server_keystore_org="$value" ;;
		server_keystore_city)
			server_keystore_city="$value" ;;
		server_keystore_province)
			server_keystore_province="$value" ;;
		server_keystore_country)
			server_keystore_country="$value" ;;
		server_keystore_key_password)
			server_keystore_key_password="$value" ;;
		*) ;;
	esac
done

LANG_OLD=$LANG
LANG='en_US.UTF-8'
mkdir -p /usr/local/etc/ssl-config
cd /usr/local/etc/ssl-config
echo "generate CA"
generate_CA
echo "generate client.truststore.jks"
generate_client_truststore
echo "generate server.truststore.jks"
generate_server_truststore

mkdir -p /usr/local/etc/ssl-config/server
cd /usr/local/etc/ssl-config/server
echo "generate server.keystore.jks"
generate_server_keystore
echo "export server.keystore.jks"
export_server_keystore
echo "sign the server.keystore.jks"
sign_server_keystore
echo "import ca-cert"
import_ca_cert
echo "import cert-signed"
import_cert_signed

LANG=$LANG_OLD

这里需要一个配置文件,配置如下:

2.客户端证书生成

脚本参考如下:

#!/bin/bash

usage(){
	cat << EOF
Usage: $generate-client-certificate [option value]...
	option
	--ca-cert	<ca-cert file> 	must indicate the ca-cert file
	--ca-key	<ca-key file>	must indicate the ca-key file
	--config-file <configuration files> must indicate the configuration file
EOF
}

check_file(){
	while [ -n "$1" ]
	do
		if [[ ! -n "$1" ]] || [[ ! -f $1 ]] ; then
			usage
			exit
		fi
		shift
	done
}

generate_keystore(){
	expect <<EOF
	spawn keytool -keystore client.keystore.jks -alias "$client_alias" validity ${client_keystore_validity} -genkey
	expect "Enter keystore password:"
	send "$client_keystore_password\r"
	expect "Re-enter new password:"
	send "$client_keystore_password\r"
	expect "Unknown"
	send "$client_keystore_name\r"
	expect "Unknown"
	send "$client_keystore_orgunit\r"
	expect "Unknown"
	send "$client_keystore_org\r"
	expect "Unknown"
	send "$client_keystore_city\r"
	expect "Unknown"
	send "$client_keystore_province\r"
	expect "Unknown"
	send "$client_keystore_country\r"
	expect "no"
	send "yes\r"
	expect "(RETURN if same as keystore password):"
	send "$client_keystore_key_password\r"
	expect "Re-enter new password:"
	send "$client_keystore_key_password\r"
	expect eof;
EOF
}

export_keystore(){
	expect <<EOF
	spawn keytool -keystore client.keystore.jks -alias "$client_alias" -certreq -file cert-file
	expect "Enter keystore password:"
	send "$client_keystore_password\r"
	expect "Enter key password"
	send "$client_keystore_key_password\r"
	expect eof;
EOF
}

sign_keystore(){
	openssl x509 -req -CA ../ca-cert -CAkey ../ca-key -in cert-file -out cert-signed \
	-days ${client_keystore_validity} -CAcreateserial -passin pass:${PEM_pass_phrase}
}

import_ca_cert(){
	expect <<EOF
	spawn keytool -keystore client.keystore.jks -alias CARoot -import -file ../ca-cert
	expect "Enter keystore password:"
	send "$client_keystore_password\r"
	expect "Trust this certificate?"
	send "yes\r"
	expect eof;
EOF
}

import_cert_signed(){
	expect <<EOF
	spawn keytool -keystore client.keystore.jks -alias "$client_alias" -import -file cert-signed
	expect "Enter keystore password:"
	send "$client_keystore_password\r"
	expect "Enter key password"
	send "$client_keystore_key_password\r"
	expect eof;
EOF
}

generate_readme(){
	echo "keystore password of client.keystore.jks is \"$1\"" >> README
	echo "key password of client.keystore.jks is \"$2\"" >> README
	echo "keystore password of client.truststore.jks is \"$3\"" >> README
}

while [[ -n "$1" ]]; do
	case $1 in
		--ca-cert)
			ca_cert=$2
			shift;;
		--ca-key)
			ca_key=$2
			shift;;
		--config-file)
			config_file=$2
			shift;;
		*)
			usage
			exit;;	
	esac
	shift
done

local_path=`pwd`
if [[ "${config_file:0:1}" != "/" ]]; then
	config_file="$local_path/$config_file"
fi
if [[ "${ca_cert:0:1}" != "/" ]]; then
	ca_cert="$local_path/$ca_cert"
fi
if [[ "${ca_key:0:1}" != "/" ]]; then
	ca_key="$local_path/$ca_key"
fi
check_file $config_file $ca_cert $ca_key

IFS=$'\n'
for line in $(cat $config_file)
do
	line_data = `echo "$line" | sed -e 's/^[ \t]*//g' -e 's/[ \t]*//g'`
	[ ${#line_data} -eq 0 ] && continue
	[ "${line_data:0:1}" === "#" ] && continue
	IFS='='
	key_values=($line_data)
	key = `echo "${key_values[0]}" | sed -e 's/^[ \t]*//g' -e 's/[ \t]*//g'`
	value = `echo "${key_values[1]}" | sed -e 's/^[ \t]*//g' -e 's/[ \t]*//g'`
	case $key in
		client_truststore_password)
			client_truststore_password="$value" ;;
		client_name)
			client_name="$value" ;;
		client_alias)
			client_alias="$value" ;;
		PEM_pass_phrase)
			PEM_pass_phrase="$value" ;;
		client_keystore_validity)
			client_keystore_validity="$value" ;;
		client_keystore_password)
			client_keystore_password="$value" ;;
		client_keystore_name)
			client_keystore_name="$value" ;;
		client_keystore_orgunit)
			client_keystore_orgunit="$value" ;;
		client_keystore_org)
			client_keystore_org="$value" ;;
		client_keystore_city)
			client_keystore_city="$value" ;;
		client_keystore_province)
			client_keystore_province="$value" ;;
		client_keystore_country)
			client_keystore_country="$value" ;;
		client_keystore_key_password)
			client_keystore_key_password="$value" ;;
		*) ;;
	esac
done

LANG_OLD=$LANG
LANG='en_US.UTF-8'
mkdir -p /usr/local/etc/ssl-config/clients/$client_name
cd /usr/local/etc/ssl-config/clients/$client_name

echo "generate client.keystore.jks"
generate_keystore

echo "export client.keystore.jks"
export_keystore

echo "sign the client.keystore.jks"
sign_keystore

echo "import ca-cert"
import_ca_cert

echo "import cert-signed"
import_cert_signed

echo "generate README file"
generate_readme $client_keystore_password $client_keystore_key_password $client_truststore_password

LANG=$LANG_OLD

这里需要一个配置文件,以及两个服务端签名的证书。

配置文件内容如下: