用OpenSSL做自签名的证书(by quqi99)

作者:张华 发表于:2014-04-18
版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明
(http://blog.csdn.net/quqi99 )

注:csdn居然丢文章,这篇2014年的就丢了,这是从互联网上找到的其他网站的转载备份。

加密技术回顾

非对称加密算法如RSA的特点如下:
1, 公钥加密私钥解密, 大家都可以用我的公钥给我发加密的数据了, 因为只有我有私钥才能解密.
2, 私钥加密公钥解密叫数字签名(例如所谓的UEFI secure boot就是在主板硬件里集成一些操作系统的公钥,由主板硬件去校验操作系统是法合法,但关键是微软把持了公钥的申请,主板硬件厂商没有提供界面让用法自定义公钥,尤其在移动领域很多win8的硬件根本不提供关闭secure boot的选项这样就造成只能安装win8一种系统), 大家收到我用私钥加密后的数据, 看用公钥能不能打得开, 能打开说明这数据确实是由我所发的, 因为别人没有我的私钥不可能伪造这些数据.
非对称加密去处很费时间, 我们一般采用对称密钥算法如DES来加密, 但对称密钥的保存是一个问题.
所以我们可以采用非对称加密算法来加密先协商交换对称密钥, 这就叫SSL. 假设客户端A的公私钥对是(P1,V1), 服务端B的公私钥对是(P2,V2), A需要确认和它通信的是B, 那么SSL的过程是:
首先, A和B都持有对方的公钥.
step1, A->B: hello 是step2, B->A: 用V2加密过的P1(即用户证书,A就用P2解密出P1, 这种数字签名方式让A确定了和它通信的是B)
step3, A->B: ok
step4, B->A: 用V1加密的一段信息
step5, A->B: 用P1加密一个自动生成的对称密钥K(用之前的P1解密成功这段信息则认为B是可信的了)
step6, B->A: 用K加密的数据(之后两对密钥功能结束,由K来加解密数据)
总结一下, 这里(P2,V2)就是certificate authority (CA)用来给客户签名用的公私钥。
(P1,V1)是客户自己的公私钥,提交给CA,CA所做的事情就是上述step2用(P2,V2)来给客户的(P1,V1)签名,简单吧?
V2是CA公司要保密的,而P2就是公用CA证书要安装到客户端

用V2加密过(签名过)的P1,称为用户证书,和用户私钥V1连起一个文件后, 一般被安装在服务器端。

X.509证书是一些标准字段的集合, 是包含有关用户或设备及其相应公钥信息的一种非常通用的证书格式, 目前版本是3. 必要字段包括:
1, 版本号
2, 由CA给每一个证书分配的序列号;
3, 证书使用的签名算法
4, 证书的认证机构
5, 证书的有效日期
6, 证书的所有人的唯一标识
7, 认证机构使用私钥的数字签名
8, 公钥信息
不同于PGP证书任何人都可以扮演认证者的角色, X.509证书的认证者只能是CA或由CA指定的人.要获得一份X.509证书,必须请求CA发给你证书。用户提供自己的公钥,证明自己拥有相应的私钥,并提供有关自己的某些特定信息。然后在这些信息上数字签名,并将整个数据包(称为证书请求)发给CA。CA做一些努力来验证用户提供的信息是正确的,然后就生成证书并返回给用户。
OpenSSL对X.509的支持如下:
(1) 证书请求管理
(2) 证书生成
(3) 证书吊销及CRL管理
(4) X509名字管理
(5) 属性管理
(6) 扩展管理
(7) 验证及信任管理

用OpenSSL做自签名的证书(pem格式)步骤:
1, 先生成CA的公私钥
mkdir CA & cd CA
mkdir newcerts private
echo ‘01’ > serial #会生成以为个数字为名字的pem文件, 且每个数字自增1
touch index.txt #生成记录数据库
使用配置文件, 由于openssl命令行参数太多, 为避免写太多, 就使用一个配置文件代替, 如https://github.com/openstack/nova/blob/master/nova/CA/openssl.cnf.tmpl
生成(P2,V2), 这时候P2=cacert.pem, V2=private/cakey.pem
openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem -out cacert.pem -days 365 -config ./openssl.cnf -batch -nodes
查看证书信息, openssl x509 -in cacert.pem -noout -text
2, 生成<P1,V1>,即Certificate signing Reqeust(CSR), P1=req.pem, V1=key.pem
openssl req -new -nodes -out req.pem -config ./openssl.cnf
3, 用CA的私钥V2为P1签名, 即在newcerts目录生成用户证书cert.pem, 并更新数据库文件index.txt及serail文件
openssl ca -out cert.pem -config ./openssl.cnf -infiles req.pem
查看证书信息, openssl x509 -in cert.pem -noout -text
4, 安装证书
用户私钥key.pem(V1)和用V2加密过的用户公钥(cert.pem)安装到服务端(有的服务器碉要把这两个文件连成一个,可以执行: cat key.pem cert.pem > key-cert.pem), 如:
/home/httpd/ssl/cert.pem Site certificate
/home/httpd/ssl/key.pem Site private key
最后将CA的公钥P2=cacert.pem安装到客户端

在OpenStack PKI认证中:
1, Keystone产生了CA公私钥: CA.pem, CA.key
2, Keystone产生了用户公私钥: keystone.pub, keystone.key
3, Keystone产生了用户证书: keystone.pem (即使用CA.key对keystone.pub进行了签名)
假如nova要使用PKI认证的话:
1, CA端,即keystone端,安装有: CA.pem, CA.key, keystone.key, keystone.pem
2, 用户端,即nova端,安装有:keystone.pem
过程:
1, 用户拿用户名和密码去keystone认证,keystone将用户信息通过keystone.key进行签名后作为token返回用户
2, 用户用这一token去访问nova, nova拿到token后,使用keystone.pem解密。(而原来的UUID方式nova还得再拿token去keystone那边验证一下是否有效,所以使用PKI方式能减轻keystone的压力。

再举个例子,如在安装openconnect时生成证书:

sudo apt-get -y install build-essential pkg-config libgnutls28-dev libreadline-dev libseccomp-dev libwrap0-dev libnl-nf-3-dev liblz4-dev gnutls-bin

#Create CA certificate
mkdir -p /tmp/cert && cd /tmp/cert
cat > /tmp/cert/ca.tmpl << EOF
cn = “sts CA”
organization = “sts CA”
serial = 1
expiration_days = 3650
ca
signing_key
cert_signing_key
crl_signing_key
EOF
#Generate CA secret KEY: V2
certtool --generate-privkey --outfile CA.key
#Generate CA certifice: P2 signed by V2
certtool --generate-self-signed --load-privkey CA.key --template ca.tmpl --outfile CA.pem

#Create User certificate (here is for VPN server)
cat > /tmp/cert/vpnserver.tmpl << EOF
cn = “sts vpn server”
organization = “sts”
expiration_days = 3650
signing_key
encryption_key
tls_www_server
EOF
#Generate User secret KEY: V1
certtool --generate-privkey --outfile vpnserver.key
#Generate User certificate:
certtool --generate-certificate --load-privkey vpnserver.key --load-ca-certificate CA.pem --load-ca-privkey CA.key --template vpnserver.tmpl --outfile vpnserver.pem

#CA.pem,vpnserver,pem,vpnserver.key need to be installed in vpnserver
sudo cp CA.pem /etc/ssl/certs/CA.pem
sudo cp vpnserver.pem /etc/ssl/private/vpnserver.pem
sudo cp vpnserver.key /etc/ssl/private/vpnserver.key
OpenStack创建CA的方法:

openssl genrsa -out /etc/keystone/ssl/private/cakey.pem 1024
openssl req -new -x509 -extensions v3_ca -key /etc/keystone/ssl/private/cakey.pem -out /etc/keystone/ssl/certs/ca.pem -days 3650 -config /etc/keystone/ssl/certs/openssl.conf -subj /C=US/ST=Unset/L=Unset/O=Unset/CN=localhost
openssl genrsa -out /etc/keystone/ssl/private/keystonekey.pem 1024
openssl req -key /etc/keystone/ssl/private/keystonekey.pem -new -out /etc/keystone/ssl/certs/req.pem -config /etc/keystone/ssl/certs/openssl.conf -subj /C=US/ST=Unset/L=Unset/O=Unset/CN=localhost
openssl ca -batch -out /etc/keystone/ssl/certs/keystone.pem -config /etc/keystone/ssl/certs/openssl.conf -days 3650d -cert /etc/keystone/ssl/certs/ca.pem -keyfile /etc/keystone/ssl/private/cakey.pem -infiles /etc/keystone/ssl/certs/req.pem

再看一个使用easy-rsa为openvpn生成证书的实例:

sudo apt-get install easy-rsa openssl
sudo cp -r /usr/share/easy-rsa/ /etc/openvpn
cd /etc/openvpn/easy-rsa
sudo chown -R whoami:root /etc/openvpn
mkdir /etc/openvpn/easy-rsa/keys
source ./vars
export KEY_COUNTRY=CN
export KEY_PROVINCE=BJ
export KEY_CITY=BJ
export KEY_ORG=sts
export KEY_OU=sts
export KEY_NAME=sts
export KEY_EMAIL=root@sts
export KEY_NAME=“server”
./clean-all
./build-ca
$ ls keys/
ca.crt ca.key index.txt serial
./build-key-server server
$ ls keys/
01.pem ca.key index.txt.attr serial server.crt server.key
ca.crt index.txt index.txt.old serial.old server.csr
cp /etc/openvpn/easy-rsa/keys/{server.crt,server.key,ca.crt} /etc/openvpn

#It’s ideal for each client connecting to the VPN to have its own unique certificate and key.
#This is preferable to generating one general certificate and key to use among all client devices.
./build-key client1
scp ubuntu@:/etc/openvpn/easy-rsa/keys/client1.crt /etc/openvpn/
scp ubuntu@:/etc/openvpn/easy-rsa/keys/client1.key /etc/openvpn/
scp ubuntu@:/etc/openvpn/easy-rsa/keys/client.ovpn /etc/openvpn/
scp ubuntu@:/etc/openvpn/easy-rsa/keys/ca.crt /etc/openvpn/

常见证书格式及转换

PKCS(Public-Key Cryptography Standards), 是由RSA实验室与其他安全系统开发商共同制定的一个公钥密码标准
X.509是常用的通用的证书格式, 所有的证书都符合PKI(Public Key Infrastructure)制定的的ITU-T X509国际标准
.cer/.crt是用于存储证书, 以二进制形式存储, 不含私钥
.pem跟.cer/.crt的区别是它以ascii来表示
pfx/p12用于存放个人证书/私钥, 他通常包含保护密码, 二进制存储, 转换如:openssl pkcs12 -export -clcerts -in server-cert.cer -inkey server-key.key -out server.p12

JKS和JCEKS是Java密钥库(KeyStore)的两种比较常见类型, 可以使用java提供的证书工具keytool(openssl和keytool都是可以用来管理证书的工具而已)进行转换(如:keytool -import -v -trustcacerts -storepass 123456 -alias server -file cacert.pem -keystore server.jks)

例如: k8s中的dashboard若不在浏览器里导入p12证书在采用RBAC授权时就会什么也看不到:

# generate client-certificate-data
grep 'client-certificate-data' /var/run/kubernetes/admin.kubeconfig | head -n 1 | awk '{print $2}' | base64 -d >> kubecfg.crt
# generate client-key-data
grep 'client-key-data' /var/run/kubernetes/admin.kubeconfig | head -n 1 | awk '{print $2}' | base64 -d >> kubecfg.key
# generate p12
openssl pkcs12 -export -clcerts -inkey kubecfg.key -in kubecfg.crt -out kubecfg.p12 -name "kubernetes-client"

非对称算法可以使用开源的GPG工具,可参考文档: http://wenku.baidu.com/link?url=d5fWoN46-y7581212dDUEt7dkUfFkriW0bKy_gwUjps4zpKH64jytimWDm-yfuKIwAtu0jFoWW_ocVTJhSeRb2_QQLUz8oIBQulU6jSI133
及:

https://help.ubuntu.com/community/GnuPrivacyGuardHowto
sudo apt-get install rng-tools
sudo rngd -r /dev/urandom

sudo apt-get install gnupg-agent
killall -q gpg-agent
eval $(gpg-agent --daemon)

创建密钥对:gpg --gen-key, 如创建了:“Zhang Hua (zhhuabj) veryhua2006@gmail.com
查看公钥:gpg --list-public
查看私钥:gpg --list-secret-key
查看签名:gpg --list-sig
查看公钥指纹:gpg --fingerprint $GPGKEY
提取公钥:gpg --armor --output public.key --export $GPGKEY 或者: gpg --export -a $GPGKEY > public.key

提取私钥:gpg -a --export-secret-keys $KEYID > customer-mirror.key
生成公钥回收证书,当私钥出问题时可将它上传密钥服务器声明公钥作废:
gpg --output revoke.asc --gen-revoke $GPGKEY
声明作废:gpg --keyserver Server Address --send-keys $GPGKEY

迁移KEY

gpg --output mygpgkey_pub.gpg --armor --export  $GPGKEY
gpg --output mygpgkey_sec.gpg --armor --export-secret-key $GPGKEY

gpg --import mygpgkey_pub.gpg
gpg --allow-secret-key-import --import mygpgkey_sec.gpg

上传公钥到密钥服务器,如:gpg --send-keys --keyserver keyserver.ubuntu.com $GPGKEY 或把公钥导成文本之后直接在http://keyserver.ubuntu.com/这里提交公钥。

查询:

https://keyserver.ubuntu.com/pks/lookup?fingerprint=on&op=index&search=0x

目前只能用指纹:

gpg --keyid-format long --list-keys xx.xxx@xx.com
gpg --with-colons --fingerprint E6A84FFFCF31A67F | grep fpr | cut -d ':' -f 10
gpg --recv-keys C7100A4CD0D8F3AE44212746E6A84FFFCF31A67F

交互命令窗口:gpg --cert-digest-algo=SHA256 --edit-key $GPGKEY

给自己加密文件,加密是用公钥,gpg --encrypt -r veryhua2006@gmail.com test.txt, 会生成名为test.txt.gpg的加密文件
给自己解决文件,gpg --decrypt test.txt.gpg > test.txt

给别人加密文件当然要先导入别人的公钥:gpg --import otherpublic.key
核对对方的公钥指纹:gpg --fingerprint other@gmail.com
为别人加密文件: gpg --encrypt --recipient other@gmail.com test.txt
对别人的公钥进行签名,这样别人知道是你发的: gpg --sign-key other@gmail.com
上面导入了别人的公钥一般还得:

# Then export the key to your local trustedkeys to make it trusted:
gpg --no-default-keyring -a --export 3516D1A5BF0077E71414E19715B9B3EE0DCDF806 | gpg --no-default-keyring --keyring ~/.gnupg/trustedkeys.gpg --import -

对文件进行签名: gpg --clearsign file
验证签名是否完整: gpg --verity file.asc

OpenPGP能用于加密邮件,将GPG指纹注册到launchpad中(https://launchpad.net/~zhhuabj),这样launchpad将给你发签名或加密过的邮件,然后再用openPGP enabled的邮件客户端如thunderbird来接收解密邮件和验证签名。
thunderbird通过enigmail插件来支持OpenPGP, Configure OpenPGP support in Thunderbird under Enigmail->Preferences and add under GnuPG executable path. The path for GnuPG is /usr/bin/gpg.
如果不想用邮件客户端,直接用firefox来访问如gmail等webmail的话,安装firegpg插件即可。chrome不需要装插件直接支持pgp解密。

将GPG指纹(gpg --fingerprint)注册到launchpad中(https://launchpad.net/~zhhuabj)后会收到一封邮件,内容类似如下,将其存成一个文件,再解密(gpg --decrypt file.txt)后就生成了一个验证链接如https://launchpad.net/token/Hc7J9x7kF55CHTZJs,点击验证即可。
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1.4.11 (GNU/Linux)

52gY/bZADAl0xhScHvvuYquGS3oApfgtNM3UJWXa
=ZgnD
-----END PGP MESSAGE-----

Signed Ubuntu Code of Conduct in https://launchpad.net/~zhhuabj,
1, 先下载UbuntuCodeofConduct-2.0.txt, https://launchpad.net/codeofconduct/2.0/+download
2, gpg --clearsign UbuntuCodeofConduct-2.0.txt
3, 将生成的UbuntuCodeofConduct-2.0.txt.asc文件再上传至 https://launchpad.net/codeofconduct/2.0/+sign即可。

2014-5-23日添加,配置使用Google Authenticator服务

Google帐户支持密码+临时验证码的两阶段验证方式。
临时验证码也支持直接短信发到手机上,也可以在Android手机上安装Google Authenticator服务来接收临时验证码。
具体先在https://accounts.google.com/b/0/SmsAuthConfig页面配置,并先生成google服务端为安装了Google Authenticator服务的客户端生成的密钥。然后再在Google Authenticator里输入这个密钥就可以实现一次一密了。

2020-05-21更新 - 产生密钥;

#https://www.dazhuanlan.com/2019/12/15/5df63aed10999
#generate ca key pairs
mkdir -p ca/{private,certs,newcerts} && cd ca
openssl genrsa -aes256 -passout pass:password -out private/ca.key.pem 4096
chmod 400 private/ca.key.pem
wget https://jamielinux.com/docs/openssl-certificate-authority/_downloads/root-config.txt -O openssl.cnf
sed -i "s,/root/ca,.,g" openssl.cnf
openssl req -config ./openssl.cnf -key private/ca.key.pem -new -x509 -days 7300 -sha256 -extensions v3_ca -passin pass:password \
     -subj "/C=CN/ST=BJ/O=STS/OU=quqi.com/CN=quqi.com.rootca/emailAddress=quqi@mail.com" -out certs/ca.cert.pem
chmod 444 certs/ca.cert.pem
openssl x509 -noout -text -in certs/ca.cert.pem #verify

#generate intermediate key pairs
mkdir -p intermediate/{certs,crl,csr,newcerts,private}
chmod 744 intermediate/private
touch index.txt && echo 1000 > serial && echo 1000 > crlnumber
openssl genrsa -aes256 -passout pass:password -out intermediate/private/intermediate.key.pem 4096
chmod 400 intermediate/private/intermediate.key.pem
cp ./openssl.cnf ./openssl-im.cnf
#modify the following section of openssl-im.cnf file
[ CA_default ]
dir             = .
private_key     = $dir/private/intermediate.key.pem
certificate     = $dir/certs/intermediate.cert.pem
crl             = $dir/crl/intermediate.crl.pem
policy          = policy_loose
openssl req -config ./openssl-im.cnf -new -sha256 -passin pass:password \
     -subj "/C=CN/ST=BJ/O=STS/OU=quqi.com/CN=quqi.com.imca/emailAddress=quqi@mail.com" \
     -key intermediate/private/intermediate.key.pem -out intermediate/csr/intermediate.csr.pem
openssl ca -config ./openssl.cnf -extensions v3_intermediate_ca -days 3650 -notext -md sha256 -passin pass:password \
     -in intermediate/csr/intermediate.csr.pem -out intermediate/certs/intermediate.cert.pem
chmod 444 intermediate/certs/intermediate.cert.pem
openssl x509 -noout -text -in intermediate/certs/intermediate.cert.pem
openssl verify -CAfile certs/ca.cert.pem intermediate/certs/intermediate.cert.pem

#generate certificate chain
cat intermediate/certs/intermediate.cert.pem certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem
chmod 444 intermediate/certs/ca-chain.cert.pem

#generate clinet.quqi.com key pairs
openssl genrsa -out intermediate/private/client.quqi.com.key.pem 2048
chmod 444 intermediate/private/client.quqi.com.key.pem
openssl req -config ./openssl-im.cnf -key intermediate/private/client.quqi.com.key.pem \
     -subj "/C=CN/ST=BJ/O=STS/OU=quqi.com/CN=client.quqi.com/emailAddress=quqi@mail.com" \
     -new -sha256 -out intermediate/csr/client.quqi.com.csr.pem
openssl ca -config ./openssl.cnf -extensions server_cert -days 3650 -notext -md sha256 -passin pass:password\
     -in intermediate/csr/client.quqi.com.csr.pem -out intermediate/certs/client.quqi.com.cert.pem
chmod 444 intermediate/certs/client.quqi.com.cert.pem
openssl x509 -noout -text -in intermediate/certs/client.quqi.com.cert.pem
openssl verify -CAfile intermediate/certs/ca-chain.cert.pem intermediate/certs/client.quqi.com.cert.pem

20210819更新 - 导入别人的公钥验证别人的软件

例如,本例中,要使用dsc,dsc别人提供的用别人的公钥签过名的,我们一是需要从服务器下载别人的公钥,二是将别人的公钥加入到自己本地的信任数据库的,三是用这个公钥验证别人的软件。

sudo apt install git-buildpackage -y
mkdir -p /tmp/deb
https://launchpad.net/~ubuntu-cloud-archive/+archive/ubuntu/train-staging/
wget https://launchpad.net/~ubuntu-cloud-archive/+archive/ubuntu/train-staging/+sourcefiles/neutron/2:15.3.4-0ubuntu1~cloud1/neutron_15.3.4-0ubuntu1~cloud1.dsc
sudo chown -R $USER ~/.gnupg/
# bakup gpg keys
gpg --output mygpgkey_pub.gpg --armor --export $GPGKEY
gpg --output mygpgkey_sec.gpg --armor --export-secret-key $GPGKEY
# import gpg keys from other machine
sudo apt-get install rng-tools gnupg-agent -y && sudo rngd -r /dev/urandom && killall -q gpg-agent && eval $(gpg-agent --daemon)
gpg --import mygpgkey_pub.gpg
gpg --allow-secret-key-import --import mygpgkey_sec.gpg
gpg --list-public
gpg --list-sig
export GPGKEY=C7100A4CD0D8F3AE44212746E6A84FFFCF31A67F
gpg --send-keys --keyserver keyserver.ubuntu.com $GPGKEY 

# import dsc. the dsc provider signs dsc, and dsc user verifies dsc
gpg --verify ./neutron_15.3.4-0ubuntu1~cloud1.dsc
gpg --search-keys 3516D1A5BF0077E71414E19715B9B3EE0DCDF806
gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3516D1A5BF0077E71414E19715B9B3EE0DCDF806
# you can ignore 'There is no indication that the signature belongs to the owner'
# as it simply means you have not established a web of trust with other GPG users
gpg --verify ./neutron_15.3.4-0ubuntu1~cloud1.dsc
rm -rf ./neutron_15.3.4-0ubuntu1~cloud1.dsc
git config --global user.email "xxx.zhang@xxx.com"
git config --global user.name "Zhang Hua"
# Then export the key to your local trustedkeys to make it trusted:
gpg --no-default-keyring -a --export 3516D1A5BF0077E71414E19715B9B3EE0DCDF806 | gpg --no-default-keyring --keyring ~/.gnupg/trustedkeys.gpg --import -
# but it still says: gpg: Can't check signature: No public key
gbp import-dsc https://launchpad.net/~ubuntu-cloud-archive/+archive/ubuntu/train-staging/+sourcefiles/neutron/2:15.3.4-0ubuntu1~cloud1/neutron_15.3.4-0ubuntu1~cloud1.dsc

20231023更新 - 使用GPG加密git commit:
1, 使用‘gpg --armor --export $GPGKEY’命令导出GPG public key, 然后更新到git页面 https://github.com/settings/keys
2, 使用’git commit --amend --author=“Zhang xxx xxx.zhang@xxx.com” -S<GPG_private_key>’ 加密git commit, 注意,如果看到这个错误“error: gpg failed to sign the data”,那是一是邮箱名要正确,二是-S后接GPG_private_key (这个可以通过命令:gpg --list-secret-keys --keyid-format LONG 查看)
3, 验证: git log --show-signature
4, 运行git push zhhuabj lp2039403 -f 后从PR页(https://github.com/canonical/snap-openstack/pull/42)可以看到commit后有一个"Verified"状态了

20211124更新 - 产生key

openssl genrsa -passout pass:password -out ca.key
openssl req -x509 -passin pass:password -new -nodes -key ca.key -days 3650 -out ca.crt -subj "/C=CN/ST=BJ/O=STS"
openssl genrsa -passout pass:password -out lb.key
openssl req -new -key lb.key -out lb.csr -subj "/C=CN/ST=BJ/O=STS/CN=www.quqi.com"
openssl x509 -req -in lb.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out lb.crt -days 3650

若要加上Subject Alternative Name,则:

openssl genrsa  -out ca.key
openssl req -x509 -new -nodes -key ca.key -days 3650 -out ca.crt -subj "/C=CN/ST=BJ/O=STS"
sudo cp /etc/ssl/openssl.cnf .
[ req ]
req_extensions     = v3_req
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
IP.1    = 192.168.1.8
IP.2    = 192.168.1.9
DNS.1   = your-website.dev
DNS.2   = another-website.dev
openssl req -new -key client.key -out client.csr -subj "/C=CN/ST=BJ/O=STS/CN=www.quqi.com"  -config openssl.cnf
openssl genrsa -out client.key
openssl req --text --noout -in client.csr

20220611 - 制作证书

mkdir -p ss && cd ss
#openssl req -newkey rsa:4096 -x509 -sha256 -days 3650 -nodes -out ca.crt -keyout ca.key -subj "/C=US/ST=Washington/L=Redmond/O=Microsoft/OU=IT/CN=CA"
#for DOMAIN in server
#do
#  openssl genrsa -out $DOMAIN.key
#  openssl req -new -key $DOMAIN.key -out $DOMAIN.csr -subj "/C=US/ST=Washington/L=Redmond/O=Microsoft/OU=IT/CN=$DOMAIN"
#  openssl x509 -req -in $DOMAIN.csr -out $DOMAIN.crt -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650
#done
openssl ecparam -out ca.key -name secp384r1 -genkey
openssl req -new -sha256 -key ca.key -out ca.csr \
  -subj "/C=US/ST=Washington/L=Redmond/O=Microsoft/OU=IT/CN=CA" \
  -addext "keyUsage=critical,keyCertSign,cRLSign,digitalSignature,keyEncipherment" \
  -addext "extendedKeyUsage=serverAuth,clientAuth,codeSigning,emailProtection,timeStamping"
openssl x509 -req -sha256 -days 365 -in ca.csr -signkey ca.key -out ca.crt
openssl ecparam -out example.com.key -name secp384r1 -genkey
openssl req -new -sha256 -key example.com.key -out example.com.csr \
  -subj "/C=US/ST=Washington/L=Redmond/O=Microsoft/OU=IT/CN=example.com" \
  -addext "keyUsage=critical,keyCertSign,cRLSign,digitalSignature,keyEncipherment" \
  -addext "extendedKeyUsage=serverAuth,clientAuth,codeSigning,emailProtection,timeStamping"
openssl x509 -req -in example.com.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out example.com.crt -days 365 -sha256
chmod +r example.com.key
openssl dhparam -out dhparam 2048

apt install nginx -y
cp dhparam /etc/nginx/dhparam
cat << EOF | tee /etc/nginx/sites-available/default
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    location / {
        return 301 https://\$host\$request_uri;
    }
}
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com;
    ssl_certificate /root/ss/example.com.crt;
    ssl_certificate_key /root/ss/example.com.key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m; 
    ssl_session_tickets off;
    ssl_dhparam /root/ss/dhparam;
    ssl_ecdh_curve secp384r1;
    ssl_protocols TLSv1.2;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers on; 
    location /abcdefgh {
	proxy_redirect off;
	proxy_pass http://127.0.0.1:8008;
	proxy_http_version 1.1;
	proxy_set_header Upgrade \$http_upgrade;
	proxy_set_header Connection "upgrade";
	proxy_set_header Host \$http_host;
    }  
}
EOF

客户端想要客户端认证的话(不想得添加no-verify标志),需:

curl --resolve quqi.com:443:10.5.0.126 --cacert ~/ca/ca.crt https://quqi.com:443/streams/v1/index.json
sudo cp ~/ca/ca.crt /usr/local/share/ca-certificates/ca.crt
sudo chmod 644 /usr/local/share/ca-certificates/ca.crt
sudo update-ca-certificates --fresh
curl --resolve quqi.com:443:10.5.0.126 https://quqi.com:443/streams/v1/index.json
#export SSL_CERT_DIR=/etc/ssl/certs

debug测试:

openssl x509 -noout -text -in ./ca.crt
openssl verify -CAfile ./ca.crt example.com.crt
nmap --script ssl-enum-ciphers -p 443 <IP>
OPENSSL_CONF=/etc/ssl/ openssl s_client -CApath /etc/ssl/certs/ -connect <IP>:443 -tls1_2 -servername example.com
curl -k <IP>:443
curl --resolve example.com:443:<IP> --cacert ./ca.crt <IP>:443
curl --proxy socks5://127.0.0.1:7072 https://ifconfig.me
google-chrome --proxy-server="socks5://127.0.0.1:7072"

20221221

https://blog.csdn.net/quqi99/article/details/104278572

20230301 - 配置证书

配置证书避免这个错误:x509: certificate relies on legacy Common Name field, use SANs instead

:#https://goharbor.io/docs/2.6.0/install-config/configure-https/
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -sha512 -days 3650 -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=quqi.com" -key ca.key -out ca.crt
openssl genrsa -out quqi.com.key 4096
openssl req -sha512 -new -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=quqi.com" -key quqi.com.key -out quqi.com.csr
#complies with the Subject Alternative Name (SAN) and x509 v3 extension requirements to avoid 'x509: certificate relies on legacy Common Name field, use SANs instead'
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1=quqi.com
DNS.2=quqi
DNS.3=hostname
EOF
openssl x509 -req -sha512 -days 3650 -extfile v3.ext -CA ca.crt -CAkey ca.key -CAcreateserial -in quqi.com.csr -out quqi.com.crt
#for docker, the Docker daemon interprets .crt files as CA certificates and .cert files as client certificates.
openssl x509 -inform PEM -in quqi.com.crt -out quqi.com.cert

20231222 - keystone VIP domain切换为keystone/0 unit IP

那在openstack中将keystone VIP domain换成 keystone/0 IP时需要做哪些SNI上的调整呢?
keystone在使用了keystone-hacluster之后,会将keystone的unit数从1变成3, 同时keystone-hacluster子charm会用corosync配置vip (juju config keystone vip)。若配置了SSL, CA可以用vault管理也可以用file(ssl_cert)管理:

# CA
juju run --format=json -u vault/leader get-root-ca| jq -r .[].results.output
juju config keystone ssl_cert

#stsstack会将二者(CA)写到/tmp/stsstack-bundles.ssl.fe501ff2-4b61-46e7-865b-fdfe76573c6d
model_uuid=`juju show-model --format=json| jq -r '.[]."model-uuid"'`
openssl x509 -noout -text -in /tmp/stsstack-bundles.ssl.$model_uuid

#CA是需要安装到openstack client端的:
sudo cp ${model_ca_cert_path} /usr/local/share/ca-certificates/cacert.crt
sudo chmod 644 /usr/local/share/ca-certificates/cacert.crt
sudo update-ca-certificates --fresh 1>/dev/null

在每个keystone的unit上的/etc/apache2/ssl/keystone/目录会根据unit’s local IP + VIP + domain配置3个server certs (如juju-573c6d-ceph-8上的三个server certs (cert_10.5.100.0 cert_10.5.3.33 cert_juju-573c6d-ceph-8.cloud.sts )的CN全用的是 juju-573c6d-ceph-8.cloud.sts

root@juju-573c6d-ceph-8:~# ls /etc/apache2/ssl/keystone/
cert_10.5.100.0  cert_10.5.3.33  cert_juju-573c6d-ceph-8.cloud.sts  key_10.5.100.0  key_10.5.3.33  key_juju-573c6d-ceph-8.cloud.sts

ls /etc/apache2/ssl/keystone/ | grep cert_ | xargs -I {} sh -c 'echo "File: {}"; openssl x509 -noout -text -in /etc/apache2/ssl/keystone/{} | grep CN'

nova端也有类似的 server certs:

root@juju-573c6d-ceph-14:/home/ubuntu# ls /etc/apache2/ssl/nova/
cert_10.5.2.144                     cert_juju-573c6d-ceph-14.cloud.sts  key_10.5.2.144                      key_juju-573c6d-ceph-14.cloud.sts 

但是apache只用了/etc/apache2/ssl/keystone/cert_10.5.100.0, 如下:

root@juju-573c6d-ceph-7:/home/ubuntu# grep -r -i 'SSLCertificate' /etc/apache2/sites-enabled/openstack_https_frontend.conf |awk '{print $2}' |head -n3 | xargs -I {} sh -c 'echo "File: {}"; openssl x509 -noout -text -in {} | grep CN'
File: /etc/apache2/ssl/keystone/cert_10.5.100.0
        Issuer: CN = Vault Root Certificate Authority (charm-pki-local)
        Subject: CN = juju-573c6d-ceph-7.cloud.sts
File: /etc/apache2/ssl/keystone/cert_10.5.100.0
        Issuer: CN = Vault Root Certificate Authority (charm-pki-local)
        Subject: CN = juju-573c6d-ceph-7.cloud.sts
File: /etc/apache2/ssl/keystone/key_10.5.100.0
Could not read certificate from /etc/apache2/ssl/keystone/key_10.5.100.0
402729A74B7F0000:error:1608010C:STORE routines:ossl_store_handle_load_result:unsupported:../crypto/store/store_result.c:151:
Unable to load certificate

这样,当使用VIP=10.5.100.0来访问时,在juju-573c6d-ceph-7上就使用SN=juju-573c6d-ceph-7.cloud.sts, 在juju-573c6d-ceph-8就使用juju-573c6d-ceph-8.cloud.sts.
但如果使用keystone/0 unit的IP(10.5.3.250)或domain(juju-573c6d-ceph-7.cloud.sts)来访问时,由于keystone端的 cert_10.5.3.250 cert_juju-573c6d-ceph-7.cloud.sts也使用相同的SNI=juju-573c6d-ceph-7.cloud.sts. 所以感觉这块没问题,但需要将enpoint也从VIP改为juju-573c6d-ceph-7.cloud.sts

openstack --insecure endpoint set --url https://juju-573c6d-ceph-7.cloud.sts:35357/v3 --region RegionOne --service keystone --interface admin cd96c652e5944be68eb27e4217058314
openstack --insecure endpoint set --url https://juju-573c6d-ceph-7.cloud.sts:5000/v3 --region RegionOne --service keystone --interface internal e04e786789ea482f808af62d33fbe7e4
openstack --insecure endpoint set --url https://juju-573c6d-ceph-7.cloud.sts:5000/v3 --region RegionOne --service keystone --interface public f950d28570fa469e95369fd30f5aa007

这样改来改去地显示不可能。而且参考我以前博客(https://blog.csdn.net/quqi99/article/details/108427898)的“configure ssl for keystone”一节,可能还有这些玩意(juju config keystone os-admin-hostname= D O M A I N o s − p u b l i c − h o s t n a m e = DOMAIN os-public-hostname= DOMAINospublichostname=DOMAIN os-internal-hostname=$DOMAIN),这样不现实。
那客户用什么呢?客户的endpoint里用的是VIP还是VIP domain? 如果是domain通过在/etc/hosts里映身 VIP domain -> keystone/0 unit IP能做吗?
另外,客户如何用CLI,那能使用openstack --insecure来做,那如果使用openstack rest api呢?主要是apache端禁用了http, 只支持https(port 5000 and 4990), 这样客户程序也支持通过https来调用openstack rest api. 似乎此路不通。
剩下的内容见: https://blog.csdn.net/quqi99/article/details/106265390

20240703 - 一个签名错误

这个签名错误未解决,只是记录一些过程

#gpg: 使用 RSA 密钥 AB23E9A98422889E08C3838CBFECAECBA0E7D8C3 gpg: 无法检查签名:缺少公钥
gpg --delete-keys AB23E9A98422889E08C3838CBFECAECBA0E7D8C3
gpg --keyserver keyserver.ubuntu.com --recv-keys AB23E9A98422889E08C3838CBFECAECBA0E7D8C3
gpg --list-keys AB23E9A98422889E08C3838CBFECAECBA0E7D8C3
gpg --refresh-keys
#increase trust level
gpg --edit-key AB23E9A98422889E08C3838CBFECAECBA0E7D8C3
gpg> trust
gpg> 5
gpg> quit
export GNUPGHOME=~/.gnupg  && gpgconf --kill all
dget https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/octavia/1:14.0.0-0ubuntu1/octavia_14.0.0-0ubuntu1.dsc
gpg --with-fingerprint --verify octavia_14.0.0-0ubuntu1.dsc

#above doesn't work, dpkg may use itself key ring, which is different with GNUPGHOME
gpg --export AB23E9A98422889E08C3838CBFECAECBA0E7D8C3 > james_page_public_key.asc
sudo gpg --no-default-keyring --keyring /etc/apt/trusted.gpg --import james_page_public_key.asc
sudo gpg --no-default-keyring --keyring /etc/apt/trusted.gpg --list-keys

#dpkg may not access /etc/apt/trusted.gpg as well
sudo apt-get install debsig-verify
gpg --no-default-keyring --keyring ~/.gnupg/trustedkeys.gpg --import james_page_public_key.asc
sudo gpg --no-default-keyring --keyring ~/.gnupg/trustedkeys.gpg --list-keys

参考

http://www.blogjava.net/alwayscy/archive/2006/12/01/84852.html
http://blog.sina.com.cn/s/blog_9e9d2211010199yj.html

http://lingxiankong.github.io/blog/2014/02/06/openstack-ssl/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

quqi99

你的鼓励就是我创造的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值