作者: kamidox 來源: 區(qū)塊鏈兄弟 原文鏈接:http:///E7PoxzX 寫在前面 你哼著小曲,打開招商銀行的網(wǎng)站,想查查看今年的獎金到賬了沒有。突然,一個想法驚出你一身冷汗:萬一打開的是李鬼的招商銀行網(wǎng)站,一輸入密碼登錄,不是密碼全被不法分子竊取了么?瀏覽器怎么判斷這是一個可信的網(wǎng)站,而不是某李鬼網(wǎng)站呢?要回答這個問題,得從數(shù)字證書及數(shù)字簽名的原理談起。實際上,本文要介紹的這些知識,也是當(dāng)前火熱的區(qū)域鏈技術(shù)的基礎(chǔ)。 摘要算法 要談清楚這些問題,需要先了解一下摘要算法。摘要算法根據(jù)輸入計算出摘要。 摘要算法它的特點是:
數(shù)據(jù)指紋 摘要算法的這個特點經(jīng)常被用來計算數(shù)據(jù)的指紋,然后進行指紋驗證。常用的摘要算法有 SHA1, SHA256, MD5 等等。SHA256 摘要算法的輸出是 32 個字節(jié),MD5 的摘要算法是 16 字節(jié)。比如,網(wǎng)站登錄時,用戶會網(wǎng)頁上輸入密碼,服務(wù)器端要對輸入的密碼進行驗證。 此時網(wǎng)頁前端不必把密碼直接發(fā)送給服務(wù)器去驗證,而是使用摘要算法計算密碼的指紋,并把這個摘要信息發(fā)送給服務(wù)器進行驗證(這樣可以減少密碼被人截獲的風(fēng)險),這樣服務(wù)器只要拿相同的摘要算法也算一下密碼的摘要,對比兩個摘要是否相同即可知道用戶輸入的密碼是否正確。 備注:服務(wù)器的規(guī)范做法,不會保存密碼的原文在數(shù)據(jù)庫里的,一般通用的做法是生成一個隨機的鹽值,稱為 salt,然后計算并保存密碼加鹽的摘要。 另外一個常用的場景是,對文件的完整性進行驗證。比如,你從網(wǎng)站上下載了一個文件,下載提供方還會提供這個文件的 MD5 摘要信息,你把這個文件下載下來后,可以計算一下這個文件的 MD5 摘要,然后和網(wǎng)站提供的 MD5 對比,如果一樣,說明下載下來的文件是完整的;如果不一致,說明下載下來的文件是不完整的。 非對稱加密算法 非對稱加密算法和摘要算法,構(gòu)成了數(shù)字簽名和數(shù)字證書的基礎(chǔ)。非對稱加密算法的最大特點是:加密時使用的密鑰和解密時使用的密鑰是不一樣的。即,非對稱加密算法有兩套密碼,分別稱為私鑰和公鑰,私鑰私密保存,只有自己知道;公鑰可以發(fā)給通信的對端。私鑰加密的數(shù)據(jù),只有對應(yīng)的公鑰能解密,公鑰加密的信息,只有私鑰能解密。用大白話,使用非對稱加密算法來加密通信的數(shù)據(jù)后,我對外發(fā)的信息別人都能解讀(因為公鑰任何人都可以得到,是公開的),但別人給我發(fā)的信息,只有我能解讀(因為只有我自己有私鑰,能解密)。 加密 解密 備注:與非對稱加密算法對應(yīng)的是對稱加密算法。對稱加密算法的密碼只有一個,通信雙方共享這個密碼。常用的對稱加密算法有 AES, DES 等。 數(shù)字簽名 常用的非對稱加密算法有 RSA 和 ECC 等。非對稱算法最經(jīng)典的應(yīng)用,是結(jié)合摘要算法對數(shù)據(jù)進行簽名?,F(xiàn)實生活中,簽名的物理意義,是表示簽下名字的主體認可被簽名數(shù)據(jù)的有效性。比如,紙面簽名是使用筆寫上自己的名字,在簽名認證時,通過確認筆跡來進行確認。那么,在數(shù)字世界中,怎么樣進行數(shù)字簽名呢?數(shù)字簽名的步驟如下:
簽名 對簽名進行檢查的步驟如下:
簽名檢查 假設(shè),有人偷偷篡改了數(shù)據(jù),由于數(shù)字簽名是沒辦法改變的,因為數(shù)字簽名是經(jīng)過私密保存的私鑰加密過的,別人沒有私鑰,故無法對數(shù)字簽名進行修改。在驗證簽名時,上述步驟 2 算出來的摘要(被篡改后的數(shù)據(jù)算出來的摘要)和步驟 1 算出來的摘要(用公鑰直接解密的,原數(shù)據(jù)的摘要)必定不相同,這樣就可以驗證出來數(shù)據(jù)被人篡改了。 證書簽名 有了數(shù)字簽名的算法,我們就可以對實體頒發(fā)數(shù)字證書,然后讓有公信力的機構(gòu)對數(shù)字證書進行簽名,這樣就可以證明實體的真實身份。數(shù)字證書的主體內(nèi)容包含三部分主要內(nèi)容:
老牌的提供數(shù)字簽名服務(wù)的機構(gòu)是 VeriSign,交納一定的費用,VeriSign 可以使用他們的 CA 證書給你的數(shù)字證書進行簽名。這樣主流的瀏覽器就會認可這個證書,并認為使用了這個證書的網(wǎng)站是安全的。問題是 VeriSign 怎么做到的呢? 實際上,VeriSign 以他們的信譽背書,生成了一個根證書,這個根證書是自簽名的。即 VeriSign 在法律層面上要負責(zé)這個根證書的真實性和有效性。萬一哪一天 VeriSign 的根證書的私鑰泄漏了,被不法分子拿去,不法分子完全可以使用這個私鑰,給一些惡意網(wǎng)站的證書進行簽名。當(dāng)用戶打開這些惡意網(wǎng)站時,瀏覽器就不會提示用戶。相反,瀏覽器會認為這是一個可信的網(wǎng)站。 有了根證書,VeriSign 就可以用根證書,按照不同的業(yè)務(wù)和行業(yè)簽發(fā)一堆專用的 CA 證書出來,然后再用 CA 證書去給具體的實體的數(shù)字證書進行簽名。瀏覽器驗證實體的數(shù)字證書的合法性時,先檢查這個證書的簽名是否正確,然后檢查給這個證書簽名的 CA 證書的合法性。這樣沿著證書鏈一步步往上驗證,最終驗證到了根證書。由于瀏覽器內(nèi)置了 VeriSign 的根證書,故瀏覽器知道這個證書是合法的。瀏覽器就是這樣判斷一個網(wǎng)站的證書是否是可信的。 比如下圖是招商銀行的證書: 證書鏈 從圖中可以看到,招商銀行的證書是由 Symantec Class 3 EV SSL CA - G3 這個 CA 證書簽名的,而這個 CA 證書又是由 VeriSign Class 3 Public Primary Certification Authority - G5 這個證書簽名的。這樣也就不難理解,為什么 VeriSign 在給你的網(wǎng)站的數(shù)字證書進行簽名時需要收取費用:實際上這是一個名譽背書的費用。技術(shù)角度來看,運行一條指令就可以對你的數(shù)字證書進行簽名,沒有任何的成本,但 VeriSign 必須在法律層面保證,他們簽名的對象是個可信的實體。 實際上,你完全可以生成一個自簽名的證書,即用你自己生成的證書的私鑰給你自己的證書簽名。這是完全合法的,但瀏覽器往往不認可這種自簽名證書,并且提示用戶說,這個網(wǎng)站的證書是不可信的。 實踐出真知 如果你對技術(shù)細節(jié)不感興趣,這篇文章閱讀到此就可以結(jié)束了。本節(jié)演示如何使用 openssl 工具包,對數(shù)據(jù)進行數(shù)字簽名及驗證,以及對證書進行簽名。 信息摘要 我們先把要計算摘要的數(shù)據(jù)保存到 data.txt 文件里: $ echo 'This is real words from Joey.' > data.txt 然后以這個文件作為輸入計算 SHA256 摘要信息: $ openssl dgst -sha256 -hex data.txt 其輸出為: SHA256(data.txt)= f1b1b3f5f35944c8e2169031efac2a37147dac631b8dbd7cfa5d265e0e804e8d 當(dāng)然,我們也可以換成 MD5 算法并計算其摘要: $ openssl dgst -md5 -hex data.txtMD5(data.txt)= ed764086c5770a9d5ff0e60036aa4226 從輸出不難看出,SHA256 的摘要輸出是 32 個字節(jié)(f1 是第一個字節(jié),b1 是第二個字節(jié),依此類推),MD5 的摘要輸出是 16 字節(jié)。 非對稱加密算法 我們先生成一個 2048 bit 的 RSA 算法私鑰: $ openssl genrsa -out rsa_private.key 2048 rsa_private.key 就是生成的私鑰。這是個文本文件,你可以用任何文本編輯器打開它,內(nèi)容如下: -----BEGIN RSA PRIVATE KEY-----BASE64(PRIVATE KEY)-----END RSA PRIVATE KEY----- 私鑰數(shù)據(jù)是經(jīng)過 BASE64 編碼的數(shù)據(jù),故顯示成 ASCII 字符。私鑰必須私密保存,一旦泄漏,整個安全體系就崩塌了。由于私鑰是如此的重要,openssl 提供了一個方法來加密保存私鑰文件。下面的命令用來生成密碼保護的密鑰: $ openssl genrsa -aes256 -passout pass:yourpwd -out rsa_aes_private.key 2048 這個命令生成的私鑰 rsa_aes_private.key 是使用 AES 256 算法加密保存的,密碼就是字符串 yourpwd 。下次使用這個私鑰時,就必須提供這個密碼才能使用。我們還可以把加密保存的私鑰轉(zhuǎn)為不加密的,其命令為: $ openssl rsa -in rsa_aes_private.key -passin pass:yourpwd -out rsa_private.key 當(dāng)然,明文的私鑰也可以加密保存起來: $ openssl rsa -in rsa_private.key -aes256 -passout pass:newpwd -out rsa_aes_private.key 有了私鑰,我們就可以生成與之配套使用的公鑰: $ openssl rsa -in rsa_private.key -pubout -out rsa_public.key rsa_public.key 就是對應(yīng)的公鑰。公鑰文件也是一個純文本文件,其內(nèi)容示意如下: -----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA69EVk9GKyEQDRfV8OJUf49eaJ67bTP/zAPm5huf9z7EhAaltjyfHNaCQMYVTAKUAS9c7XhKxA8NkHil/HNBE4UONY054voisKWYqxtHaoFkcfY5QE+vj9JVJajwYAKZjA362zo2y8qbpJ6INCMeB19oOuGFBTkn4z0RR71kFriyQ2pOjbHru5pH9bC9t4GjvkNMNWeFdSdR3uO3zIYB6cl176kaYZ8Bwr+PeGl+jzMpd7lDSEVLLaAt1jZiNLQ1dYTN4GGuURy/6b3d4+TZ1VxNlLc0+8l+vyzpXRZWxZcEBjA4voeWmxqBKUsA6jKTDS/V6IFOTakoOGLk5w3f1EQIDAQAB-----END PUBLIC KEY----- 證書及簽名 生成自簽名證書 使用已有 RSA 算法的私鑰生成自簽名證書: $ openssl req -new -x509 -days 365 -key rsa_private.key -out cert.crt -subj '/C=CN/ST=FJ/L=XM/O=sfox/OU=dev/CN=sfox.com/emailAddress=sfox@sfox.com' -days 參數(shù)指明這個證書的有效期;-key 參數(shù)指定使用的 RSA 私鑰文件;-out 參數(shù)指定輸出的自簽名證書文件,一般以 crt 作為后綴名;-subj 參數(shù)用來指定證書的名稱,如果不帶這個參數(shù),則需要逐個輸入證書的名稱參數(shù),包含國家,省份,城市,組織名稱,部門名稱,通用名稱等等。 可以使用下面命令來查看自簽名證書的信息: $ openssl x509 -in cert.crt -noout -text 其輸出示意如下: Certificate: Data: Version: 1 (0x0) Serial Number: 11926462855904995145 (0xa5834ec7411ba749) Signature Algorithm: sha256WithRSAEncryption Issuer: C=CN, ST=FJ, L=XIAMEN, O=SFOX, OU=SW, CN=sfox/emailAddress=sfox@qq.com Validity Not Before: Mar 31 13:35:11 2018 GMT Not After : Mar 31 13:35:11 2019 GMT Subject: C=CN, ST=FJ, L=XIAMEN, O=SFOX, OU=SW, CN=sfox/emailAddress=sfox@qq.com Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:eb:d1:15:93:d1:8a:c8:44:03:45:f5:7c:38:95: 1f:e3:d7:9a:27:ae:db:4c:ff:f3:00:f9:b9:86:e7: fd:cf:b1:21:01:a9:6d:8f:27:c7:35:a0:90:31:85: 53:00:a5:00:4b:d7:3b:5e:12:b1:03:c3:64:1e:29: 7f:1c:d0:44:e1:43:8d:63:4e:78:be:88:ac:29:66: 2a:c6:d1:da:a0:59:1c:7d:8e:50:13:eb:e3:f4:95: 49:6a:3c:18:00:a6:63:03:7e:b6:ce:8d:b2:f2:a6: e9:27:a2:0d:08:c7:81:d7:da:0e:b8:61:41:4e:49: f8:cf:44:51:ef:59:05:ae:2c:90:da:93:a3:6c:7a: ee:e6:91:fd:6c:2f:6d:e0:68:ef:90:d3:0d:59:e1: 5d:49:d4:77:b8:ed:f3:21:80:7a:72:5d:7b:ea:46: 98:67:c0:70:af:e3:de:1a:5f:a3:cc:ca:5d:ee:50: d2:11:52:cb:68:0b:75:8d:98:8d:2d:0d:5d:61:33: 78:18:6b:94:47:2f:fa:6f:77:78:f9:36:75:57:13: 65:2d:cd:3e:f2:5f:af:cb:3a:57:45:95:b1:65:c1: 01:8c:0e:2f:a1:e5:a6:c6:a0:4a:52:c0:3a:8c:a4: c3:4b:f5:7a:20:53:93:6a:4a:0e:18:b9:39:c3:77: f5:11 Exponent: 65537 (0x10001) Signature Algorithm: sha256WithRSAEncryption b3:41:be:6f:54:3c:d7:fc:53:c6:21:f5:ea:fa:2d:c7:70:ed: 29:57:c4:0b:74:43:74:24:1b:05:df:2e:9f:ef:76:32:8a:8e: 4a:85:31:18:a2:50:95:1a:6e:07:cf:e9:82:04:55:ee:1b:26: 0a:e7:bf:47:ef:d5:69:d1:ef:fb:db:50:52:84:2d:85:e9:2c: 15:5c:de:2d:9c:74:fe:90:b9:02:29:1b:dc:fb:b8:ef:08:b2: 04:0c:27:66:c8:f1:31:a6:f3:52:73:4b:16:41:0d:f1:a9:d5: f2:1b:60:3a:44:a0:be:35:ef:a6:e4:10:bf:90:4e:98:3f:56: 3e:3d:ef:99:b2:38:97:2b:5a:f9:46:61:4a:e1:77:9e:76:0a: 3a:d6:2f:f2:16:31:8c:cf:e5:e4:e5:42:14:07:8c:fa:a6:48: 19:76:cd:6d:63:8e:62:a2:65:83:9f:9d:c4:d6:32:97:6a:54: e6:27:49:30:aa:08:72:0c:2f:e0:9a:a1:ae:2a:75:34:ad:31: 0f:26:71:7e:6f:75:d4:cc:d3:58:13:2c:18:da:2d:ef:a1:e6: 7a:9a:d1:d4:1d:48:b4:ac:06:84:8b:07:1b:15:9c:f8:e5:fe: ac:58:c4:50:74:a9:8e:c2:f9:24:01:a2:d1:83:92:41:96:fa: bb:42:73:7a 生成簽名請求文件 當(dāng)需要申請使用 CA 證書對證書進行簽名時,需要生成簽名請求文件。使用己有的 RSA 私鑰生成簽名請求文件的命令為: $ openssl req -new -key rsa_private.key -out cert.csr -subj '/C=CN/ST=FJ/L=XM/O=sfox/OU=dev/CN=sfox.com/emailAddress=sfox@sfox.com 其中 -key 指定證書的私鑰信息,openssl 命令會使用私鑰來算出公鑰,并把公鑰包含在證書文件里;-out 指明要生成的證書簽名請求文件的文件名,一般以 csr 作為后綴;-subj 表示待簽名的證書的名稱信息。生成的證書請求文件可以使用如下命令來查看詳情: $ openssl req -noout -text -in cert.csrCertificate Request: Data: Version: 0 (0x0) Subject: C=CN, ST=FJ, L=XM, O=SFOX, OU=SW, CN=sfox.com/emailAddress=sfox@qq.com Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:eb:d1:15:93:d1:8a:c8:44:03:45:f5:7c:38:95: 1f:e3:d7:9a:27:ae:db:4c:ff:f3:00:f9:b9:86:e7: fd:cf:b1:21:01:a9:6d:8f:27:c7:35:a0:90:31:85: 53:00:a5:00:4b:d7:3b:5e:12:b1:03:c3:64:1e:29: 7f:1c:d0:44:e1:43:8d:63:4e:78:be:88:ac:29:66: 2a:c6:d1:da:a0:59:1c:7d:8e:50:13:eb:e3:f4:95: 49:6a:3c:18:00:a6:63:03:7e:b6:ce:8d:b2:f2:a6: e9:27:a2:0d:08:c7:81:d7:da:0e:b8:61:41:4e:49: f8:cf:44:51:ef:59:05:ae:2c:90:da:93:a3:6c:7a: ee:e6:91:fd:6c:2f:6d:e0:68:ef:90:d3:0d:59:e1: 5d:49:d4:77:b8:ed:f3:21:80:7a:72:5d:7b:ea:46: 98:67:c0:70:af:e3:de:1a:5f:a3:cc:ca:5d:ee:50: d2:11:52:cb:68:0b:75:8d:98:8d:2d:0d:5d:61:33: 78:18:6b:94:47:2f:fa:6f:77:78:f9:36:75:57:13: 65:2d:cd:3e:f2:5f:af:cb:3a:57:45:95:b1:65:c1: 01:8c:0e:2f:a1:e5:a6:c6:a0:4a:52:c0:3a:8c:a4: c3:4b:f5:7a:20:53:93:6a:4a:0e:18:b9:39:c3:77: f5:11 Exponent: 65537 (0x10001) Attributes: a0:00 Signature Algorithm: sha256WithRSAEncryption 13:aa:fc:0f:82:a4:b1:cf:3a:f3:3f:ff:53:b8:50:e8:41:cc: 6b:a3:1c:5b:e2:4d:b0:47:f3:02:a8:ae:34:22:94:fc:8d:6b: 11:41:82:33:9f:b1:df:da:fd:90:18:55:5d:aa:9e:61:82:26: e0:b5:9e:86:0d:18:cb:8d:e4:f5:d3:2c:32:8d:21:9d:f8:c2: 3d:c8:22:e2:9c:10:69:bc:25:de:a4:14:05:c3:2c:c7:7b:d4: ee:30:53:9c:71:2f:0e:f5:04:83:54:d8:74:28:e9:ef:4a:72: b5:88:a5:73:d5:78:8e:27:88:be:52:16:fd:a9:cc:13:38:aa: 1c:94:a4:20:a5:23:4d:bd:7d:29:d2:db:da:ec:86:2c:99:36: fb:c0:b2:0f:ec:da:ef:51:d5:f7:37:d0:11:59:d0:66:c4:e9: d1:ed:a1:2b:d4:b3:46:6b:fe:6f:17:3b:77:0c:be:f8:20:5b: ca:66:2d:64:17:20:5d:19:73:4d:be:5e:e3:fc:25:1a:cb:03: 87:4d:55:7a:56:9d:ed:d7:7d:5a:55:e2:85:1b:2f:d2:fe:74: 43:6f:84:5c:2b:de:c9:0c:05:76:08:65:de:6a:21:d6:26:0f: 23:5a:12:4e:13:0e:8f:fd:ef:7c:e6:b4:6b:07:80:0f:2b:b8: 7f:66:c7:16 細心的讀者可以發(fā)現(xiàn),證書簽名請求文件和自簽名的證書文件相比,少了 Issuer(頒發(fā)者),Serial Number,Validity(有效期)等信息。 使用 CA 證書對 CSR 文件進行簽名 要使用 CA 證書對簽名請求文件進行簽名,你必須有 CA 證書文件以及 CA 證書的私鑰文件。有了這兩個文件,可以使用下面的命令進行簽名: $ openssl x509 -req -days 3650 -in cert.csr -CA ca.crt -CAkey ca.key -passin pass:yourpwd -CAcreateserial -out cert_ca_signed.crt -days 表示證書的有效期,此處指定 3650 表示 10 年有效期;-in 表示輸入文件,此處是指證書請求簽名文件的文件名;-CA 指定 CA 證書的文件名;-CAkey 指定 CA 證書的私鑰文件;-passin 指定 CA 證書的私鑰文件的加密密碼,如果以明文保存的私鑰文件,則此參數(shù)可省略。-CAcreateserial 參數(shù)指定給簽名后的證書創(chuàng)建序列號;-out 參數(shù)指明輸出的簽名后的數(shù)字證書文件的文件名。 當(dāng)然,這里你完全可以使用自簽名的證書文件及其對應(yīng)的私鑰文件給其他的證書請求文件進行簽名。 數(shù)字簽名及驗證 本小節(jié)將演示對一段文本內(nèi)容進行簽名,然后驗證簽名的正確性。 我們先生成待簽名的數(shù)字內(nèi)容: $ echo 'This is real words from Joey.' > data.txt 接著,對數(shù)字內(nèi)容進行簽名,簽名的時候使用的是私鑰: $ openssl dgst -sha256 -sign rsa_private.key -out data.sign data.txt 這個命令對 data.txt 文件的內(nèi)容計算 SHA256 摘要;然后使用對輸出的 32 字節(jié)的摘要信息,使用 rsa_private.key 指定的私鑰進行加密,并把密文輸出到 data.sign 文件里。data.sign 是個二進制文件,文件里保存的內(nèi)容就是 data.txt 文件的數(shù)字簽名。 接著,我們對數(shù)字內(nèi)容進行簽名檢查,檢查簽名時使用的是公鑰: $ openssl dgst -sha256 -verify rsa_public.key -signature data.sign data.txt 不出意外的話,輸出的內(nèi)容為: Verified OK 表示數(shù)字簽名驗證成功,data.txt 文件的內(nèi)容沒有被篡改?,F(xiàn)在,我們把 data.txt 文件修改一下,看看簽名驗證能否成功: $ echo 'This is fake words from Joey.' > data.txt$ openssl dgst -sha256 -verify rsa_public.key -signature data.sign data.txtVerification Failure 此時輸出的是 Verification Failure 表示數(shù)字簽名驗證失敗。 當(dāng)然,如果我們手頭沒有現(xiàn)成的公鑰業(yè)驗證簽名,只要有這個網(wǎng)站的證書,則可以可以從證書里獲取到公鑰: openssl x509 -in cert_ca_signed.crt -pubkey -noout > rsa_public.key (完) |
|
來自: 昵稱48503472 > 《區(qū)塊鏈》