密碼學基礎3:密鑰文件格式完全解析 1 ASN.1 2 編碼規則 3 密鑰格式解析 4 總結 參考資料

這是密碼學筆記第三篇。之前兩篇分析了 RSA 算法和橢圓曲線密碼學的基本原理,從中可以知道 RSA 算法的本質是大整數質數因子分解,橢圓曲線密碼學的本質是曲線上的打點,樸素的原理後面處處閃耀着數學之光。從理論到實踐,這篇文章來解析下日常使用的密鑰文件格式。

文章主要解決下面幾個問題:

  • 使用 opensslssh-keygen 生成的 RSA 和 ECC 的密鑰文件裏面存了什麼內容,用的什麼編碼規則?
  • 有些 RSA 私鑰頭部是 -----BEGIN RSA PRIVATE KEY-----,而有些又是 -----BEGIN PRIVATE KEY-----,它們存儲的內容有什麼區別?
  • 使用 openssl 生成的公鑰跟 ssh-keygen 生成的密鑰對中的公鑰格式不一樣,它們有什麼區別?
  • opensslssh-keygen 都支持輸入密碼對私鑰加密以增強安全性,它們加密方式分別是什麼?有什麼不同之處嗎?

1 ASN.1

ASN.1(Abstract Syntax Notation One) 是一種數據描述語言,跟 protobuf 和 Thrift 這些接口描述語言類似,它通過模塊(module) 來描述數據結構。ASN.1 最早用於電信領域,後來在計算機密碼學中也有廣泛應用。

ASN.1 定義了一些數據類型來描述數據結構,包括基礎類型(如整數類型 INTEGER,布爾類型 BOOLEAN,字符串類型 OCTET STRING,BIT STRING)和結構化類型(如結構體類型 SEQUENCE,列表類型 SEQUENCE OF 等),完整類型列表見 [ASN.1 Types]。類型通常都有個類型標籤,其中類型標籤分爲通用的、應用自定義的、上下文特定的、以及私有的 4 種類型。其中通用的類型標籤如下:

Type Tag Number
INTEGER 0x02
BIT STRING 0x03
OCTET STRING 0x04
NULL 0x05
OBJECT IDENTIFIER 0x06
SEQUENCE and SEQUENCE OF 0x10
IA5String 0x16
UTCTime 0x17

下面用ASN.1定義了一個名爲 FooProtocol 的模塊,其中包含一個結構體類型字段 FooQuestion。結構體 FooQuestion 包括一個整形字段 id 和一個字符串類型字段 question(IA5String 是不包括控制字符的字符串類型)。

FooProtocol DEFINITIONS ::= BEGIN
    FooQuestion ::= SEQUENCE {
        id INTEGER,
        question       IA5String
    }
END

ASN.1 只是描述了數據結構,並沒有指定怎麼編碼數據。因此,出現了多種編碼規則以方便數據在網絡上傳輸和不同終端間交互。比較常見的有 XER, JER, BER, DER等。如待編碼的數據如下:

myQuestion FooQuestion ::= SEQUENCE {
    id 5,
    question "Anybody there?"
}

使用各編碼規則編碼結果如下,其中 XER 和 JER 不用多說,BER 和 DER 是最常見的密鑰文件編碼規則,下一節詳細分析。

                    XER(XML Encoding Rules)
            <FooQuestion>
                <id>5</id>
                <question>Anybody there?</question>
            </FooQuestion>

                    JER(JSON Encoding Rules)
    { "id" : 5, "question" : "Anybody there?" }
        
                    BER(Basic Encoding Rules)
        30 13 02 01 05 16 0e 41 6e 79 62 6f 64 79 20 74 68 65 72 65 3f

                    DER(Distinguished Encoding Rules)
        30 13 02 01 05 16 0e 41 6e 79 62 6f 64 79 20 74 68 65 72 65 3f

2 編碼規則

