Openssl与数字签名


安全相关的开发工作不可避免的会碰到“数字签名”,“数字证书”等概念,无论是数字签名还是数字证书都跟openssl这个超级厉害开源软件有着千丝万缕的联系。笔者在研究安全启动的过程成中被数字证书这套技术折腾得焦头烂额,本文打算从非对称加密算法说起,分析数字签名、数字证书的来龙去脉,同时会介绍一些Openssl关于证书管理等方面的命令。

非对称加密

1976年,美国学者Dime和Henman为解决信息公开传送和密钥管理问题,提出一种新的密钥交换协议,允许在不安全的媒体上的通讯双方交换信息,安全地达成一致的密钥,这就是“公开密钥系统”。与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。常见的非对称加密算法包括:RSA、Elgamal、背包算法、Rabin、D-H、ECC。笔者不擅算法,所以这就简单讲一讲应用最广泛的RSA算法,该算法能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。

RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。RSA算法描述:
(1)选择一对不同的、足够大的素数p, q
(2)计算n=p \cdot q
(3)计算f(n)=(p-1) \cdot (q-1),同时对p, q严加保密,不让任何人知道。
(4)找一个与f(n)互质的数e,且1 < e < f(n)
(5)计算d,使得d \cdot e\equiv 1 \, mod \, f(n)。这个公式也可以表达为d \equiv (e-1) \, mod \, f(n)

这里要解释一下,模运算是整数运算,有一个整数m,以n为模做模运算,即m mod n。怎样做呢?让m去被n整除,只取所得的余数作为结果,就叫做模运算。例如,10 mod 3=1;26 mod 6=2;28 mod 2 =0等等。≡是数论中表示同余的符号。公式中,≡符号的左边必须和符号右边同余,也就是两边模运算结果相同。显而易见,不管f(n)取什么值,符号右边1 mod f(n)的结果都等于1;符号的左边d与e的乘积做模运算后的结果也必须等于1。这就需要计算出d的值,让这个同余等式能够成立。

(6)公钥KU=(e,n),私钥KR=(d,n)。
(7)加密时,先将明文变换成0至n-1的一个整数M。若明文较长,可先分割成适当的组,然后再进行交换。设密文为C,则加密过程为:C \equiv M^2 \,mod \,n
(8)解密过程为:M \equiv C^d \,mod \,n

RSA总结如下:

118958533

数字签名和数字证书[1]

1.鲍勃有两把钥匙,一把是公钥,另一把是私钥。

Screen Shot 2017-07-09 at 13.45.45

 

2.鲍勃把公钥送给他的朋友们—-帕蒂、道格、苏珊—-每人一把。

Screen Shot 2017-07-09 at 13.45.56

 

3.苏珊要给鲍勃写一封保密的信。她写完后用鲍勃的公钥加密,就可以达到保密的效果。鲍勃收信后,用私钥解密,就看到了信件内容。这里要强调的是,只要鲍勃的私钥不泄露,这封信就是安全的,即使落在别人手里,也无法解密。

Screen Shot 2017-07-09 at 13.46.06

 

5.鲍勃给苏珊回信,决定采用”数字签名”。他写完后先用Hash函数,生成信件的摘要(digest)。

Screen Shot 2017-07-09 at 13.48.42

 

6.然后,鲍勃使用私钥,对这个摘要加密,生成”数字签名”(signature)。

Screen Shot 2017-07-09 at 13.49.34

 

7.鲍勃将这个签名,附在信件下面,一起发给苏珊。

Screen Shot 2017-07-09 at 13.50.12

 

8.苏珊收信后,取下数字签名,用鲍勃的公钥解密,得到信件的摘要。由此证明,这封信确实是鲍勃发出的。

Screen Shot 2017-07-09 at 13.50.54

 

9.苏珊再对信件本身使用Hash函数,将得到的结果,与上一步得到的摘要进行对比。如果两者一致,就证明这封信未被修改过。

Screen Shot 2017-07-09 at 13.51.54

 

10.复杂的情况出现了。道格想欺骗苏珊,他偷偷使用了苏珊的电脑,用自己的公钥换走了鲍勃的公钥。此时,苏珊实际拥有的是道格的公钥,但是还以为这是鲍勃的公钥。因此,道格就可以冒充鲍勃,用自己的私钥做成”数字签名”,写信给苏珊,让苏珊用假的鲍勃公钥进行解密。

 

11.后来,苏珊感觉不对劲,发现自己无法确定公钥是否真的属于鲍勃。她想到了一个办法,要求鲍勃去找”证书中心”(certificate authority,简称CA),为公钥做认证。证书中心用自己的私钥,对鲍勃的公钥和一些相关信息一起加密,生成”数字证书”(Digital Certificate)。

Screen Shot 2017-07-09 at 13.55.21

12.鲍勃拿到数字证书以后,就可以放心了。以后再给苏珊写信,只要在签名的同时,再附上数字证书就行了。

Screen Shot 2017-07-09 at 13.56.43

 

