How to add SANs to a self-signed certificate for IIS

从Chrome 58版本开始,如果一张SSL证书里没有Subject Alternative Name信息,浏览器就会报错。对于CA来说,他们在签发证书的时候已经会把common name作为SAN加在证书信息里面,因此在CA处购买SSL证书的人可能感觉不到这个问题。如果是自己内部搭建的CA签的证书,签发出去的证书没有这个SAN,那么客户浏览网页的时候浏览器就会报错。

本文其实没有太大的意义,毕竟CA已经自动把Common Name加到SAN里面,本文纯粹是记录一下个人的兴趣以及尝试的结果。

用Windows IIS生成的CSR是不包含SAN的,我们今天想要做到的就是把SAN加在最终的签发证书上。

首先我们先用IIS来生成一个CSR,这个步骤可以参加我之前的博文。在IIS里面生成CSR之后会自动生成一个Self Signed的证书。

MMC CSR request

在MMC里面我们可以看到该证书是没有Subject Alternative Names的。

Self Signed with no SAN

接下来我们会模拟CA签发证书的流程。

我们先创建本地CA

首先创建CA Root Key

在签证书之前,我们先创建我们自己的根证书(我在这里选择了4096 bit的根证书是因为签发的证书的长度不能超过根证书。)

1
2
3
4
5
openssl genrsa -out myCA.key 4096
Generating RSA private key, 4096 bit long modulus
...........++
............................................................................................................................++
e is 65537 (0x010001)
然后我们来生成一个我们的CA证书
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
openssl req -x509 -new -key myCA.key -sha256 -days 1825 -out myCA.crt
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:AU
State or Province Name (full name) [Some-State]:Victoria
Locality Name (eg, city) []:Melbourne
Organization Name (eg, company) [Internet Widgits Pty Ltd]:CA-Aufomm
Organizational Unit Name (eg, section) []:CA
Common Name (e.g. server FQDN or YOUR name) []:Aufomm
Email Address []:

CA Cert

CA创建好之后,我们要开始签证书了。这里我采用两个approach:

用IIS里生成的私钥重新生成含有SAN的CSR,然后用CA证书(不含配置文件)签。

这个步骤其实是没有必要的,现在的CA签发证书最重要的是CSR上Public Key的部分,即使是在生成CSR的时候没有加SAN,只要是在申请证书的时候在申请表上面写了SAN,最后签发的证书里面就会包含SAN。
再次声明本教程纯属个人兴趣,实际SSL申请不需要如此繁杂

我们先从MMC把证书保存未PKCS12格式保存在本地,命名为 SelfSignFromIIS.pfx
然后我们把私钥从PFX文件里面提取出来
1
2
3
4
openssl pkcs12 -in SelfSignFromIIS.pfx -nocerts -out key.key
Enter Import Password:
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
为了方便起见,我们删除私钥的密码
1
2
3
openssl rsa -in key.key -out key.key
Enter pass phrase for key.key:
writing RSA key
创建一个配置文件addSan.cnf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[req]
default_bits = 2048
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[ dn ]
C = Country
ST = State
L = Locality
O = Organisation
CN = Common Name

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = aufomm-test.com
#DNS.2 = www.your-new-domain.com
然后就可以用之前生成的私钥和该配置文件来生成CSR啦
1
2
3
4
5
6
7
8
9
10
11
12
13
openssl req -new -sha256 -nodes -key key.key -out testAddSan.csr -config addSan.cnf
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country []:AU
State []:Victoria
Locality []:Melbourne
Organisation []:Aufomm
Common Name []:aufomm-test.com
我们来检查一下这个CSR testAddSan.csr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
openssl req -text -noout -verify -in testAddSan.csr
verify OK
Certificate Request:
Data:
Version: 1 (0x0)
Subject: C = AU, ST = Victoria, L = Melbourne, O = Aufomm, CN = aufomm-test.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Exponent: 65537 (0x10001)
Attributes:
Requested Extensions:
X509v3 Subject Alternative Name:
DNS:aufomm-test.com
Signature Algorithm: sha256WithRSAEncryption
最后我们用之前生成的CA证书来签这个CSR,看看DNS的内容是否可以保留
1
2
3
4
openssl x509 -req -in testAddSan.csr -CA cacert.pem -CAkey cakey.pem -CAcreateserial -out testAddSan.crt -days 365 -sha256
Signature ok
subject=C = AU, ST = Victoria, L = Melbourne, O = Aufomm, CN = aufomm-test.com
Getting CA Private Key

可以看到用该方法签出来的证书并没有SAN。

IIS生成CSR之后我引用配置文件来签这个CSR

使用配置文件用CA证书来签刚才在IIS里生成的CSR了
1
2
3
4
openssl x509 -req -in CSRfromIIS.req -CA myCA.crt -CAkey myCA.key -CAcreateserial -out test-CSR.crt -days 365 -sha256 -extfile sign.cnf
Signature ok
subject=C = AU, ST = Victoria, L = Melbourne, O = Aufomm Test, OU = Test, CN = aufomm-test.com
Getting CA Private Key
这里我们可以看到我引用了一个配置文件sign.cnf来签,内容为
1
2
3
4
5
6
7
8
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = aufomm-test.com
#DNS.2 =
最终得到的证书包含SAN信息如下:

以上的测试再次验证了CSR文件对于CA来说最关键的是它包含的Public Key的部分,SAN的部分只要在申请表上填写好证书签发之后就会在上面。在生成CSR的时候可以大胆的不用包含SAN。