前文提到 ASN.1 只是定義了數據結構,並未規定具體的編碼方式,與之對應的有多種編碼規則。ASN.1 與特定的編碼規則一起通過使用獨立於計算機架構和編程語言的方法來描述數據結構,爲結構化數據的表示、編碼、傳輸、解碼提供了便利。本節主要介紹密鑰和證書中常見的編碼規則 BER,DER,以及由 DER 衍生出的密鑰文件格式 PEM。

BER (Basic Encoding Rules)

BER 是基礎編碼規則,編碼結構包括類型標誌、長度,值以及結束符(可選),每個字段以 8bit 即字節進行分割。

----------------------------------------------------
| Identifier | Length | Contents | End-of-contents |
|   octets   | octets |  octets  |      octets     |
----------------------------------------------------

Identifier: 類型標誌,就是ASN.1 規定的類型,只是除了標籤號(tag number)外,還加了 3 位,第 7,8 位用於區分是通用的標籤類型還是其他標籤類型, 第 6 位 用於區分是基礎類型還是結構化類型。Identifier 結構如下,後面我們會看到密鑰中的結構體類型 SEQUENCE 的 Identifier 爲 0x30,即是由這個格式而來(0011000)。

---------------------------------
| 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
---------------------------------
|Class  |P/C| Tag Number        |
---------------------------------
  • Class:如果是通用類型標籤則爲 00,應用自定義的類型標籤則爲 01,上下文特定類型標籤 10,私有類型標籤 11。
  • P/C:如果是基礎類型,則爲 0,結構化類型爲 1。
  • Tag Number:就是 ASN.1 中定義的數據類型標籤號。

Length: 分三種情況,

  • 1)數據長度 < 128:則 Length 的 8bit首位爲0,其他7位表示數據長度。
  • 2)數據長度 >= 128:則 Length 的第一個8bit爲 0x8?,其中 ? 是後面跟的是長度。比如 0x81 表示後面一個字節爲長度,如果是 0x82 則表示後面兩個字節爲長度,以此類推。
  • 3)如果數據長度未知,則 Length=0x80,並增加 End-of-contents=00 00 結束標記。

Contents & End-of-contents: 數據內容。對於未知數據長度的數據類型,纔有 End-of-contents,爲00 00

實例:

  • 使用 OCTET STRING 編碼字符串 Hello,爲 04 05 48 65 6C 6C 6F,即類型爲 04,長度爲 05,內容爲 0x48 65 6C 6C 6F,即 Hello 的 ASCII 碼。
  • 使用 INTEGER 編碼整數 129,爲 02 81 81
  • 結構化類型是包含了多個數據類型的複合類型,後面詳細分析。

DER (Distinguished Encoding Rules)

DER 是典型的 Tag-Length-Value(TLV) 編碼方式,是 PKCS 密鑰體系常用的編碼。
DER 是 BER 的子集,編碼規則幾乎一樣,不過去掉了 BER 的一些靈活性,多了幾個限制:

  • 如果數據長度在 0-127 之間,則 Length 必須使用第 1 種編碼方式。
  • 如果數據長度 >= 128,則 Length 必須使用第 2 種編碼方式,且 Length 必須用最少的字節編碼,如果能用 2 字節的則不能用 3 字節。
  • 數據要用明確長度的編碼方式,不支持 Length 的第3種編碼即未知數據長度+結束標記的方式。

注意:ASN.1 規定整型 INTEGER 需要支持正整數、負整數和零。BER/DER 使用大端模式存儲 INTEGER,並通過最高位來編碼正負數(最高位0爲正數,1爲負數)。 如果密鑰參數值最高位爲 1,則 BER/DER 編碼會在參數前額外加 0x00 以表示正數,這也就是爲什麼有時候密鑰參數前面會多出1字節 0x00 的原因。

PEM(Privacy Enhanced Mail): 因爲 DER 編碼是二進制數據,早期的 Email 不能發送附件,也不方便直接傳輸二進制數據([原因]),因此密鑰文件通常會在 DER 編碼基礎上進行 Base64 編碼,這就是經常看到的密鑰文件格式 PEM。PEM 最早是用來增強郵件安全性的,不過沒有被廣泛接受,最後卻是在密碼學中得到了發揚光大,如 openssl 和 ssh-keygen 工具生成的公私鑰文件默認都採用 PEM 格式。需要注意的是,PEM 本身不是 ASN.1 的編碼規則,它只是 Base64-encoded DER

3 密鑰格式解析

ASN.1 編碼規則只定義了數據編碼方式,但是並沒有賦予數據意義。公鑰密碼學標準 PKCS (Public Key Cryptography Standards) 和公鑰基礎設施 PKIX(Public-Key Infrastructure X.509) 等使用 ASN.1 的類型定義密鑰和證書的格式和編碼,以描述公私鑰和證書屬性。 需要注意,PKCS 雖然名字是公鑰密碼學標準,它其實也包括私鑰格式標準。 這兩個標準的內容浩瀚如煙,本節只分析常見幾種密鑰相關的部分。

3.1 PKCS #1

PKCS #1 是 RSA Cryptography Specifications,即 RSA 密碼學規範,它在 [rfc8017] 中有詳細說明,定義了 RSA 密鑰文件的格式和編碼方式,以及加解密、簽名、填充的基礎算法。

RSA 密鑰格式

RSA 公私鑰的 ASN.1 類型定義如下,根據類型定義和數據編碼,就能解析出 RSA 公私鑰中的參數了(參數含義請參考我之前的《RSA算法原理解析》一文)。


 RSAPublicKey ::= SEQUENCE {
        modulus           INTEGER,  -- n
        publicExponent    INTEGER   -- e
 }
         
 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
}

使用 openssl 生成的一對 RSA 公私鑰 (示例爲方便展示,用的 1024 位密鑰,實際中請使用 2048 位以上)

$ openssl genrsa -out prikey.p1 1024
$ openssl rsa -in prikey.p1 -pubout -RSAPublicKey_out > pubkey.p1

PKCS#1 格式解析如下:公鑰的 SEQUENCE 包括 RSA 公鑰參數 n 和 e 兩個屬性。RSA 私鑰則首先是版本號 0,然後是 RSA 私鑰的 8 個參數。

加密私鑰

可以對 PKCS#1 的私鑰進行加密,如 ssh-keygen 可以指定 passphrase (測試的密碼是 testtest)加密 RSA 私鑰,加密後的私鑰 enc_prikey.p1 格式如下:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,8C2A8D6593F411D7336B842037B5200B

EncryptedRSAPrivateKey
-----END RSA PRIVATE KEY-----

DEK-Info 裏面指明瞭加密算法是 AES-128-CBC,IV 是 8C2A8D6593F411D7336B842037B5200B,AES加密的實際密碼=md5(設定密碼 + IV的前8個字節)。可以使用 openssl aes-128-cbc 驗證加密結果是否與 EncryptedRSAPrivateKey 一致。

$ tail -n +2 prikey.p1 | grep -v 'END RSA' | base64 -d | 
openssl aes-128-cbc -e -iv 8C2A8D6593F411D7336B842037B5200B -K $(python -c "exec(\"import hashlib\\nprint hashlib.md5(bytearray('testtest') + bytearray.fromhex('8C2A8D6593F411D7')).hexdigest()\")") | base64

3.2 PKCS #8

PKCS#8 是 Private-Key Information Syntax Standard,即私鑰格式相關的標準,它不像 PKCS#1 只支持 RSA,而是支持各種類型的私鑰。PKCS#8 私鑰文件格式中首尾並未說明私鑰算法類型,算法類型在數據中標識。PKCS#8 中的私鑰也支持加密。

未加密私鑰格式

未加密私鑰格式的 ASN.1 類型定義如下(參見 [rfc5958] ):

    OneAsymmetricKey ::= SEQUENCE {
        version                   Version,
        privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
        privateKey                PrivateKey,
        attributes            [0] Attributes OPTIONAL,
       ...,
       [[2: publicKey        [1] PublicKey OPTIONAL ]],
       ...}

        Version ::= INTEGER  # 版本號。
    
        PrivateKeyAlgorithmIdentifier ::= SEQUENCE  { # 密鑰算法標識
                algorithm               OBJECT IDENTIFIER,
                parameters              ANY DEFINED BY algorithm OPTIONAL  }
    
        PrivateKey ::= OCTET STRING # 不同類型的私鑰格式不同,比如 RSA 的是 RSAPrivateKey類型,而 ECC 的是 ECPrivateKey 類型。
            
        Attributes ::= SET OF Attribute # 跟公鑰相關的屬性,比如證書什麼的,在公私鑰中通常爲空。
        
        PublicKey ::= BIT STRING # 不同類型密鑰包含的公鑰內容也不同。

RSA 私鑰格式

可以使用 openssl 將 PKCS#1 格式的私鑰 prikey.p1 轉換成 PKCS#8 格式的 prikey.p8,如下:

$ openssl pkcs8 -in prikey.p1 -topk8 -out prikey.p8 -nocrypt

私鑰格式解析如下:

  • version:版本號,目前值爲 0。
  • privateKeyAlgorithm:私鑰算法, rsaEncryptionOBJECT IDENTIFIER1.2.840.113549.1.1.1,具體含義參見 [這裏]
  • privateKey:私鑰,OCTET STRING 類型,裏面其實封裝了一個 RSAPrivateKey 類型,跟 PKCS#1 一樣。
  • attributes 和 publicKey 爲空。

ECC 私鑰格式

橢圓曲線類型的私鑰格式在 rfc5915 中定義如下:

ECPrivateKey ::= SEQUENCE {
     version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
     privateKey     OCTET STRING,
     parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
     publicKey  [1] BIT STRING OPTIONAL
}

使用 openssl 創建一個 PKCS#8 格式的 ecc 密鑰,採用 prime256v1 曲線:

# 生成傳統格式的 ECC 私鑰,類似 PKCS#1 那樣,只包含 privateKey,密鑰類型在頭部 -----BEGIN EC PRIVATE KEY----- 標識,橢圓曲線在 parameters 標識。
$ openssl ecparam -name prime256v1 -genkey -noout -out ecc_prikey.tradfile

# 轉換爲 PKCS#8 格式
$ openssl pkcs8 -topk8 -in ecc_prikey.tradfile -out ecc_prikey.p8 -nocrypt
$ cat ecc_prikey.p8
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgMbahscIGpSZ6NULI
iQ/pTI9ZcvFdXKtjN1bAGO2bxvahRANCAATwq1k9rx/8neP8MqVR7UuJ98bLFsU5
jpueH0ougZNWrsKUki0cgKDGrb3C8Q2NMRO336ve22Xk674lk/ZDHkAV
-----END PRIVATE KEY-----

ASN.1 格式解析如下:

  • 前面部分是算法標識 1.2.840.10045.2.1(ecPublicKey) 和 1.2.840.10045.3.1.7 (prime256v1)
  • 後面是私鑰信息,其中包括了版本號 1,OCTET STRING 類型私鑰 31B6A1...F6,BIT STRING 類型的公鑰 0000 0100 1111 0000...

當然通過 openssl 可以直接解析出公私鑰和曲線類型,如下:

$ openssl ec -in ecc_prikey.p8 -noout -text
read EC key
Private-Key: (256 bit)
priv:
    31:b6:a1:b1:c2:06:a5:26:7a:35:42:c8:89:0f:e9:
    4c:8f:59:72:f1:5d:5c:ab:63:37:56:c0:18:ed:9b:
    c6:f6
pub:
    04:f0:ab:59:3d:af:1f:fc:9d:e3:fc:32:a5:51:ed:
    4b:89:f7:c6:cb:16:c5:39:8e:9b:9e:1f:4a:2e:81:
    93:56:ae:c2:94:92:2d:1c:80:a0:c6:ad:bd:c2:f1:
    0d:8d:31:13:b7:df:ab:de:db:65:e4:eb:be:25:93:
    f6:43:1e:40:15
ASN1 OID: prime256v1
NIST CURVE: P-256