13.苏珊收信后,用CA的公钥解开数字证书,就可以拿到鲍勃真实的公钥了,然后就能证明”数字签名”是否真的是鲍勃签的。

bg2011080913

基于Openssl的数字证书管理

  1. 创建安全启动CA证书目录

mkdir /mnt/edony/workspace/securebootCA

  1. CA证书创建的相关工作目录和文件

mkdir /mnt/edony/workspace/securebootCA/{certs,crl,newcerts,private}
touch index.txt
echo 01>serial
# 各文件功能解释
certs——存放已颁发的证书
newcerts——存放CA指令生成的新证书
private——存放私钥
crl——存放已吊销的证书
index.txt——OpenSSL定义的已签发证书的文本数据库文件,这个文件通常在初始化的时候是空的
serial——证书签发时使用的序列号参考文件,该文件的序列号是以16进制格式进行存放的,该文件必须提供并且包含一个有效的序列号

  1. 自定义CA创建的配置文件

cp /etc/pki/tls/openssl.cnf /mnt/edony/workspace/securebootCA
# 修改CA目录
[ CA_default ]

#dir = /etc/pki/CA # Where everything is kept
dir = /root/edony/workspace/securebootCA

[ v3_req ]

[ v3_ca ]

  1. 生成随机数

openssl rand -out private/.rand 1000
# 参数解释
rand——生成随机数
-out——指定输出文件
1000——指定随机数长度

  1. 生成根证书
    5.1 生成根证书私钥(pem文件)
    OpenSSL通常使用PEM(Privacy Enbanced Mail)格式来保存私钥,构建私钥的命令如下:

openssl genrsa -aes256 -out private/securebootca.key 2048
# 参数解释
genrsa——使用RSA算法产生私钥
-aes256——使用256位密钥的AES算法对私钥进行加密
-out——输出文件的路径
2048——指定私钥长度

5.2 生成根证书签发申请文件(csr文件)
使用上一步生成的私钥(pem文件),生成证书请求文件(csr文件):

openssl req -new -key private/euler-securebootca.key -out private/securebootca.csr -config openssl.cnf -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=XXX/OU=XXX/CN=Secure Boot (CA key)/emailAddress=xxx@xxx.xxx"

# 参数解释
req——执行证书签发命令
-new——新证书签发请求
-key——指定私钥路径
-out——输出的csr文件的路径
-subj——证书相关的用户信息(subject的缩写)
-config——指定配置文件

5.3 自签发根证书(cer文件)
csr文件生成以后,可以将其发送给CA认证机构进行签发,当然,这里我们使用OpenSSL对该证书进行自签发:

openssl x509 -req -days 3650 -sha256 -signkey private/securebootca.key -in private/securebootca.csr -out certs/securebootca.cer -extfile v3_ca
# 参数解释
x509——生成x509格式证书
-req——输入csr文件
-days——证书的有效期(天)
-sha256——证书摘要采用sha256算法
-extensions——按照openssl.cnf文件中配置的v3_ca项添加扩展
-signkey——签发证书的私钥
-in——要输入的csr文件
-out——输出的cer证书文件

-extfile——证书包括X509 v3的extension属性值

  1. 用根证书签发secureboot证书
    6.1 生成secureboot私钥

openssl genrsa -aes256 -out private/secureboot.key 2048

6.2 生成证书请求文件

openssl req -new -key private/secureboot.key -out private/secureboot.csr -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=XXX/OU=XXX/CN=Secureboot"  -extfile v3_ca

6.3 签发secureboot证书

openssl x509 -req -days 3650 -sha256 -extensions v3_req -CA certs/euler-securebootca.cer -CAkey private/euler-securebootca.key -CAserial ca.srl -CAcreateserial -in private/secureboot.csr -out certs/secureboot.cer
# 参数解释
-CA——指定CA证书的路径
-CAkey——指定CA证书的私钥路径
-CAserial——指定证书序列号文件的路径
-CAcreateserial——表示创建证书序列号文件(即上方提到的serial文件),创建的序列号文件默认名称为-CA,指定的证书名称后加上.srl后缀
-extensions——这里指定的-extensions的值为v3_req,在OpenSSL的配置中,v3_req配置的basicConstraints的值为CA:FALSE,而前面生成根证书时,使用的-extensions值为v3_ca,v3_ca中指定的basicConstraints的值为CA:TRUE,表示该证书是颁发给CA机构的证书

6.4 导出secureboot证书的x509公钥

openssl x509 -in certs/securebootsigner.cer -outform der -out certs/securebootsigner.der

  1. 将密钥封装成PKCS#12

openssl pkcs12 -export -inkey private/secureboot.key -in certs/secureboot.cer -name secureboot -out secureboot.p12

  1. 将秘钥导入到签名秘钥数据库

pk12util -d /etc/pki/pesign -i secureboot.p12

  1. 用secureboot证书对vmlinuz签名
    9.1 修改kernel.spec

