2017年5月29日 星期一

OpenSSL Certificate Chain (included SAN)


憑證主要分三種:根憑證(Root Certificate),中繼憑證(Intermediate Certificate),終端憑證(End-Entity Certificate),"通常"是階級式的驗證,像資料結構的樹一樣,根憑證就是根節點,終端憑證是葉節點,其他都是中繼憑證(如果沒有意外的話)。

不過還有一種網狀的,就是根憑證是跟其他根憑證互相信任那叫做互簽憑證(Cross Certificate),不過這不是要講的。

所以就要來用OpenSSL簽一組憑證串鏈(Certificate Chain)。

chrome 58版本(應該是)中,增加一個憑證驗證:SAN(Subject Alternative Name),SAN是x509憑證可選的欄位,當一組憑證想要簽不同的common name就可以使用SAN,有點類似DNS的canonical name,雖然他是可選的欄位,但是這次chrome更新讓很多不少自簽憑證都不能用。

先講一下會用到的副檔名:

  • *.pem:是用ASCII方式表達憑證以base64編碼的憑證,我就用這格式保存公鑰以及私鑰。
  • *.crt:憑證公鑰(通常是pem格式),保存公鑰。
  • *.key:私鑰(通常是pem格式),保存私鑰。
  • *.der:二進位的憑證,只放公鑰,給user用的。
  • *.srl:憑證序號。
  • *.csr:憑證的簽名請求(不會保存)。

預計最後產生的憑證串鏈

                                     + 192.168.1.100
            +----- grism.packetx.biz + 192.168.1.150
packetx.biz +                        + 192.168.1.120
            +----- ssl.packetx.biz


這邊是用common name表示,common name主要就是用哪個hostname(或IP地址)連到該網站。
根憑證是packetx.biz,兩個中繼憑證,grism.packetx.biz底下有三個憑證,所以使用這三個網站憑證只要驗證grism.packetx.biz或packetx.biz就好了。
說"或"是因為他是一條鏈,往上驗證只要一個成功就是安全的憑證。


首先簽一個根憑證,根憑證上面已經沒有可以再驗證的對象(authority),所以是自己簽給自己。

根憑證(Root Certificate)


私鑰

首先產生一把長度為4096 bit的私鑰(既然是根憑證,可以大一點沒關係,像是8192 bit),私鑰就是root_ca.key
~ openssl genrsa -out root_ca.key 4096
Generating RSA private key, 4096 bit long modulus
.........  
..................................................  
e is 65537 (0x10001)

產生config檔

我個人不喜歡用OpenSSL的組態檔和他的互動模式(interactive mode),能夠當參數給就用參數給;但是很不幸因為SAN關係,必須要用組態檔了。
~ cat <<EOF > v3.ext
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
subjectAltName = @alt_names

[alt_names]
DNS.1 = packetx.biz
EOF

先產生要增加的額外欄位,這邊注意底下的DNS.x = XXX就是增加common name的地方,所以如果有其他要增加就以這格式,DNS.2DNS.3...。
其他欄位比較重要的是basic constraintsCA:truekey usagekey cert sign,表示這個憑證可以再往下簽(總不可能讓它無限簽吧)。
終端憑證這邊會有點不同,兩個差異可以看這邊。

What is the difference between the x.509 V3 extensions Basic Constraints and Key Usage to create a CA certificate?

接著複製預設的組態檔,然後把這個檔案append到後面。
~ cp /System/Library/OpenSSL/openssl.cnf .
~ cat v3.ext >> ./openssl.cnf
~ rm -f v3.ext

OS X預設的openssl.cnf位置在/System/Library/OpenSSL/openssl.cnf,其他系統就自己查吧。

產生自簽憑證(公鑰)

~ openssl req -new -x509 \
    -days 3650 -sha256 \
    -config ./openssl.cnf \
    -key root_ca.key -out root_ca.crt \
    -subj "/C=TW/ST=New Taipei City/L=Zhonghe Dist./O=PacketX Technology Ltd./OU=R&D/CN=packetx.biz"

-days:憑證期限,根憑證時間長一點沒關係,不然到時候整組重簽會非常麻煩。
-config:就是剛剛的組態檔。
-key:剛剛的私鑰。
-out:要產生的憑證(公鑰)。
-subj:憑證主題,C是是國家,ST是州或省,L是地點或城市,O是組織名稱,OU是部門,CN就是common name。

產生給使用者的憑證

使用者憑證給der格式,把憑證(公鑰)轉成der格式。
~ openssl x509 -in root_ca.crt -outform DER -out root_ca.der

使用者只要把這個.der加入受信任的根憑證,這憑證之後簽的所有憑證都會合法。

合併公私鑰

有些server site可以接受公私鑰放在同一個檔案,方法很簡單,直接用cat把兩個檔案合併(必須是pem格式)。
~ cat root_ca.crt root_ca.key > root_ca.pem

這樣就完成產生自簽根憑證了。
~ openssl x509 -in root_ca.pem -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            dd:10:1d:57:89:03:e7:9d
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=TW, ST=New Taipei City, L=Zhonghe Dist., O=PacketX Technology Ltd., OU=R&D, CN=packetx.biz
        Validity
            Not Before: May 29 08:46:10 2017 GMT
            Not After : May 27 08:46:10 2027 GMT
        Subject: C=TW, ST=New Taipei City, L=Zhonghe Dist., O=PacketX Technology Ltd., OU=R&D, CN=packetx.biz
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (4096 bit)
                Modulus (4096 bit):
                    00:db:05:71:21:00:72:86:c9:46:91:ba:7c:02:f5:
                    2a:b5:01:d8:59:9f:7d:21:5b:4e:aa:09:08:97:ef:
...略
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                C3:25:C1:9F:58:75:6E:18:44:13:A0:2A:70:54:4D:76:5B:6A:6E:D3
            X509v3 Authority Key Identifier: 
                keyid:C3:25:C1:9F:58:75:6E:18:44:13:A0:2A:70:54:4D:76:5B:6A:6E:D3

            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:0
            X509v3 Key Usage: critical
                Digital Signature, Certificate Sign, CRL Sign
            X509v3 Subject Alternative Name: 
                DNS:packetx.biz
    Signature Algorithm: sha256WithRSAEncryption
        95:83:7b:00:b3:c6:c1:f0:e2:b9:26:63:5e:e6:5b:49:d2:8b:
        f6:1e:ff:76:a9:88:fc:e8:53:bd:96:ee:b9:6a:a7:07:02:b7:
...略

可以看到X509v3 Subject Alternative Name有一個DNS了,這個就是SAN。

中繼憑證(Intermediate Certificate)


私鑰

產生私鑰步驟都是一樣的。
~ openssl genrsa -out sub_root_ca.key 4096
Generating RSA private key, 4096 bit long modulus
...................................................................................................................................++
........................................++
e is 65537 (0x10001)

簽名請求

接著希望這把公私鑰是長在剛剛那張根憑證底下,所以產生一個簽名請求來跟根憑證簽署。
~ openssl req -new \
    -key sub_root_ca.key -out sub_root_ca.csr \
    -subj "/C=TW/ST=New Taipei City/L=Zhonghe Dist./O=PacketX Technology Ltd./OU=R&D/CN=grism.packetx.biz"

這邊要注意,common name是不能重複的。

產生config檔

一樣先產生組態檔,這次不一樣的是不需要整個openssl.cnf,只需要增加的部分。
~ cat <<EOF > v3.ext
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
subjectAltName = @alt_names

[alt_names]
DNS.1 = grism.packetx.biz
EOF

簽名

~ openssl x509 -req \
    -days 3650 -sha256 \
    -extfile v3.ext -CAcreateserial \
    -CA root_ca.crt -CAkey root_ca.key \
    -in sub_root_ca.csr -out sub_root_ca.crt
~ rm -f v3.ext
~ rm -f sub_root_ca.csr

-extfile:剛剛產生的組態檔。
-CAcreateserial:憑證中的序號,序號不能重複;使用這個參數會先產生sub_root_ca.srl之後會利用這個檔案遞增上去。
-CA:憑證(上面的)公鑰。
-CAkey:憑證(上面的)私鑰。
-in:剛剛的簽名請求。
-out:該中繼憑證的公鑰。

產生給使用者的憑證

~ openssl x509 -in sub_root_ca.crt -outform DER -out sub_root_ca.der

合併公私鑰

~ cat sub_root_ca.crt sub_root_ca.key > sub_root_ca.pem

這樣就完成中繼憑證了。
~ openssl x509 -in sub_root_ca.pem -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            c4:94:9c:a5:f9:75:34:52
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=TW, ST=New Taipei City, L=Zhonghe Dist., O=PacketX Technology Ltd., OU=R&D, CN=packetx.biz
        Validity
            Not Before: May 29 09:32:18 2017 GMT
            Not After : May 27 09:32:18 2027 GMT
        Subject: C=TW, ST=New Taipei City, L=Zhonghe Dist., O=PacketX Technology Ltd., OU=R&D, CN=grism.packetx.biz
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (4096 bit)
                Modulus (4096 bit):
                    00:bd:06:e9:b2:27:31:8e:23:c7:74:3d:55:d7:89:
                    06:94:0b:31:ca:21:5e:25:4e:4b:65:a6:64:3f:c6:
