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
这里需要一个配置文件,以及两个服务端签名的证书。
配置文件内容如下: