接觸GMSSL一段時間了,總結一點點想法
證書:DER格式、PEM格式
.DER = DER擴展用於二進制DER編碼證書。
.PEM = PEM擴展用於不同類型的X.509v3文件,是以“ - BEGIN ...”前綴的ASCII(Base64)數據。
DER格式是二進制的,PEM則是文本格式,
實際上,PEM格式的內容在去掉"---BEGIN"的內容,采取BASE64解碼,得到的BLOG內容,就是DER格式的內容
DER的內容,實際上在GMSSL、OPENSSL中,都是以ASN.1格式進行編碼的內存BLOB
查看GMSSL的代碼,就可以看到公鑰、私鑰各自的ASN格式化支持代碼
RSA的公鑰、私鑰支持代碼如下:
ASN1_SEQUENCE_cb(RSAPrivateKey, rsa_cb) = { ASN1_SIMPLE(RSA, version, LONG), ASN1_SIMPLE(RSA, n, BIGNUM), ASN1_SIMPLE(RSA, e, BIGNUM), ASN1_SIMPLE(RSA, d, CBIGNUM), ASN1_SIMPLE(RSA, p, CBIGNUM), ASN1_SIMPLE(RSA, q, CBIGNUM), ASN1_SIMPLE(RSA, dmp1, CBIGNUM), ASN1_SIMPLE(RSA, dmq1, CBIGNUM), ASN1_SIMPLE(RSA, iqmp, CBIGNUM) } ASN1_SEQUENCE_END_cb(RSA, RSAPrivateKey) ASN1_SEQUENCE_cb(RSAPublicKey, rsa_cb) = { ASN1_SIMPLE(RSA, n, BIGNUM), ASN1_SIMPLE(RSA, e, BIGNUM), } ASN1_SEQUENCE_END_cb(RSA, RSAPublicKey)
對於BIGNUM,在格式化時,會先輸出一個長度字節(1 byte),再依次輸出內容
SM2只定義了密文中的ASN.1的格式化支持代碼,如下:
ASN1_SEQUENCE(SM2CiphertextValue) = {
ASN1_SIMPLE(SM2CiphertextValue, xCoordinate, BIGNUM),
ASN1_SIMPLE(SM2CiphertextValue, yCoordinate, BIGNUM),
ASN1_SIMPLE(SM2CiphertextValue, hash, ASN1_OCTET_STRING),
ASN1_SIMPLE(SM2CiphertextValue, ciphertext, ASN1_OCTET_STRING),
} ASN1_SEQUENCE_END(SM2CiphertextValue)
這兒實際定義了密文的三塊C1/C2/C3,C1=(x+y)的內容,C2是ciphertext部分,C3是hash部分
至於ASN.1實際的BLOB內存編碼,從RSA的公、私鑰分析文件可以看出,鏈接:https://etherhack.co.uk/asymmetric/docs/rsa_key_breakdown.html
參考如下:
[description] [256bit] [512bit] [1024bit] [2048bit] [4096bit]
OpenSSL 1024 bit RSA Private Key Breakdown
On Linux, using the following command generated this key:
openssl genrsa -out rsa_1024_priv.pem 1024
To understand how the key is broken down into its respective components, execute the following additional command:
openssl rsa -text -in rsa_1024_priv.pem
Alternatively, you can do what I did and breakdown the individual components by hand - in order to learn how the data structure actually works.
Firstly, the data block has to be decoded from it's standard Base64 format, so remove the "-----BEGIN..." lines at the start and end of the file and convert the data into Hexadecimal.
The data block is now in a format we can read (sort of).
Using Abstract Syntax Notation 1 (or ASN.1), we can read and identify the Distinguished Encoding Rules (DER) encoded components contained within this data.
Although the only data stored in this instance of the ASN format is of type Integer, other standard variable types are listed here for clarity. When the Integer type is used in this context, it is followed by the length in bytes for the following data object, and then the data itself, as can be seen below.
- 0x02 == Integer
- 0x03 == Bit String
- 0x04 == Octet String
- 0x05 == NULL
- 0x06 == Object Identifier
- 0x10 == "Sequence" and "Sequence of"
- 0x11 == "Set" and "Set of"
- 0x13 == Printable String
- 0x14 == T61 String
- 0x16 == IA5 String
- 0x17 == UTC Time
- 0x30 82 == ASN1 Sequence
1024 bit RSA Private Key in Base64 Format
-----BEGIN RSA PRIVATE KEY----- MIICXgIBAAKBgQDHikastc8+I81zCg/qWW8dMr8mqvXQ3qbPAmu0RjxoZVI47tvs kYlFAXOf0sPrhO2nUuooJngnHV0639iTTEYG1vckNaW2R6U5QTdQ5Rq5u+uV3pMk 7w7Vs4n3urQ6jnqt2rTXbC1DNa/PFeAZatbf7ffBBy0IGO0zc128IshYcwIDAQAB AoGBALTNl2JxTvq4SDW/3VH0fZkQXWH1MM10oeMbB2qO5beWb11FGaOO77nGKfWc bYgfp5Ogrql4yhBvLAXnxH8bcqqwORtFhlyV68U1y4R+8WxDNh0aevxH8hRS/1X5 031DJm1JlU0E+vStiktN0tC3ebH5hE+1OxbIHSZ+WOWLYX7JAkEA5uigRgKp8ScG auUijvdOLZIhHWq7y5Wz+nOHUuDw8P7wOTKU34QJAoWEe771p9Pf/GTA/kr0BQnP QvWUDxGzJwJBAN05C6krwPeryFKrKtjOGJIniIoY72wRnoNcdEEs3HDRhf48YWFo riRbZylzzzNFy/gmzT6XJQTfktGqq+FZD9UCQGIJaGrxHJgfmpDuAhMzGsUsYtTr iRox0D1Iqa7dhE693t5aBG010OF6MLqdZA1CXrn5SRtuVVaCSLZEL/2J5UcCQQDA d3MXucNnN4NPuS/L9HMYJWD7lPoosaORcgyK77bSSNgk+u9WSjbH1uYIAIPSffUZ bti+jc1dUg5wb+aeZlgJAkEAurrpmpqj5vg087ZngKfFGR5rozDiTsK5DceTV97K a3Y+Nzl+XWTxDBWk4YPh2ZlKv402hZEfWBYxUDn5ZkH/bw== -----END RSA PRIVATE KEY-----
Private Key in Hexadecimal Format
In this example, the Hexadecimal values have been paired for clarity, but in the other examples (see links at the top of this page) the values have not been separated.
Parts highlighted below, in order:
- ASN.1 Header
- Algorithm Version
- Modulus
- Public Exponent
- Private Exponent
- prime1
- prime2
- exponent 1
- exponent 2
- coefficient
-----BEGIN RSA PRIVATE KEY-----
30 82 02 5e 02 01 00 02 81 81 00 c7 8a 46 ac b5 cf 3e 23 cd 73 0a
0f ea 59 6f 1d 32 bf 26 aa f5 d0 de a6 cf 02 6b b4 46 3c 68 65 52
38 ee db ec 91 89 45 01 73 9f d2 c3 eb 84 ed a7 52 ea 28 26 78 27
1d 5d 3a df d8 93 4c 46 06 d6 f7 24 35 a5 b6 47 a5 39 41 37 50 e5
1a b9 bb eb 95 de 93 24 ef 0e d5 b3 89 f7 ba b4 3a 8e 7a ad da b4
d7 6c 2d 43 35 af cf 15 e0 19 6a d6 df ed f7 c1 07 2d 08 18 ed 33
73 5d bc 22 c8 58 73 02 03 01 00 01 02 81 81 00 b4 cd 97 62 71 4e
fa b8 48 35 bf dd 51 f4 7d 99 10 5d 61 f5 30 cd 74 a1 e3 1b 07 6a
8e e5 b7 96 6f 5d 45 19 a3 8e ef b9 c6 29 f5 9c 6d 88 1f a7 93 a0
ae a9 78 ca 10 6f 2c 05 e7 c4 7f 1b 72 aa b0 39 1b 45 86 5c 95 eb
c5 35 cb 84 7e f1 6c 43 36 1d 1a 7a fc 47 f2 14 52 ff 55 f9 d3 7d
43 26 6d 49 95 4d 04 fa f4 ad 8a 4b 4d d2 d0 b7 79 b1 f9 84 4f b5
3b 16 c8 1d 26 7e 58 e5 8b 61 7e c9 02 41 00 e6 e8 a0 46 02 a9 f1
27 06 6a e5 22 8e f7 4e 2d 92 21 1d 6a bb cb 95 b3 fa 73 87 52 e0
f0 f0 fe f0 39 32 94 df 84 09 02 85 84 7b be f5 a7 d3 df fc 64 c0
fe 4a f4 05 09 cf 42 f5 94 0f 11 b3 27 02 41 00 dd 39 0b a9 2b c0
f7 ab c8 52 ab 2a d8 ce 18 92 27 88 8a 18 ef 6c 11 9e 83 5c 74 41
2c dc 70 d1 85 fe 3c 61 61 68 ae 24 5b 67 29 73 cf 33 45 cb f8 26
cd 3e 97 25 04 df 92 d1 aa ab e1 59 0f d5 02 40 62 09 68 6a f1 1c
98 1f 9a 90 ee 02 13 33 1a c5 2c 62 d4 eb 89 1a 31 d0 3d 48 a9 ae
dd 84 4e bd de de 5a 04 6d 35 d0 e1 7a 30 ba 9d 64 0d 42 5e b9 f9
49 1b 6e 55 56 82 48 b6 44 2f fd 89 e5 47 02 41 00 c0 77 73 17 b9
c3 67 37 83 4f b9 2f cb f4 73 18 25 60 fb 94 fa 28 b1 a3 91 72 0c
8a ef b6 d2 48 d8 24 fa ef 56 4a 36 c7 d6 e6 08 00 83 d2 7d f5 19
6e d8 be 8d cd 5d 52 0e 70 6f e6 9e 66 58 09 02 41 00 ba ba e9 9a
9a a3 e6 f8 34 f3 b6 67 80 a7 c5 19 1e 6b a3 30 e2 4e c2 b9 0d c7
93 57 de ca 6b 76 3e 37 39 7e 5d 64 f1 0c 15 a4 e1 83 e1 d9 99 4a
bf 8d 36 85 91 1f 58 16 31 50 39 f9 66 41 ff 6f
-----END RSA PRIVATE KEY-----
Extracted Key Components, in order of appearance
Private-Key:
header:
30 82 02 5e (0x3082 == ASN.1 Sequence)
separator:
02 01 (0x02 == Integer and 0x01 == 1 byte long)
algorithm version:
00 (0x00 == version zero)
separator:
02 81 81 (0x02 == Integer and 0x81 == 129 bytes long)
modulus: (129 bytes - starts with a null (0x00), remove this.)
00 c7 8a 46 ac b5 cf 3e 23 cd 73 0a 0f ea 59
6f 1d 32 bf 26 aa f5 d0 de a6 cf 02 6b b4 46
3c 68 65 52 38 ee db ec 91 89 45 01 73 9f d2
c3 eb 84 ed a7 52 ea 28 26 78 27 1d 5d 3a df
d8 93 4c 46 06 d6 f7 24 35 a5 b6 47 a5 39 41
37 50 e5 1a b9 bb eb 95 de 93 24 ef 0e d5 b3
89 f7 ba b4 3a 8e 7a ad da b4 d7 6c 2d 43 35
af cf 15 e0 19 6a d6 df ed f7 c1 07 2d 08 18
ed 33 73 5d bc 22 c8 58 73
separator:
02 03 (0x02 == Integer and 0x03 == 3 bytes long)
public exponent: (3 bytes)
01 00 01 (Integer value 65537, Fermat Number F4)
separator:
02 81 81 (0x02 == Integer and 0x81 == 129 bytes long)
private exponent: (129 bytes - starts with a null, remove this)
00 b4 cd 97 62 71 4e fa b8 48 35 bf dd 51 f4
7d 99 10 5d 61 f5 30 cd 74 a1 e3 1b 07 6a 8e
e5 b7 96 6f 5d 45 19 a3 8e ef b9 c6 29 f5 9c
6d 88 1f a7 93 a0 ae a9 78 ca 10 6f 2c 05 e7
c4 7f 1b 72 aa b0 39 1b 45 86 5c 95 eb c5 35
cb 84 7e f1 6c 43 36 1d 1a 7a fc 47 f2 14 52
ff 55 f9 d3 7d 43 26 6d 49 95 4d 04 fa f4 ad
8a 4b 4d d2 d0 b7 79 b1 f9 84 4f b5 3b 16 c8
1d 26 7e 58 e5 8b 61 7e c9
separator:
02 41 (0x02 == Integer and 0x41 == 65 bytes long)
prime1: (65 bytes - starts with a null, remove this)
00 e6 e8 a0 46 02 a9 f1 27 06 6a e5 22 8e f7
4e 2d 92 21 1d 6a bb cb 95 b3 fa 73 87 52 e0
f0 f0 fe f0 39 32 94 df 84 09 02 85 84 7b be
f5 a7 d3 df fc 64 c0 fe 4a f4 05 09 cf 42 f5
94 0f 11 b3 27
separator:
02 41 (0x02 == Integer and 0x41 == 65 bytes long)
prime2: (65 bytes - starts with a null, remove this)
00 dd 39 0b a9 2b c0 f7 ab c8 52 ab 2a d8 ce
18 92 27 88 8a 18 ef 6c 11 9e 83 5c 74 41 2c
dc 70 d1 85 fe 3c 61 61 68 ae 24 5b 67 29 73
cf 33 45 cb f8 26 cd 3e 97 25 04 df 92 d1 aa
ab e1 59 0f d5
separator:
02 40 (0x02 == Integer and 0x40 == 64 bytes long)
exponent1: (64 bytes)
62 09 68 6a f1 1c 98 1f 9a 90 ee 02 13 33 1a
c5 2c 62 d4 eb 89 1a 31 d0 3d 48 a9 ae dd 84
4e bd de de 5a 04 6d 35 d0 e1 7a 30 ba 9d 64
0d 42 5e b9 f9 49 1b 6e 55 56 82 48 b6 44 2f
fd 89 e5 47
separator:
02 41 (0x02 == Integer and 0x41 == 65 bytes long)
exponent2: (65 bytes - starts with a null, remove this)
00 c0 77 73 17 b9 c3 67 37 83 4f b9 2f cb f4
73 18 25 60 fb 94 fa 28 b1 a3 91 72 0c 8a ef
b6 d2 48 d8 24 fa ef 56 4a 36 c7 d6 e6 08 00
83 d2 7d f5 19 6e d8 be 8d cd 5d 52 0e 70 6f
e6 9e 66 58 09
separator:
02 41 (0x02 == Integer and 0x41 == 65 bytes long)
coefficient: (65 bytes - always starts with a null)
00 ba ba e9 9a 9a a3 e6 f8 34 f3 b6 67 80 a7
c5 19 1e 6b a3 30 e2 4e c2 b9 0d c7 93 57 de
ca 6b 76 3e 37 39 7e 5d 64 f1 0c 15 a4 e1 83
e1 d9 99 4a bf 8d 36 85 91 1f 58 16 31 50 39
f9 66 41 ff 6f
SSL 1024 bit RSA Public Key Breakdown
Using Linux, the following command generated this public key:
openssl rsa -pubout -in rsa_1024_priv.pem -out rsa_1024_pub.pem
-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHikastc8+I81zCg/qWW8dMr8m qvXQ3qbPAmu0RjxoZVI47tvskYlFAXOf0sPrhO2nUuooJngnHV0639iTTEYG1vck NaW2R6U5QTdQ5Rq5u+uV3pMk7w7Vs4n3urQ6jnqt2rTXbC1DNa/PFeAZatbf7ffB By0IGO0zc128IshYcwIDAQAB -----END PUBLIC KEY-----
Public Key in Hexadecimal Format
Parts in bold, in order:
- Modulus
- Public Exponent
-----BEGIN PUBLIC KEY-----
30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 81 8d 00
30 81 89 02 81 81 00 c7 8a 46 ac b5 cf 3e 23 cd 73 0a 0f ea 59 6f
1d 32 bf 26 aa f5 d0 de a6 cf 02 6b b4 46 3c 68 65 52 38 ee db ec
91 89 45 01 73 9f d2 c3 eb 84 ed a7 52 ea 28 26 78 27 1d 5d 3a df
d8 93 4c 46 06 d6 f7 24 35 a5 b6 47 a5 39 41 37 50 e5 1a b9 bb eb
95 de 93 24 ef 0e d5 b3 89 f7 ba b4 3a 8e 7a ad da b4 d7 6c 2d 43
35 af cf 15 e0 19 6a d6 df ed f7 c1 07 2d 08 18 ed 33 73 5d bc 22
c8 58 73 02 03 01 00 01
-----END PUBLIC KEY-----
Extracted Public Key Components
header:
30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01
01 05 00 03 81 8d 00 30 81 89
separator:
02 81 81
modulus:
00 c7 8a 46 ac b5 cf 3e 23 cd 73 0a 0f ea 59
6f 1d 32 bf 26 aa f5 d0 de a6 cf 02 6b b4 46
3c 68 65 52 38 ee db ec 91 89 45 01 73 9f d2
c3 eb 84 ed a7 52 ea 28 26 78 27 1d 5d 3a df
d8 93 4c 46 06 d6 f7 24 35 a5 b6 47 a5 39 41
37 50 e5 1a b9 bb eb 95 de 93 24 ef 0e d5 b3
89 f7 ba b4 3a 8e 7a ad da b4 d7 6c 2d 43 35
af cf 15 e0 19 6a d6 df ed f7 c1 07 2d 08 18
ed 33 73 5d bc 22 c8 58 73
separator:
02 03
public exponent:
01 00 01
[W3C Valid CSS 2]
[W3C Valid XHTML 1.1]
另外,參考學習此鏈接:https://tls.mbed.org/kb/cryptography/asn1-key-structures-in-der-and-pem
快速翻譯版本如下:
DER和PEM中的ASN.1關鍵結構
介紹
每個人都喜歡PEM和用於以便攜式格式保存加密密鑰和證書的ASN.1結構。好吧..如果他們真的被記錄下來,每個人都會這樣做。但是,找到每個DER或PEM格式文件中的結構是一個很大的壯舉。
由於我們需要這些信息,我們也會在這里分享,以幫助他人尋求知識和理解;)
ASN.1和DER編碼
在RSA,PKCS#1和SSL / TLS社區內,ASN.1的可分辨編碼規則(DER)編碼用於以便攜式格式表示密鑰,證書等。盡管ASN.1不是最容易理解的表示格式並且帶來了很多復雜性,但它確實有其優點。證書或密鑰信息存儲在ASN.1的二進制DER中,提供RSA,SSL和TLS的應用程序應處理DER編碼以讀取信息。
PEM文件
由於DER編碼導致編碼數據的真正二進制表示,因此設計了一種格式,以便能夠以可打印字符的編碼方式發送這些格式,以便您可以實際郵寄這些內容。我現在關注的格式是PEM格式。
我們將看到的大多數PEM格式的文件是由OpenSSL在生成或導出RSA私鑰或公鑰和X509證書時生成的。
本質上,PEM文件只是DER編碼數據的base64編碼版本。為了區分外部DER編碼字符串中的數據類型,數據周圍存在頁眉和頁腳。PEM編碼文件的示例是:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMYfnvWtC8Id5bPKae5yXSxQTt
+Zpul6AnnZWfI2TtIarvjHBFUtXRo96y7hoL4VWOPKGCsRqMFDkrbeUjRrx8iL91
4/srnyf6sh9c8Zk04xEOpK1ypvBz+Ks4uZObtjnnitf0NBGdjMKxveTq+VE7BWUI
yQjtQ8mbDOsiLLvh7wIDAQAB
-----END PUBLIC KEY-----
第一行和最后一行表示內部應該預期的DER格式。里面的數據是DER編碼信息的base64編碼版本。
格式
所以這一切都很好。但是在每個不同的文件中你應該期待什么結構?請看下面的不同格式的解釋。
RSA公鑰文件(PKCS#1)
RSA公鑰PEM文件特定於RSA密鑰。
它以標簽開頭和結尾:
-----BEGIN RSA PUBLIC KEY-----
BASE64 ENCODED DATA
-----END RSA PUBLIC KEY-----
在base64編碼數據中,存在以下DER結構:
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER -- e
}
公鑰文件(PKCS#8)
由於RSA不是專門用於X509和SSL / TLS,因此PKCS#8形式提供了更通用的密鑰格式,它標識了公鑰的類型並包含相關數據。
它以標簽開頭和結尾:
-----BEGIN PUBLIC KEY-----
BASE64 ENCODED DATA
-----END PUBLIC KEY-----
在base64編碼數據中,存在以下DER結構:
PublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
PublicKey BIT STRING
}
AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL
}
因此,對於RSA公鑰,OID是1.2.840.113549.1.1.1,並且有一個RSAPublicKey作為PublicKey密鑰數據bitstring。
RSA私鑰文件(PKCS#1)
RSA私鑰PEM文件特定於RSA密鑰。
它以標簽開頭和結尾:
-----BEGIN RSA PRIVATE KEY-----
BASE64 ENCODED DATA
-----END RSA PRIVATE KEY-----
在base64編碼數據中,存在以下DER結構:
RSAPrivateKey ::= SEQUENCE {
version Version,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
}
私鑰文件(PKCS#8)
由於RSA不是專門用於X509和SSL / TLS,因此PKCS#8形式的更通用密鑰格式可用於標識私鑰的類型並包含相關數據。
未加密的PKCS#8編碼數據以標簽開頭和結尾:
-----BEGIN PRIVATE KEY-----
BASE64 ENCODED DATA
-----END PRIVATE KEY-----
在base64編碼數據中,存在以下DER結構:
PrivateKeyInfo ::= SEQUENCE {
version Version,
algorithm AlgorithmIdentifier,
PrivateKey OCTET STRING
}
AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL
}
因此對於RSA私鑰,OID是1.2.840.113549.1.1.1並且存在RSAPrivateKey作為PrivateKey密鑰數據八位字節串。
加密的PKCS#8編碼數據以標簽開頭和結尾:
-----BEGIN ENCRYPTED PRIVATE KEY-----
BASE64 ENCODED DATA
-----END ENCRYPTED PRIVATE KEY-----
在base64編碼數據中,存在以下DER結構:
EncryptedPrivateKeyInfo ::= SEQUENCE {
encryptionAlgorithm EncryptionAlgorithmIdentifier,
encryptedData EncryptedData
}
EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
EncryptedData ::= OCTET STRING
EncryptedData OCTET STRING是PKCS#8 PrivateKeyInfo(見上文)。
這有幫助嗎?