# EFI SecureBoot signing, x86_64-only
%ifarch x86_64
# 删除原来的redhat的pesign签名
#%pesign -s -i $KernelImage -o $KernelImage.signed -a %{SOURCE13} -c %{SOURCE14} -n %{pesign_name}
/usr/bin/pesign -s -i $KernelImage -o $KernelImage.signed -c 'secureboot' -n /etc/pki/pesign
mv $KernelImage.signed $KernelImage
%endif

9.2 编译安装secureboot证书签名的kernel

rpmbuild -ba SPECS/kernel.spec
# kernel版本号不要求与下面的RPM包一致
rpm -Uvh kernel-3.10.0-327.53.58.73.x86_64.rpm –force

  1. 用secureboot证书对grub2签名
    10.1 修改grub2.spec

%ifarch aarch64
mv %{grubefiname}.orig %{grubefiname}
mv %{grubeficdname}.orig %{grubeficdname}
%else
/usr/bin/pesign -s -i %{grubefiname}.orig -o %{grubefiname} -c 'secureboot' -n /etc/pki/pesign
/usr/bin/pesign -s -i %{grubeficdname}.orig -o %{grubeficdname} -c 'secureboot' -n /etc/pki/pesign
%endif

10.2 编译安装secureboot证书签名的grub2

rpmbuild -ba SPECS/grub2.spec
# grub2版本号不要求与下面的RPM包一致
rpm -Uvh grub2-efi-2.02-0.33.h1.x86_64.rpm –force

11 用secureboot证书对shim签名
11.1 shim-unsigned中集成euler-securebootca.cer证书

# 修改shim-unsigned的spec文件(shim.spec)
#Source1: securebootca.cer
Source1: euler-securebootca.cer
rpmbuild -ba SPECS/shim.spec

11.2 用secureboot证书对shim签名生成shim-signed

# 修改shim-signed.spec文件
# 此处的spec文件具体修改未定,此处附上的Redhat的shim-signed.spec
cd shim-signed-%{version}
%ifarch %{ca_signed_arches}
pesign -i %{SOURCE0} -h -P > shim.hash
if ! cmp shim.hash %{_datadir}/shim/shim.hash ; then
echo Invalid signature\! > /dev/stderr
exit 1
fi
cp %{SOURCE0} shim.efi
%endif
%ifarch %{rh_signed_arches}
%pesign -s -i %{_datadir}/shim/shim.efi -a %{SOURCE3} -c %{SOURCE2} -n redhatsecureboot301 -o shim-%{efidir}.efi
%endif
%ifarch %{rh_signed_arches}
%ifnarch %{ca_signed_arches}
cp shim-%{efidir}.efi shim.efi
%endif
%endif

%pesign -s -i %{_datadir}/shim/MokManager.efi -o MokManager.efi -a %{SOURCE3} -c %{SOURCE2} -n redhatsecureboot301
%pesign -s -i %{_datadir}/shim/fallback.efi -o fallback.efi -a %{SOURCE3} -c %{SOURCE2} -n redhatsecureboot301

  1. 将公钥导入到MokList(针对MOK做安全启动的场景)

mokutil –import secureboot.der
mokutil –import signing_key.x509

  1. 查看NSS证书数据库中的证书列表

certutil -L -d /etc/pki/pesign/

  1. 删除NSS证书数据库中的证书

certutil -D -d /etc/pki/pesign/ -n secureboot

  1. BIOS集成CA证书的方式验证安全启动
    15.1 BIOS认证shim
    用集成在BIOS中的证书对应的私钥对shim.efi进行签名(目前使用的是securebootca.cer)

15.2 shim认证grub2
step1: shim中集成securebootca.cer证书
step2: 用该证书对grub2x64.efi进行签名?还是用该证书签发的证书对grub2x64.efi进行签名?(有疑问)

15.3 shim认证vmlinuz
同shim认证grub2

15.4 kernel认证ko
kernel编译时完成

  1. X509v3 extensions

openssl genrsa -aes256 -out private/EulerOSCA.key 2048

openssl req -new -key private/EulerOSCA.key -out private/EulerOSCA.csr -config openssl-ca.cnf -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=HUAWEI TECHNOLOGIES CO.,LTD/OU=EulerOS/CN=EulerOS Secure Boot (EulerOS CA key)/emailAddress=euleros-security@huawei.com"

openssl x509 -req -days 3650 -sha256 -signkey private/EulerOSCA.key -in private/EulerOSCA.csr -out certs/EulerOSCA.cer -extfile v3_ca

openssl x509 -in certs/EulerOSCA.cer -noout -text

openssl genrsa -out private/EulerOS.key 2048

openssl req -new -key private/EulerOS.key -out private/EulerOS.csr -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=HUAWEI TECHNOLOGIES CO.,LTD/OU=EulerOS/CN=EulerOS Secure Boot (EulerOS Signing key 1)/emailAddress=euleros-security@huawei.com"

openssl x509 -req -days 3650 -sha256 -CA certs/EulerOSCA.cer -CAkey private/EulerOSCA.key -CAserial ca.srl -CAcreateserial -in private/EulerOS.csr -out certs/EulerOS.cer -extfile v3_ca

# file v3_ca
basicConstraints = CA:FALSE
keyUsage = Digital Signature
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s