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

Posted quqi99

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用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

参考

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/

以上是关于用OpenSSL做自签名的证书(by quqi99)的主要内容,如果未能解决你的问题,请参考以下文章

怎么在windows上openssl颁发代码签名证书?

调试OpenStack时遇到的主要问题(by quqi99)

try chatgpt ( by quqi99 )

add a wifi AP for armbian box (by quqi99)

add a wifi AP for armbian box (by quqi99)

add a wifi AP for armbian box (by quqi99)