目錄
認識數位簽章
數位簽章
數位簽章(英語:Digital Signature)是一種用於鑑別數位信息的方法。一套數位簽章通常定義兩種互補的運算,一個用於簽名,另一個用於驗證,電子簽章用以辨識及確認電子文件簽署人身分電子文件的真偽。
數位簽章流程圖
簽章流程
- 將資料(Data)通過雜湊演算法獲得一個雜湊值(Hash)有時又稱作指紋(fingerprint)
- 使用對稱式密鑰中的私鑰(Private Key)對雜湊值(Hash)進行加簽得到簽章(Signature)
- 將簽章(Signature)、憑證(Certificate)作為資料(Data)附件稱為數位簽章資料(Digitally signed data)
驗證流程
- 數位簽章資料分成簽章和資料
- 使用對稱式密鑰中的公鑰(Public Key)對進行解簽取得簽章中的雜湊值(Hash)
- 將資料(Data)通過雜湊演算法獲得一個雜湊值(Hash)
- 比對 1. 所產生的兩個雜湊值(Hash)是否相同,相同則代表內容正確驗證通過
補充重點
- 簽章流程中的憑證(Certificate)有可能以其他方式釋放出來不一定以附件形式夾帶
- 驗證流程中的公鑰來自於憑證(Certificate)
- 圖中並未詳細提到雜湊演算法,以 openssl 實際運作為例
- 雜湊演算法由簽章者於簽章時決定,並且將雜湊演算方式放入簽章(Signature)中
- 簽章內容包含雜湊值(Hash)及雜湊演算方式,兩種資料使用 asn1 格式來儲存
- 使用者在解簽後會取得雜湊演算方式,因此知道要將資料(Data)通過哪種方式計算出雜湊值(Hash)
用指令來玩數位簽章
測試環境
item | version |
---|---|
OS | macOS Sierra |
openssl | OpenSSL 1.0.2o. |
製作私鑰及憑證
- 製作私鑰Bash
$ openssl genrsa -out my.key 2048
Generating RSA private key, 2048 bit long modulus ................................................................+++ ..............+++ e is 65537 (0x10001)
- 建立憑證Bash
$ openssl req -x509 -new -nodes -key my.key -sha256 -days 3650 -out my.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]: TW State or Province Name (full name) [Some-State]: Taipei Locality Name (eg, city) []: Organization Name (eg, company) [Internet Widgits Pty Ltd]: Cookie's Lab Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []: CookieTsai Email Address []:
- 查看私鑰Bash
$ openssl rsa -in my.key -text -noout
Private-Key: (2048 bit) modulus: 00:c8:32:fd:5d:66:9e:8f:34:d4:e5:1c:79:69:3d: 53:47:96:92:47:77:7b:07:48:bd:01:dc:f8:be:49: a5:3c:18:88:f2:6f:bc:83:43:9a:d1:9f:33:54:bb: e1:db:8e:3f:f7:c2:7f:64:51:88:0a:38:4c:cf:73: d9:34:c0:3c:a0:a4:bd:11:bf:81:60:07:3f:41:85: 81:c4:1a:7e:cf:20:90:ea:60:7d:c1:52:c1:a7:8d: 6a:4c:9c:73:de:6b:3d:6d:bc:63:a0:7a:99:29:9c: c9:a2:c0:b5:18:68:d3:f8:30:fc:42:91:be:a0:26: 74:b6:9a:e9:20:b4:8c:7b:c8:04:06:7d:7f:1b:14: 7a:d6:0e:62:7f:9c:9f:12:fc:a3:f6:63:5c:cd:c1: 2a:d7:59:e7:47:8c:37:d0:f7:80:76:7a:cf:ce:3a: 6e:05:04:bd:24:46:e5:06:a9:6c:cd:15:8d:7f:3b: a0:f2:a1:44:7c:a9:40:54:4b:cc:97:fd:8c:cb:18: 6c:bf:50:a0:b8:32:68:9d:29:78:17:29:53:e5:a1: 74:b6:34:20:49:16:a6:f4:a2:a5:80:89:f4:36:b3: 52:25:64:e8:59:b0:f5:a3:91:f2:c2:a1:da:6c:5d: ea:ed:90:75:bd:bd:ae:c6:8a:70:61:5b:a1:6c:14: 27:3f publicExponent: 65537 (0x10001) privateExponent: 13:f1:c8:7e:02:98:2f:4a:23:1f:84:1b:b0:59:54: af:a0:17:88:99:25:9f:8f:26:8d:45:f7:5d:f5:b6: 49:6b:64:51:4a:c2:6c:0d:53:22:29:0b:13:18:f8: a2:47:e4:a5:89:31:e9:cb:99:92:f3:12:eb:e3:ed: b2:ac:a8:1d:94:eb:e5:15:c0:0c:d2:0c:02:3a:0b: b8:7e:af:3d:71:50:1e:99:68:4d:d7:31:c5:c0:77: e3:93:fe:93:1c:f9:ec:b1:c4:f7:1a:df:a1:5e:a6: 53:d9:80:f1:22:98:63:74:75:dd:27:e9:e6:c8:8d: fe:17:26:bc:84:60:2e:80:8c:92:9d:7e:01:e2:e5: 92:df:3d:fe:41:52:ac:db:3c:ad:bb:df:1d:76:86: 53:fb:8b:65:1f:39:cd:dc:59:e1:f6:ac:41:eb:9e: bd:d2:7d:e5:55:94:c6:b7:a3:0e:46:4f:67:b2:f4: be:a7:50:bf:da:20:0d:63:c1:f3:70:da:4b:e3:ae: a9:41:ca:51:66:a5:71:de:c3:89:98:fa:ba:7d:2d: ee:20:f3:14:f8:08:69:d1:f6:ed:28:cd:1e:e1:45: e3:bd:c7:fa:9b:53:71:9b:5d:69:34:e4:1c:7c:75: cc:d4:da:d1:2e:86:7f:79:96:a1:fb:e7:c0:e6:41: f1 prime1: 00:e2:82:a1:ec:5e:df:b8:e2:ef:5b:b8:01:3e:12: 65:ea:2c:00:c2:6d:2b:d4:34:99:b8:7a:f9:f0:58: b6:05:f8:7c:1b:55:9e:6a:c2:6b:5a:2d:a2:61:77: 0b:e3:f2:97:58:09:95:e1:4a:44:01:c0:d4:6a:49: 7a:79:1e:0c:4e:a2:82:1c:3a:25:71:47:7d:4d:d3: b6:dd:33:55:b5:3d:16:f7:35:4d:46:f9:7f:18:a0: 32:35:6d:fc:32:3c:f0:7b:4f:8a:9b:d8:35:58:b0: 1d:30:3b:d7:9c:e7:8e:d4:00:36:ee:d4:4e:46:75: 3c:a7:be:b9:b5:0d:b4:1a:29 prime2: 00:e2:43:6f:04:31:72:60:8f:d9:79:4a:ac:29:d3: c6:8a:63:1f:df:c3:ea:64:74:f5:74:36:9b:f7:84: 8f:c0:45:e7:3f:b8:7c:9e:79:53:a4:c3:9c:b4:f4: 17:f4:c3:12:0a:b8:7c:5d:73:e6:3e:55:ee:2b:57: a3:0b:98:e2:f1:0b:10:28:18:ee:a9:88:1d:f5:16: 0e:22:44:4d:28:30:03:97:ae:fa:53:ec:3a:ed:7f: 5b:e6:df:79:65:9c:30:fc:fc:5e:9a:70:7e:3c:f7: e4:f0:24:e9:2a:0e:55:87:40:5e:c1:73:52:7b:b9: f3:7a:c8:18:8a:fa:be:33:27 exponent1: 00:d2:84:b2:d5:aa:bf:a7:68:53:2a:1d:74:1a:2a: a3:49:e7:27:b5:8c:1d:86:16:75:20:3e:3b:79:a4: 19:58:a7:3f:41:70:6b:d1:b1:6c:70:dd:a4:e3:8c: ef:22:26:5f:7e:d5:39:d5:af:5e:51:7a:d4:71:0c: 65:a5:97:c5:bc:77:d1:11:47:01:71:ad:0d:ca:7d: 90:a1:39:8a:d8:ed:34:21:02:0b:16:81:e0:1c:15: 17:55:0d:29:ad:cf:71:7a:49:cc:fb:57:11:0d:a2: 71:1e:59:1f:e5:96:58:ea:b4:60:59:cc:3c:0b:c3: fe:61:b1:23:8c:20:76:59:31 exponent2: 45:a3:b1:a8:9d:bb:71:62:f4:f1:72:fd:38:46:79: 26:20:ca:2f:a9:f2:1b:87:30:00:db:c9:f7:4d:b2: 9c:e0:27:03:a2:b9:a0:61:01:50:85:f0:56:75:86: 66:0c:20:22:72:93:bc:83:ae:8a:e3:11:d1:ff:40: 2c:92:9a:ce:cb:b3:e6:53:7e:29:69:be:a6:af:6a: 1c:3b:df:6f:8e:0f:9d:00:fb:05:17:81:2f:95:f2: 68:45:c1:ec:77:3d:50:b0:30:41:e2:7b:c8:32:18: 21:9d:8a:b2:2a:05:43:02:99:e7:7a:a2:19:78:ab: 2a:d0:29:55:a5:45:23:23 coefficient: 45:03:43:0d:28:3c:d3:68:3b:64:be:83:9b:67:e5: d3:df:0d:b1:2a:73:2d:43:e3:29:fc:1d:0d:47:b9: 2e:bb:e9:49:e9:4b:bd:ce:48:7d:84:7f:85:24:ca: 43:f3:0e:b8:dd:d1:e4:92:ff:24:7d:7a:eb:af:6c: df:30:99:67:cd:86:50:c3:9c:b4:5a:ee:98:b2:d0: a2:ce:bc:53:8d:b4:5e:2b:f0:7e:9a:66:09:e8:5f: 87:cc:c5:e4:67:5e:a3:ba:89:3a:eb:84:52:48:ad: 03:73:1f:0a:be:56:1e:0d:16:3a:db:86:c8:0c:e8: 1a:e7:70:95:de:01:98:14
- 查看憑證Bash
$ openssl x509 -in my.crt -text -noout
Certificate: Data: Version: 3 (0x2) Serial Number: 98:3c:cd:50:90:ed:b7:74 Signature Algorithm: sha256WithRSAEncryption Issuer: C=TW, ST=Taipei, O=Cookie's Lab, CN=CookieTsai Validity Not Before: Apr 12 07:04:18 2019 GMT Not After : Apr 9 07:04:18 2029 GMT Subject: C=TW, ST=Taipei, O=Cookie's Lab, CN=CookieTsai Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:c8:32:fd:5d:66:9e:8f:34:d4:e5:1c:79:69:3d: 53:47:96:92:47:77:7b:07:48:bd:01:dc:f8:be:49: a5:3c:18:88:f2:6f:bc:83:43:9a:d1:9f:33:54:bb: e1:db:8e:3f:f7:c2:7f:64:51:88:0a:38:4c:cf:73: d9:34:c0:3c:a0:a4:bd:11:bf:81:60:07:3f:41:85: 81:c4:1a:7e:cf:20:90:ea:60:7d:c1:52:c1:a7:8d: 6a:4c:9c:73:de:6b:3d:6d:bc:63:a0:7a:99:29:9c: c9:a2:c0:b5:18:68:d3:f8:30:fc:42:91:be:a0:26: 74:b6:9a:e9:20:b4:8c:7b:c8:04:06:7d:7f:1b:14: 7a:d6:0e:62:7f:9c:9f:12:fc:a3:f6:63:5c:cd:c1: 2a:d7:59:e7:47:8c:37:d0:f7:80:76:7a:cf:ce:3a: 6e:05:04:bd:24:46:e5:06:a9:6c:cd:15:8d:7f:3b: a0:f2:a1:44:7c:a9:40:54:4b:cc:97:fd:8c:cb:18: 6c:bf:50:a0:b8:32:68:9d:29:78:17:29:53:e5:a1: 74:b6:34:20:49:16:a6:f4:a2:a5:80:89:f4:36:b3: 52:25:64:e8:59:b0:f5:a3:91:f2:c2:a1:da:6c:5d: ea:ed:90:75:bd:bd:ae:c6:8a:70:61:5b:a1:6c:14: 27:3f Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: 87:6E:65:DF:0C:06:A4:8C:87:50:05:1A:15:C3:62:77:6E:D6:09:23 X509v3 Authority Key Identifier: keyid:87:6E:65:DF:0C:06:A4:8C:87:50:05:1A:15:C3:62:77:6E:D6:09:23 X509v3 Basic Constraints: CA:TRUE Signature Algorithm: sha256WithRSAEncryption c0:d8:49:32:0a:0d:d3:5d:4a:05:9c:3d:5c:6f:ee:3d:cb:2b: 1e:21:69:34:3a:4b:58:dc:64:bc:36:8f:b4:ac:aa:ee:38:e1: b4:51:eb:aa:b3:24:aa:f4:86:a9:6d:a6:59:0f:87:1a:07:50: d6:b1:40:fe:87:12:8d:eb:96:ac:89:79:da:ba:9d:2c:00:d1: d6:66:50:60:1a:56:06:95:1f:65:b4:28:32:3a:eb:47:5b:98: bd:f1:8f:91:44:a9:f8:94:bf:61:c4:40:c3:67:94:c8:5e:46: 41:ca:ca:a1:b8:4b:be:ad:43:db:4d:01:1d:f5:2a:07:b4:01: 16:18:9b:9a:5d:35:b4:0e:d4:7f:b3:f3:46:47:7c:4e:4c:e4: 35:02:b2:65:ba:21:88:c9:59:28:1d:17:60:71:18:18:24:a8: 88:b8:83:59:3e:98:cf:76:da:a2:be:78:21:0f:a8:85:03:e6: 97:02:68:33:82:43:6c:b7:af:a3:d7:2e:7a:75:55:b4:75:d6: 2b:7a:4d:32:78:73:b4:49:fa:64:fb:8a:5f:a0:70:5e:f6:80: 27:92:2d:dc:f0:22:c8:9f:e7:f8:b5:fe:f7:c4:9d:fd:4f:0c: b8:12:89:0e:7e:a6:0b:0b:83:fb:65:59:1b:be:2a:26:29:35: 9d:55:7f:59
補充重點
- 私鑰及憑證中都包含了公鑰完整的資訊,所以在應用上會看到例子是拿私鑰或憑證去解開加簽的資料
- 上方憑證是一個自簽憑證,在憑證內容中最下方的 Hex 內容就是簽章,是可以被驗證的方法如下:
- 取出憑證中數位簽章內容,並以私鑰中的公鑰進行解簽,最後將 DER 的資料以 ASN1 的結構呈現Bash
$ openssl x509 -in my.crt -text -noout -certopt ca_default -certopt no_validity \ -certopt no_serial -certopt no_subject -certopt no_extensions -certopt no_signame | \ grep -v 'Signature Algorithm' | tr -d '[:space:]:' | xxd -r -p | \ openssl rsautl -verify -inkey my.key -asn1parse
0:d=0 hl=2 l= 49 cons: SEQUENCE 2:d=1 hl=2 l= 13 cons: SEQUENCE 4:d=2 hl=2 l= 9 prim: OBJECT :sha256 15:d=2 hl=2 l= 0 prim: NULL 17:d=1 hl=2 l= 32 prim: OCTET STRING 0000 - b5 cb da 6d 3e 8d 0b 1f-47 a9 f0 50 e7 ce 0c 59 ...m>...G..P...Y 0010 - 5b a3 a9 71 a2 33 f6 e0-09 4b d9 2f 71 3d 3a 9b [..q.3...K./q=:.
- 取出憑證內容中的 tbsCertificate 資料使用簽章中提到的 sha256 進行雜湊演算
Certificate ::= SEQUENCE { tbsCertificate TBSCertificate, // TBS 意思是 To Be Sign signatureAlgorithm AlgorithmIdentifier, signatureValue BIT STRING }
註解:Certificate 中的 tbsCertificate 是憑證中被加簽的內容- 算出憑證中 tbsCertificate 的位置
Bash$ OFFSET=$(openssl asn1parse -in my.crt | awk 'FNR==2{print $0}' | cut -d":" -f1)
- 將 tbsCertificate 從憑證中取出並存放入 tbsCertificate.der 中
Bash$ openssl asn1parse -in my.crt -strparse $OFFSET -out tbsCertificate.der -noout
- 使用 sha256 進行雜湊演算
Bash$ openssl dgst -sha256 tbsCertificate.der
SHA256(tbsCertificate.der)= b5cbda6d3e8d0b1f47a9f050e7ce0c595ba3a971a233f6e0094bd92f713d3a9b
- 對比兩份數據會發現 Hex 相同所以驗證通過第一份
0:d=0 hl=2 l= 49 cons: SEQUENCE 2:d=1 hl=2 l= 13 cons: SEQUENCE 4:d=2 hl=2 l= 9 prim: OBJECT :sha256 15:d=2 hl=2 l= 0 prim: NULL 17:d=1 hl=2 l= 32 prim: OCTET STRING 0000 - b5 cb da 6d 3e 8d 0b 1f-47 a9 f0 50 e7 ce 0c 59 ...m>...G..P...Y 0010 - 5b a3 a9 71 a2 33 f6 e0-09 4b d9 2f 71 3d 3a 9b [..q.3...K./q=:.
第二份SHA256(tbsCertificate.der)= b5cbda6d3e8d0b1f47a9f050e7ce0c595ba3a971a233f6e0094bd92f713d3a9b
註解:Hex Code 的部分又可以稱作『指紋(fingerprint)』
製作數位簽章
在開始製作數位簽章前,說一下關於 openssl 裡面加簽方式分為兩類。差異在於有沒有 Hash + ASN1,其中有經過 Hash 的可用
openssl dgst
來製作,沒有經過 Hash 的則可以用 openssl rsautl
。這並不是 openssl 唯二的兩種加簽指令,有興趣的可以再多研究,沒意外應該就是屬於這兩類其一。第一種:製作有 hash 的加簽
- ASN1(Hash function + (Data Hash)) + RSA 私鑰加簽 => 數位簽章加簽 + Base64Bash
$ echo "Hello World" | openssl dgst -sha256 -sign my.key | openssl enc -base64
jaqTRJS/FdFn6E1IwEFQTjfotBGJh9D+axqwkqdfxRlhZyUWLPpUb0CdusX2YKjv 0AyysN2B/Z6YlNs6319Qy7nud7FDrkdZtIpVdalE7L6BJXc6/7L+1J/LcBGGXNMz sZiGNpksb1mn0Qd0k5lycqoibF2CPhLuhFdvUgRQ7z3zq132qV2G2kQFrXV+EfPK T4d2YdUU1CVKkMSQEJiOCljzaz2VYR6ajIsCiVfvLgOxc4Pcp64ZtdKR/RbUD6+3 HhFTdOX8yaOoFAWRkKT0K4VxFv5DP3EMIrLiANnc8hcOkJAAfLDEJSXoSczTPVN1 iOzFjzN0ND4T80oDMGnc/g==
加簽後直接解簽Bash$ echo "Hello World" | openssl dgst -sha256 -sign my.key | \ openssl rsautl -verify -inkey my.key -asn1parse
0:d=0 hl=2 l= 49 cons: SEQUENCE 2:d=1 hl=2 l= 13 cons: SEQUENCE 4:d=2 hl=2 l= 9 prim: OBJECT :sha256 15:d=2 hl=2 l= 0 prim: NULL 17:d=1 hl=2 l= 32 prim: OCTET STRING 0000 - d2 a8 4f 4b 8b 65 09 37-ec 8f 73 cd 8b e2 c7 4a ..OK.e.7..s....J 0010 - dd 5a 91 1b a6 4d f2 74-58 ed 82 29 da 80 4a 26 .Z...M.tX..)..J&
註解:此加簽方式會以 ASN1 + DER 的資料作為被加簽對象
第二種:製作沒有 hash 的加簽
- Data + RSA 私鑰加簽 => 資料加簽加簽 + Base64Bash
$ echo "Hello World" | openssl rsautl -sign -inkey my.key | openssl enc -base64
wD+bQB0yL5Ks0aj4CviAYVNaHULrdJzg50Remo6h80COiwcUZ0SKRHVQH2TGH+xD lyw9TE0tB1a0ec+yqIEkIu7J3wCXMWflFMQdk6Vr0j/OHKAaiBOpvmMyq1xlZLVb itFMQVqZYNQKmBvotBXm/TN2fRPiRB/X0QUmS5WsfRRQWssfgFUdKLFs2nXWdUza X/pPW3mnL4oTnzdWU0kTCjT36CzfF+5Q7UdySeEUX/TtU8TT1EGez9s3AzfkS+Xe nIuj71AkhJs7RfY2LE0p05gkCgZrxFbkJXNqtrQB1MUCw+frkAv+cTz+hfpy2ggA 3DiKYeAFVRQhLru7YAzS/Q==
加簽後直接解簽Bash$ echo "Hello World" | openssl rsautl -sign -inkey my.key | \ openssl rsautl -verify -inkey my.key
Hello World
註解:此加簽方式須留意加簽資料長度是必須小於鑰匙長度(2048 bit 鑰匙只能加簽小於 256 byte 的資料)
結語
數位簽章的特性使得資料,可以在不安全的環境中傳遞,並且不怕被有心人士擷取,在一些時候這個特性真的非常重要。在我們日常中常接觸到的自然人憑證其實也是使用相同原理在運作,期許這邊文章能幫助更多人認識數加簽的過程以及實際作動。