在上一篇《橢圓曲線密碼學原理分析》一文知道,橢圓曲線的密鑰生成其實就是一個公式 P = nG,n 就是私鑰,G 是基點,P 是公鑰。注意到這裏公鑰的第一個字節 04 表示公鑰格式是 uncompressed format,即非壓縮格式,也就是把點的 X 和 Y 座標合到一起作爲公鑰。壓縮格式就是隻用 X 座標或者 Y 座標中的一個,另一個座標根據曲線方程可以求得([rfc5480] 有詳細說明)。可以通過 libnum 庫來驗證下公私鑰的準確性。

$ cat ecc.py 
from libnum.ecc import Curve
curve = Curve(
        a=0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc,
        b=0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b,
        p=0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff,
        g = (0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296,
            0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5)
)

pri = 0x31b6a1b1c206a5267a3542c8890fe94c8f5972f15d5cab633756c018ed9bc6f6
pub = curve.power(curve.g, pri)
print hex(pub[0]), hex(pub[1])
$ python ecc.py 
('0xf0ab593daf1ffc9de3fc32a551ed4b89f7c6cb16c5398e9b9e1f4a2e819356aeL', 
'0xc294922d1c80a0c6adbdc2f10d8d3113b7dfabdedb65e4ebbe2593f6431e4015L')

加密私鑰格式

PKCS#8 裏面對私鑰加密提供了 PBES2(Password-Based Encryption Scheme 2)加密模式支持。通過 PBKDF2(Password-Based Key Derivation Function 2) 對原始密碼進行多次哈希處理作爲加密密碼以增強破解難度,然後用對稱加密算法 AES 或者 DES 對私鑰進行加密。

PBKDF2 是一種 CPU 密集型算法,但是如果使用 GPU 陣列或者 FPGA 來破解還是相對容易。在密碼存儲中現在更傾向於用 Bcrypt,它不僅是 CPU 運算密集,而且是內存密集,破解難度會更高一些。不過總的來說, PBKDF2 比 ssh-keygen 的 md5 方式生存密碼安全性會高很多。

PKCS#8 加密類型私鑰的 ASN.1 類型定義如下:

EncryptedPrivateKeyInfo ::= SEQUENCE {
     encryptionAlgorithm  EncryptionAlgorithmIdentifier,
     encryptedData        EncryptedData }

     EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
                                        { CONTENT-ENCRYPTION,
                                          { KeyEncryptionAlgorithms } }

     EncryptedData ::= OCTET STRING

使用 openssl 對 PKCS#8 格式的密鑰加密是很方便的,默認就支持(生成密鑰時不加 -nocrypt 參數即可)。加密後的 ecc_prikey.p8 格式解析如下:

  • 其中加密模式是 pkcs5PBES2,密鑰生成算法是 PBKDF2,參數 salt= E20EED9A112B7BFA,iteration=2048,哈希算法是 hmacWithSHA256
  • 對稱加密算法是 aes256-cbc,參數 iv=27579581D081AEDA083889370232AD1A
  • 最後一行 11E9C5C2.... 就是加密私鑰 encryptedData。

加密過程解析:

  • 先使用密鑰生成算法 PBKDF2 生成加密密碼,python 可以用 backports.pbkdf2 模塊。
import os, binascii
from backports.pbkdf2 import pbkdf2_hmac

salt = binascii.unhexlify('E20EED9A112B7BFA')
passwd = b"testtest"
key = pbkdf2_hmac("sha256", passwd, salt, 2048, 32)
print("Derived key:", binascii.hexlify(key))

# 輸出: ('Derived key:', 'bf48084fd98fcbacd8e024166efb7232c897282fe7e4ff836db3f3d81e32ede9')
  • 然後使用 openssl 的 aes256-cbc 加密原私鑰,可以驗證跟 encryptedData 是一樣的。
$ tail -n +2 ecc_prikey.p8 | grep -v 'END '| base64 -d | 
openssl aes-256-cbc -e -iv 27579581D081AEDA083889370232AD1A -K bf48084fd98fcbacd8e024166efb7232c897282fe7e4ff836db3f3d81e32ede9 | hexdump -C

00000000  11 e9 c5 c2 4c c3 2d bb  fa 84 b9 fb db f1 d1 ff  |....L.-.........|
00000010  f0 6a 5b fa c3 a6 88 cd  02 4c ac 52 84 f4 cb c1  |.j[......L.R....|
......
00000080  8f 72 96 7a 58 aa 1f 5a  6f c1 bf dc 43 1a 46 26  |.r.zX..Zo...C.F&|

3.3 PKIX

前面提到 PKCS#8 定義了通用的私鑰格式支持各類私鑰,在 PKIX ([rfc5280]) 中也定義了通用的公鑰格式。其中包括算法標識和公鑰內容,算法標識 AlgorithmIdentifier 與前面私鑰中的 PrivateAlgorithmIdentifier 是類似的。

SubjectPublicKeyInfo  ::=  SEQUENCE  {
        algorithm         AlgorithmIdentifier,
        subjectPublicKey  BIT STRING }

        AlgorithmIdentifier  ::=  SEQUENCE  {
                algorithm               OBJECT IDENTIFIER,
                parameters              ANY DEFINED BY algorithm OPTIONAL  
        }

將之前的 PKCS#1 格式的 RSA 公鑰轉換成 PKIX 的格式:

$ openssl rsa -RSAPublicKey_in -in ../pk1/pubkey.p1 -pubout > pubkey.pkix

PKIX 格式的公鑰解析如下,包括公鑰算法 rsaEncryption 和 RSA 公鑰參數 n 和 e。

3.4 openssl 和 ssh-keygen 生成公鑰格式區別

相信大家會發現 ssh-keygen -t rsa 生成的 RSA 密鑰對中公鑰格式跟 PKCS#1 和 PKIX 中的都不一樣。ssh-keygen 生成的公鑰 id_rsa.pub 如下所示:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC+gCiA//vUMu/2dYj9oGUpY2TCw5/AtkfI2cWvl7hOkliQd7uI61gE9BV5w+Ib+HnjAB9lFYS4A8rlpRlkH9a+mCN2K/Oh5dhoonxat4qeHB5XDvmImUfdOGayT5l176KWP4ftGJt+8ygRpo05zcbuBrd/KxFZ7KDiQyXRvRv9mw== vagrant@stretch

這是 openssh 使用的一種專屬格式:

[type-name] [base64-encoded-ssh-public-key] [comment]

其中 base64-encoded-ssh-public-key 並沒有使用 ASN.1 的數據類型定義和 DER 編碼,而是使用的 SSH 協議定義的格式(見 [rfc4251]),分爲 3 部分:

string    "ssh-rsa"
mpint     e
mpint     n

這裏的 string 類型和 mpint 類型在 rfc4251 中定義,其中 mpint是使用字符串的方式來存儲整數,它們都會在數據前先用4字節存儲數據長度。id_rsa.pub 解析後格式如下所示:

00 00 00 07  73 73 68 2d 72 73 61  | 長度 7,值 ssh-rsa|
00 00 00 03  01 00 01  | e 長度 3,值 0x010001 |
00 00 00 81  00 be 80 28 80 ff fb d4 |n 長度 127,值 0x00 be 80 28 80...|
......

也可以將 ssh-keygen 生成的公鑰轉換成 PKCS#1 的格式:

$ ssh-keygen -f id_rsa.pub -e -m pem > pubkey.p1

4 總結

PKCS 和 PKIX 使用 ASN.1 定義了密鑰的數據結構,並使用 DER 編碼規則編碼密鑰,最終使用 PEM (Base64-encoded DER) 格式將密鑰數據存儲在密鑰文件中。

PKCS#1 首部會標識密鑰算法類型,PKCS#8 則是在密鑰數據中有字段專門存儲密鑰算法。openssh 使用的公鑰格式是 SSH 協議中定義的,雖然參數值一樣,但是編碼方式與 PKCS 和 PKIX 標準都不同。

ssh-keygen 是對原始密碼和初始向量經過一個簡單規則 md5 後生成加密密碼,然後使用 aes128-cbc 對稱加密。而 openssl 則是對原始密碼採用 PBKDF2 算法生成加密密碼,然後使用 aes256-cbc 對稱加密,openssl 的加密方式更安全一些。

參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章