對 certificate 這個東西又多了解了一些,這邊記錄一下目前的理解以及一些連結,方便查詢
ASN.1 定義
Certificate 用 ASN.1 表示,編碼成DER格式,或是再由DER格式轉成PEM格式,PEM格式可以用printable string來表示binary file。這裡列出 Certificate 會用到的 ASN.1 定義
Certificate ::= SEQUENCE { tbsCertificate TBSCertificate, signatureAlgorithm AlgorithmIdentifier, signatureValue BIT STRING } AlgorithmIdentifier ::= SEQUENCE { algorithm OBJECT IDENTIFIER, parameters ANY DEFINED BY algorithm OPTIONAL } TBSCertificate ::= SEQUENCE { version [0] EXPLICIT Version DEFAULT v1, serialNumber CertificateSerialNumber, signature AlgorithmIdentifier, issuer Name, validity Validity, subject Name, subjectPublicKeyInfo SubjectPublicKeyInfo, issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, -- If present, version MUST be v2 or v3 subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, -- If present, version MUST be v2 or v3 extensions [3] EXPLICIT Extensions OPTIONAL -- If present, version MUST be v3 } Version ::= INTEGER { v1(0), v2(1), v3(2) } CertificateSerialNumber ::= INTEGER Validity ::= SEQUENCE { notBefore Time, notAfter Time } Time ::= CHOICE { utcTime UTCTime, generalTime GeneralizedTime } UniqueIdentifier ::= BIT STRING SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING } Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension Extension ::= SEQUENCE { extnID OBJECT IDENTIFIER, critical BOOLEAN DEFAULT FALSE, extnValue OCTET STRING -- contains the DER encoding of an ASN.1 value -- corresponding to the extension type identified -- by extnID } Name ::= CHOICE { -- only one possibility for now -- rdnSequence RDNSequence } RDNSequence ::= SEQUENCE OF RelativeDistinguishedName RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue AttributeTypeAndValue ::= SEQUENCE { type AttributeType, value AttributeValue } AttributeType ::= OBJECT IDENTIFIER AttributeValue ::= ANY -- DEFINED BY AttributeType DigestInfo ::= SEQUENCE { digestAlgorithm DigestAlgorithmIdentifier, digest Digest } DigestAlgorithmIdentifier ::= AlgorithmIdentifier Digest ::= OCTET STRING
Example file
使用 DOCSIS 的 Test certificate 來當範例Test DOCSIS ROOT Cert
Test DOCSIS ROOT Private Key
Test DOCSIS ROOT Public Key
Test CVC
Certificate format
直接拿範例(Test_CVC.der)來了解certificate
一張 certificate 從最外層分可以切成 3 塊
tbsCertificate: tbs (to be sign 縮寫 ?), 這部分是 certificate 的主體,包含最重要的 public key, 以及這隻key的各種屬性,例如:版本,序號,有效日期,...等
signatureAlgorithm : 簽發者(issuer) 用的演算法
signatureValue : 用簽發者的 private key 搭配 signatureAlgorithm 計算 tbsCertificate 的結果, 收到 certificate 的人則是利用簽發者的 public key 去驗證簽名是否正確
signature
先看 sign certificate這件事做了什麼tbsCertificate 就是要被拿來計算的資料,要如何計算則是記在 signatureAlgorithm 裡
先把 Test_CVC.der 拆開,
package require asn set fd [open mfgcvc.der r] fconfigure $fd -translation binary set cvc [read $fd] close $fd ::asn::asnGetSequence cvc cert #取出 tbsCertificate,tbsCertificate的 tag 是 Sequence ::asn::asnGetSequence cert tbs #匯出時要把 tag,length補回去 set fd [open tbsCertificate w] fconfigure $fd -translation binary puts -nonewline $fd [::asn::asnSequence $tbs] close $fd #取出 signatureAlgorithm , 1.2.840.113549.1.1.5 - SHA-1 with RSA Encryption ::asn::asnGetSequence cert alg ::asn::asnGetObjectIdentifier alg oid binary scan $alg H* parameters puts oid=[join $oid .] puts parameters=$parameters # 取出 signature,只匯出 content ::asn::asnGetBitString cert sign set fd [open signatureValue w] fconfigure $fd -translation binary puts -nonewline $fd [binary format B* $sign] close $fd
解出 tbsCertificate 和 signatureValue 兩個檔案,並看一下 signatureAlgorithm
signatureAlgorithm 解出來的結果是
oid=1.2.840.113549.1.1.5 (SHA-1 with RSA Encryption)
parameters=0500 (這是Null,目前看過的這個參數都是Null)
簽發及驗證
分別看簽發者與接收者的動作
簽發者:
1.先算出sha1 hash
openssl sha1 tbsCertificate
SHA1(tbscert)= 1a8e55e7778defea444f7c88ca685b4ce6593cca
2.把 hash 編碼成 DigestInfo
package require asn package require asn # http://www.alvestrand.no/objectid/1.3.14.3.2.26.html # 1.3.14.3.2.26 - SHA-1 hash algorithm # DigestInfo ::= SEQUENCE { # digestAlgorithm DigestAlgorithmIdentifier, # digest Digest } # DigestAlgorithmIdentifier ::= AlgorithmIdentifier # Digest ::= OCTET STRING # AlgorithmIdentifier ::= SEQUENCE { # algorithm OBJECT IDENTIFIER, # parameters ANY DEFINED BY algorithm OPTIONAL } set digestAlgorithm "" append digestAlgorithm [asn::asnObjectIdentifier [split 1.3.14.3.2.26 .]] append digestAlgorithm [asn::asnNull] set digestAlgorithm [asn::asnSequence $digestAlgorithm] set digest [asn::asnOctetString [binary format H* 1a8e55e7778defea444f7c88ca685b4ce6593cca]] set DigestInfo [asn::asnSequence $digestAlgorithm$digest] # 輸出 DigestInfo 再用 openssl 加密 set fd [open DigestInfo w] fconfigure $fd -translation binary puts -nonewline $fd $DigestInfo close $fd
3.再把結果 padding 後用 private key 加密就能算出 signatureValue openssl rsautl -inkey TEST_DOCSIS_CABLE_MODEM_ROOT_CA_PRIVATEKEY.PEM -sign -in DigestInfo -out DigestInfo.der 算出來的DigestInfo.der 就是 signatureValue,可以拿算出來的 DigestInfo.der 和從 certificate 解出來的 signatureValue 來驗證有沒有算對 openssl 有指令可以一次完成 hash,padding,encrypt openssl sha1 -sign TEST_DOCSIS_CABLE_MODEM_ROOT_CA_PRIVATEKEY.PEM tbscert > sign 實際用 openssl 在 sign certificate 時不需要這麼麻煩,有更方便的指令把這些動作一次做完,這個例子是用來了解 sign certificate 做了什麼事 知道怎麼 sign 之後就可以修改 tbsCertificate 的某些欄位,再手動更新 signatureValue 成正確的值 例如: 修改 certificate 的有效時間,openssl X509 指令不能設定精確的時間值,可以先用 x509 sign 出一張 certificate 後再手動修改 (當初就是很龜毛的想弄出0:0:0 ~ 23:59:59 才開始研究怎麼算出signatureValue, 後來是直接修改 openssl source code 把時間參數加上去) 接收端: 收到 certificate 後就要利用簽發者的 public key 驗證 certificate 的來源是否可靠 方法與 sign certificate 類似 1.同樣先算出sha1 hash openssl sha1 tbsCertificate SHA1(tbscert)= 1a8e55e7778defea444f7c88ca685b4ce6593cca 2.將 signatureValue 解密 這指令解密完順便解開 asn1 編碼 openssl rsautl -verify -inkey TEST_DOCSIS_CABLE_MODEM_ROOT_CA_PUBLICKEY.PEM -pubin -in signature -asn1parse Loading 'screen' into random state - done 0:d=0 hl=2 l= 33 cons: SEQUENCE 2:d=1 hl=2 l= 9 cons: SEQUENCE 4:d=2 hl=2 l= 5 prim: OBJECT :sha1 11:d=2 hl=2 l= 0 prim: NULL 13:d=1 hl=2 l= 20 prim: OCTET STRING 0000 - 1a 8e 55 e7 77 8d ef ea-44 4f 7c 88 ca 68 5b 4c ..U.w...DO|..h[L 0010 - e6 59 3c ca .Y<. 比較後知道 hash 值是一樣的,可以知道這張certificate 確實是由 TEST_DOCSIS_CABLE_MODEM_ROOT_CA 所簽發的,剩下的就是查看 tbsCertificate 的各項屬性來決定這張certificate 是否合用tbsCertificate
tbsCertificate 用 sequence 把以下內容包起來version
是 [APPLICATION 0] 包一個 INTEGER,所以 TAG 是 A0, integer 有3種可能 v1(0), v2(1), v3(2),CVC 用的是 v3 所以是 a0 03 02 01 02serialNumber
很單純的以 integer 表示signature
簽發者使用的演算法,這個值和 signatureAlgorithm 必須是一樣的,CVC 用的是SHA-1 with RSA, null parameters 所以會編成 30 0d 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 oid=1.2.840.113549.1.1.5 value=Nullissuer,subject
簽發者,主體,這兩個格式相同,用 oid 和 value 表示,再一層一層包起來,直接看CVC這個範例 美規 CVC issuer 有這幾個值是固定的 countryName(2.5.4.6): US organizationName(2.5.4.10): Data Over Cable Service Interface Specifications organizationalUnitName(2.5.4.11): Cable Modems commonName(2.5.4.3): DOCSIS Cable Modem Root Certificate Authority 編成 DER format 如下,其中 AttributeValue 都用 printable string 表示 printable string 的tag為 0x13 30 81 97 31 0b 30 09 06 03 55 04 06 (2.5.4.6) 13 02 55 53 (US) 31 39 30 37 06 03 55 04 0a (2.5.4.10) 13 30 44 61 74 61 20 4f 76 65 72 20 43 61 62 6c 65 20 53 65 72 76 69 63 65 20 49 6e 74 65 72 66 61 63 65 20 53 70 65 63 69 66 69 63 61 74 69 6f 6e 73 (Data Over Cable Service Interface Specifications) 31 15 30 13 06 03 55 04 0b (2.5.4.11) 13 0c 43 61 62 6c 65 20 4d 6f 64 65 6d 73 (Cable Modems) 31 36 30 34 06 03 55 04 03 (2.5.4.3) 13 2d 44 4f 43 53 49 53 20 43 61 62 6c 65 20 4d 6f 64 65 6d 20 52 6f 6f 74 20 43 65 72 74 69 66 69 63 61 74 65 20 41 75 74 68 6f 72 69 74 79 (DOCSIS Cable Modem Root Certificate Authority) subject 內容為 countryNameorganizationName organizationalUnitName DOCSIS commonName Code Verification Certificate organizationalUnitName 與 commonName 的值是固定的,在此範例裡 countryName = US, organizationName=VendorA organizationName 的值對 CVC 非常重要,CM 做 secure upgrade 時會比對這個值與 CM 裡的設定是否相同 因為 type 和issuer 相同 DER 就不列出來了 validity
記錄 certificate 生效以及到期的時間 30 1e (sequence ) 17 0d 30 31 30 31 30 31 30 30 30 30 30 30 5a (010101000000Z) 17 0d 31 31 30 31 30 31 30 30 30 30 30 30 5a (110101000000Z)SubjectPublicKeyInfo
certificate 最重要的內容: public key,certificate 就是用來發不公鑰的,這個欄位記錄公鑰的種類與值 30 82 01 22 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 (1.2.840.113549.1.1.1 - RSA encryption) 05 00 (Null) 03 82 01 0f (public key,以 bitstring 表示) 00 30 82 01 0a 02 82 01 01 00 a2 05 d2 10 02 f3 47 b4 dd 2e 2a 9b 05 b3 86 38 a4 91 6d ad 39 5a da 0b 48 55 9b 94 dd 4e 9d 8b 98 c6 18 6d e8 de 1e 81 db ce 8f 3c 6d 02 81 fa 1e 46 f1 93 30 c2 79 bb ba f6 50 b2 db 10 b2 13 c0 bd a5 4d 33 5f 43 0d 9f a0 de 9b 8b 71 b5 ff 1f 48 e1 06 38 71 b8 df 3c 93 c6 f8 eb 90 a6 d2 a4 aa 7b 4e f1 2e 5c 11 07 88 1d 13 f8 60 d8 e2 3b e5 c7 7b 30 39 74 75 94 e3 73 19 92 b6 81 2f b7 db 85 be 6a 8e 54 e9 dd 67 8f a7 a3 4c d6 22 50 a8 0d 69 41 98 d5 a3 af 51 8d 48 44 f4 35 9d 5d 7d a3 d1 62 e4 01 3f 62 05 e1 89 57 5e 5b 90 09 ff 83 7b b6 f2 0d 32 72 47 9e e2 d6 1a 15 c0 97 53 9a a8 9f 24 5c 88 cf bb 98 b4 da 01 73 33 31 ea aa 8d e2 01 9f 20 3e e1 67 dd 36 2e 3c 83 28 5d 28 bb 6a d9 30 94 37 e6 d8 86 42 32 c7 9b 36 68 65 3b 3f 40 f3 87 1a 31 92 90 93 a3 21 b1 02 03 01 00 01 而 RSA 的 public key 為以下格式 RSAPublicKey ::= SEQUENCE { modulus INTEGER, -- n publicExponent INTEGER, -- e – } CVC public key 有以下規定 The CM MUST be able to verify DOCSIS code file signatures that are signed using key modulus lengths of 1024, 1536 and 2048 bits. The public exponent is F4 (65537 decimal) 繼續把這個 bitstring 拆開 30 82 01 0a 02 82 01 01 00 a2 05 d2 10 02 f3 47 b4 dd 2e 2a 9b 05 b3 86 (modulus n,這個犯利用的 key 長度是 1024 bits) 38 a4 91 6d ad 39 5a da 0b 48 55 9b 94 dd 4e 9d 8b 98 c6 18 6d e8 de 1e 81 db ce 8f 3c 6d 02 81 fa 1e 46 f1 93 30 c2 79 bb ba f6 50 b2 db 10 b2 13 c0 bd a5 4d 33 5f 43 0d 9f a0 de 9b 8b 71 b5 ff 1f 48 e1 06 38 71 b8 df 3c 93 c6 f8 eb 90 a6 d2 a4 aa 7b 4e f1 2e 5c 11 07 88 1d 13 f8 60 d8 e2 3b e5 c7 7b 30 39 74 75 94 e3 73 19 92 b6 81 2f b7 db 85 be 6a 8e 54 e9 dd 67 8f a7 a3 4c d6 22 50 a8 0d 69 41 98 d5 a3 af 51 8d 48 44 f4 35 9d 5d 7d a3 d1 62 e4 01 3f 62 05 e1 89 57 5e 5b 90 09 ff 83 7b b6 f2 0d 32 72 47 9e e2 d6 1a 15 c0 97 53 9a a8 9f 24 5c 88 cf bb 98 b4 da 01 73 33 31 ea aa 8d e2 01 9f 20 3e e1 67 dd 36 2e 3c 83 28 5d 28 bb 6a d9 30 94 37 e6 d8 86 42 32 c7 9b 36 68 65 3b 3f 40 f3 87 1a 31 92 90 93 a3 21 b1 02 03 01 00 01 (publicExponent e, 0x010001 = 655337)issuerUniqueID subjectUniqueID
所有 DOCSIS 的 certificate 都沒用到這兩個欄位,目前實際在用的 certificate 中也沒看過有這兩個欄位的 用 openssl x509 與windows7 也沒解出這兩個值 RFC - support for subjectUniqueID and issuerUniqueID How put issuerUniqueID into certificate?extensions
這是v3才有的欄位,每個 extension 有三個值 extnID: 以 oid 表示 critical: BOOLEAN DEFAULT FALSE,可省略 當使用 certificate 的系統發現其中的 extension 是標示為 critical, 但系統無法辨識,處理這個 extension,系統必須拒絕使用這張 certificate 若 extension 是標示為 non-critical,系統就可以忽略這個 extension,但若系統可以辨識這個 extension,就必須處理這個 extension extnValue: OCTET STRING,根據各個 extnID 有不同的格式 以 CVC 為例,有一個 critical extension, 用來說明這隻金鑰的用途是codeSigning extnID=2.5.29.37 - Extended key usage critical= True extnValue 就要根據 Extended key usage 的格式去編碼 id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37} ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId KeyPurposeId ::= OBJECT IDENTIFIER CVC 的 KeyPurposeId 是 1.3.6.1.5.5.7.3.3 - id_kp_codeSigning 所以這一段的 DER 是 a3 1a ( extensions [3]) 30 18 30 16 ( extension ) 06 03 55 1d 25 (extnID 2.5.29.37 Extended key usage) 01 01 ff (critical true) 04 0c (extnValue) 30 0a 06 08 2b 06 01 05 05 07 03 03 (oid = 1.3.6.1.5.5.7.3.3 id_kp_codeSigning) 以下列幾個 DOCSIS certificate 有用到的 extension (有玩到其他 extension 再繼續補) Basic Constraints (基本限制) 用來標示這張 certificate 是否為 CA,以及深度(在這張 certificate 以下最多允許幾層 non-selg-sign CA) id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } BasicConstraints ::= SEQUENCE { cA BOOLEAN DEFAULT FALSE, pathLenConstraint INTEGER (0..MAX) OPTIONAL } DOCSIS Root CA Certificate 的 cA = True pathLenConstraint = 1 DER 為 30 12 06 03 55 1d 13 (2.5.29.19 - Basic Constraints) 01 01 ff (critical = True) 04 08 30 06 01 01 ff (cA = True) 02 01 01 (pathLenConstraint = 1 ) keyUsage (金鑰使用方法) 標示金鑰用途 id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } KeyUsage ::= BIT STRING { digitalSignature (0), nonRepudiation (1), -- recent editions of X.509 have -- renamed this bit to contentCommitment keyEncipherment (2), dataEncipherment (3), keyAgreement (4), keyCertSign (5), cRLSign (6), encipherOnly (7), decipherOnly (8) } DOCSIS Root CA Certificate 有用到這個 extension For the keyUsage extension, the keyCertSign bit is set, the cRLSign bit may be set, and all other bits should not be set. (CM-SP-SECv3.0-I15-130808 Appendix III.1.6.4 DOCSIS Root CA Certificate) 30 0e 06 03 55 1d 0f (2.5.29.15 - Key Usage) 01 01 ff (critical = True) 04 04 03 02 01 06 (bitstring 0000011, keyCertSign,cRLSign = 1) ^bit 0其他欄位
用 windows 檢視 certificate 時會出現一些不存在檔案本身的資訊 Thumbprint algorithm : hash 演算法 (目前只看過 sha1) Thumbprint : 利用 Thumbprint algorithm 計算 certificate 的結果,certificate 必須使用 DER 格式,如果是 PEM 要先轉成 DER 再計算中英文對照表
有些中文翻譯看起來怪怪的,整理以下對照表,想到就更新一下
Windows 英文版 WinXP 中文版 Win7 中文版 註解 tbsCertificate Version 1 Fields Only 只有版本1的欄位 版本1的欄位指的就是tbsCertificate裡的內容 version Version 版本 版本 serialNumber Serial number 序號 序號 signature Signature algorithm 簽章演算法 簽章演算法 Signature hash algorithm - 簽章雜湊演算法 win7 新增的欄位(可參考Difference between “Signature Algorithm” and “Signature Hash Algorithm” in X.509) issuer Issuer 發行者 簽發者 notBefore Valid from 有效期自 有效期自 notAfter Valid to 有效到 有效期到 subject Subject 主體 主體 subjectPublicKeyInfo Public Key 公開金鑰 公開金鑰 subjectPublicKeyInfo 裡包含公鑰類型與內容,公開金鑰的值只有 subjectPublicKeyInfo 的 subjectPublicKey extensions Extension OnlyCritical Extensions Only 副檔名 關鍵副檔名 延伸關鍵延伸 windows 顯示 certificate 的 extension 欄位時,"!" 表示critical ; "↓" 表示non-critical Key Usage 金鑰使用方式 金鑰使用方式 Basic Constraints 基本限制 基本限制 Subject Key Identifier 主體金鑰識別元 主體金鑰識別元 Version 1 Fields Only 只有版本1的欄位 版本1的欄位指的就是tbsCertificate裡的內容
沒有留言:
張貼留言