...略
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                B2:E8:3A:64:59:33:3E:01:09:41:A1:F8:AD:06:90:62:CD:EE:0E:00
            X509v3 Authority Key Identifier: 
                keyid:C3:25:C1:9F:58:75:6E:18:44:13:A0:2A:70:54:4D:76:5B:6A:6E:D3

            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:0
            X509v3 Key Usage: critical
                Digital Signature, Certificate Sign, CRL Sign
            X509v3 Subject Alternative Name: 
                DNS:grism.packetx.biz
    Signature Algorithm: sha256WithRSAEncryption
        27:f1:5b:b3:02:70:12:5d:a0:8f:af:7a:d6:e4:ef:ca:9a:b8:
        ef:25:66:51:68:59:35:9b:4c:77:97:c2:2d:e4:34:37:98:94:
...略

Issuer是簽發人,Subject是這個憑證的一些基本資訊,一樣X509v3 Subject Alternative Name有DNS。

終端憑證(End-Entity Certificate)


私鑰

~ openssl genrsa -out server.key 2048
Generating RSA private key, 2048 bit long modulus
...+++
..........+++
e is 65537 (0x10001)

簽名請求

~ openssl req -new \
    -key server.key -out server.csr \
    -subj "/C=TW/ST=New Taipei City/L=Zhonghe Dist./O=PacketX Technology Ltd./OU=R&D/CN=192.168.1.100"

簽名

~ cat <<EOF > v3.ext
basicConstraints = CA:FALSE
nsCertType = client, email
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
subjectAltName = @alt_names

[alt_names]
DNS.1 = 192.168.1.100
EOF

~ openssl x509 -req \
    -days 365 -sha256 \
    -extfile v3.ext -CAcreateserial \
    -CA sub_root_ca.crt -CAkey sub_root_ca.key \
    -in server.csr -out server.crt

~ rm -f v3.ext
~ rm -f server.csr

這邊要注意的是,basic constraintsCA:false,表示不能再往下簽了。
-CA-CAkey是上面一層的中繼憑證公私鑰。
-days最後發的憑證不用太久,通常一年就差不多了。

合併公私鑰

~ cat server.crt server.key > server.pem

這裡不需要產生給使用者的憑證是因為只要匯入他上面的中繼憑證或根憑證就好了。

~ openssl x509 -in server.pem -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            a7:42:3f:9b:28:91:45:13
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=TW, ST=New Taipei City, L=Zhonghe Dist., O=PacketX Technology Ltd., OU=R&D, CN=grism.packetx.biz
        Validity
            Not Before: May 29 10:16:14 2017 GMT
            Not After : May 29 10:16:14 2018 GMT
        Subject: C=TW, ST=New Taipei City, L=Zhonghe Dist., O=PacketX Technology Ltd., OU=R&D, CN=192.168.1.100
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (2048 bit)
                Modulus (2048 bit):
                    00:9d:0d:59:64:a4:1d:09:98:dc:c4:cc:9f:30:ad:
                    77:b2:a5:1f:e6:8b:dd:1b:bb:5d:40:23:97:65:b2:
...略
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Cert Type: 
                SSL Client, S/MIME
            X509v3 Subject Key Identifier: 
                EA:C8:69:FA:95:E4:65:12:97:FE:13:E4:F0:DD:33:0B:9E:90:ED:E4
            X509v3 Authority Key Identifier: 
                keyid:B2:E8:3A:64:59:33:3E:01:09:41:A1:F8:AD:06:90:62:CD:EE:0E:00

            X509v3 Key Usage: critical
                Digital Signature, Non Repudiation, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Client Authentication, E-mail Protection
            X509v3 Subject Alternative Name: 
                DNS:192.168.1.100
    Signature Algorithm: sha256WithRSAEncryption
        25:a4:90:00:e9:b0:06:18:79:b2:ca:ff:4b:e3:66:fb:4e:81:
        cc:df:16:aa:8c:e5:0e:4c:b8:c4:ec:55:f7:86:f4:a0:46:1b:
...略

Issuer變成中繼憑證了。


最後如果要透過指令驗證的話,需要把根憑證和中繼憑證加進來才能夠驗證。
~ cat root_ca.crt sub_root_ca.crt > tmp
~ openssl verify -CAfile tmp server.crt
server.crt: OK
~ rm -f tmp

~ openssl verify -CAfile <(cat root_ca.crt sub_root_ca.crt) server.crt
server.crt: OK


2017年1月20日 星期五

libpcap - Get stats(16)


libpcap可以讀取一些數據供讀取,像是封包掉的資訊。

libpcap - List data-link type(15)


一個device可以支援不同種data-link類型,目前為止只看到Ethernet這類,libpcap可以列出該裝置所有支援的data-link類型,也可以切換類型。

libpcap - Offline filter(14)


Wireshark可以在擷取封包時候做過濾,也可以在抓完後封包顯示特定的封包,前者叫做capture filter,後者叫做display filter;而後者是Wireshark的功能,前者則是libpcap本身的功能,那如果在libpcap中讀取儲存的pcap的想要再使用過濾器的話,libpcap提供了user space的過濾方式,語法一模一樣,只是在user space上做過濾。

2017年1月19日 星期四