1. 程式人生 > >【IoT】加密與安全:非對稱加密演算法 ECC 公私鑰 DER 編碼示例解析

【IoT】加密與安全:非對稱加密演算法 ECC 公私鑰 DER 編碼示例解析

加密演算法的公私鑰一般使用 ASN.1 標準的 DER 編碼格式,本文先介紹 ASN.1( ASN.1 基礎) 相關的基礎知識,最後給出 ECC 公鑰 DER 格式的示例便於更好理解 DER 編碼。

1、ASN.1 簡介

ASN.1( Abstract Syntax Notation One ) 是一種介面描述語言,提供了一種平臺無關的描述資料結構的方式。

ASN.1 是 ITU-T、ISO、以及 IEC 的標準,廣泛應用於電信和計算機網路領域,尤其是密碼學領域。

ASN.1 可以通過 schema 來定義資料結構,提供跨平臺的資料序列化和反序列化能力。有大量的 RFC 文件使用 ASN.1 定義協議、資料格式等。比如 https 所使用的 X.509 證書結構,就是使用 ASN.1 定義的。

ASN.1定義了若干基礎的資料型別和結構型別:

我們可以使用這些基礎型別來描述我們自己的資料結構:

 FooQuestion ::= SEQUENCE {
     trackingNumber INTEGER,
     question       IA5String
}

如上定義了一個名為 FooQuestion 的資料結構。它是一個 SEQUENCE 結構,包含了一個 INTEGER 型別,一個 IA5String
型別。

具體的 FooQuestion 可以描述為:

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

用 ASN.1 定義的資料結構例項,可以序列化為二進位制的 BER、文字型別的 JSON、XML 等。

1.1、Object Identifier 淺析

Object Identifier (OID) 是一項由ITU和ISO/IEC制定的標準,用來唯一標識物件、概念,或者其它任何具有全球唯一特性的東西。

一個OID表現為用.分隔的一串數字,比如橢圓曲線secp256r1的OID是這樣:

1.2.840.10045.3.1.7

其每個數字的含義如下:

iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7

OID是全域性統一分配的,全部的OID可以看做一棵多叉樹,每一個有效的OID表現為樹上的一個節點。當前所有的OID可以在

這裡找到。

OID是ASN.1的基本型別。

1.2、BER & DER 淺析

Basic Encoding Rules (BER) 是一種自描述的ASN.1資料結構的二進位制編碼格式。每一個編碼後的BER資料依次由資料型別標識(Type identifier),長度描述(Length description), 實際資料(actual Value)排列而成,即BER是一種二進位制TLV編碼。TLV編碼的一個好處,是資料的解析者不需要讀取完整的資料,僅從一個不完整的資料流就可以開始解析。

Distinguished Encoding Rules (DER)是BER的子集,主要是消除了BER的一些不確定性的編碼規則,比如在BER中Boolean型別true的value位元組,可以為任何小於255大於0的整數,而在DER中,value位元組只能為255。DER的這種確定性,保證了一個ASN.1資料結構,在編碼為為DER後,只會有一種正確的結果。這使得DER更適合用在數字簽名領域,比如X.509中廣泛使用了DER。

關於各種ASN.1資料型別是如何被編碼為DER,可以在這裡找到詳盡的解釋。

如果有DER資料需要解析檢視內容,這裡有一個很方便的線上工具

用DER來編碼ASN.1小節中自定義的myQuestion如下:

0x30 0x13 0x02 0x01 0x05 0x16 0x0e 0x41 0x6e 0x79 0x62 0x6f 064 0x79 0x20 0x74 0x68 0x65 0x72 0x65 0x3f
---  ---  ---  ---  ---  ---  ---  --------------------------------------------------------------------
 ^    ^    ^    ^    ^    ^    ^                                   ^
 |    |    |    |    |    |    |                                   |
 |    |    | INTEGER | IA5STRING                                   |
 |    |    | LEN=1   | TAG     |                                   |
 |    |    |         |         |                                   |
 |    | INTEGER   INTEGER   IA5STRING                          IA5STRING
 |    | TAG       VALUE(5)  LEN=14                             VALUE("Anybody there?")
 |    |
 |    |  ----------------------------------------------------------------------------------------------
 |    |                                              ^
 |  SEQUENCE LEN=19                                  |
 |                                                   |
SEQUENCE TAG                                  SEQUENCE VALUE

1.3、PEM 淺析

DER格式是ASN.1資料的二進位制編碼,計算機處理方便,但不利於人類處理,比如不方便直接在郵件正文中貼上傳送。PEM是DER格式的BASE64編碼。除此之外,PEM在DER的BASE64前後各增加了一行,用來標識資料內容。示例如下:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMYfnvWtC8Id5bPKae5yXSxQTt
+Zpul6AnnZWfI2TtIarvjHBFUtXRo96y7hoL4VWOPKGCsRqMFDkrbeUjRrx8iL91
4/srnyf6sh9c8Zk04xEOpK1ypvBz+Ks4uZObtjnnitf0NBGdjMKxveTq+VE7BWUI
yQjtQ8mbDOsiLLvh7wIDAQAB
-----END PUBLIC KEY-----

1.4、X.509 淺析

X.509是一項描述公鑰證書結構的標準,廣泛使用在HTTPS協議中,定義在RFC 3280

X.509使用ASN.1來描述公鑰證書的結構,通常編碼為DER格式,也可以進一步BASE64編碼為可列印的PEM格式。V3版本的X.509結構如下:

    Certificate  ::=  SEQUENCE  {
        tbsCertificate       TBSCertificate,
        signatureAlgorithm   AlgorithmIdentifier,
        signatureValue       BIT STRING  }

    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  }

1.5、SubjectPublicKeyInfo 介紹

如上一節所示,SubjectPublicKeyInfo是公鑰證書格式X.509的組成部分。SubjectPublicKeyInfo結構使用ASN.1描述,其中使用了橢圓曲線公私鑰加密演算法的SubjectPublicKeyInfo結構定義在RFC 5480

其結構如下:

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

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

可以看到AlgorithmIdentifier也是一個SEQUENCE,其parameters部分取決於algorithm的具體取值。

對不限制的ECC公鑰使用演算法的場景,algorithm取值:

1.2.840.10045.2.1

即: iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1

在該種類場景下,parameters的定義如下:

    ECParameters ::= CHOICE {
        namedCurve         OBJECT IDENTIFIER
    }

即parameters指定了ECC公鑰所使用的橢圓曲線。其可選的值有:

    secp192r1 OBJECT IDENTIFIER ::= {
        iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 }

    sect163k1 OBJECT IDENTIFIER ::= {
        iso(1) identified-organization(3) certicom(132) curve(0) 1 }

    sect163r2 OBJECT IDENTIFIER ::= {
        iso(1) identified-organization(3) certicom(132) curve(0) 15 }

    secp224r1 OBJECT IDENTIFIER ::= {
        iso(1) identified-organization(3) certicom(132) curve(0) 33 }

    sect233k1 OBJECT IDENTIFIER ::= {
        iso(1) identified-organization(3) certicom(132) curve(0) 26 }

    sect233r1 OBJECT IDENTIFIER ::= {
        iso(1) identified-organization(3) certicom(132) curve(0) 27 }

    secp256r1 OBJECT IDENTIFIER ::= {
        iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 }

    sect283k1 OBJECT IDENTIFIER ::= {
        iso(1) identified-organization(3) certicom(132) curve(0) 16 }

    sect283r1 OBJECT IDENTIFIER ::= {
        iso(1) identified-organization(3) certicom(132) curve(0) 17 }

    secp384r1 OBJECT IDENTIFIER ::= {
        iso(1) identified-organization(3) certicom(132) curve(0) 34 }

    sect409k1 OBJECT IDENTIFIER ::= {
        iso(1) identified-organization(3) certicom(132) curve(0) 36 }

    sect409r1 OBJECT IDENTIFIER ::= {
        iso(1) identified-organization(3) certicom(132) curve(0) 37 }

    secp521r1 OBJECT IDENTIFIER ::= {
        iso(1) identified-organization(3) certicom(132) curve(0) 35 }

    sect571k1 OBJECT IDENTIFIER ::= {
        iso(1) identified-organization(3) certicom(132) curve(0) 38 }

    sect571r1 OBJECT IDENTIFIER ::= {
        iso(1) identified-organization(3) certicom(132) curve(0) 39 }

algorithm確定後,再來看下subjectPublicKey,對ECC公鑰來講,subjectPublicKey就是ECPoint:

    ECPoint ::= OCTET STRING

是長度為65位元組的OCTET STRING,其中第一個位元組代表ECPoint是否經過壓縮,如果為0x04,代表沒有壓縮。剩下的64個位元組,前32個位元組,表示ECPoint的X座標,後32個位元組表示ECPoint的Y座標。

OCTET STRING型別的ECPoint在轉換為BIT STRING型別的subjectPublicKey時,按照大端位元組序轉換。

2、ECC 公鑰 DER 示例

我們以一個DER編碼的ECC公鑰為例,詳細剖析一下X.509 ECC公鑰的格式。公鑰內容如下:

0x30 0x59 0x30 0x13 0x06 0x07 
0x2a 0x86 0x48 0xce 0x3d 0x02 
0x01 0x06 0x08 0x2a 0x86 0x48 
0xce 0x3d 0x03 0x01 0x07 0x03 
0x42 0x00 0x04 0x13 0x32 0x8e 
0x0c 0x11 0x8a 0x70 0x1a 0x9e 
0x18 0xa3 0xa9 0xa5 0x65 0xd8 
0x41 0x68 0xce 0x2f 0x5b 0x11 
0x94 0x57 0xec 0xe3 0x67 0x76 
0x4a 0x3f 0xb9 0xec 0xd1 0x15 
0xd0 0xf9 0x56 0x8b 0x15 0xe6 
0x06 0x2d 0x72 0xa9 0x45 0x56 
0x99 0xb0 0x9b 0xb5 0x30 0x90 
0x8d 0x2e 0x31 0x0e 0x95 0x68 
0xcc 0xcc 0x19 0x5c 0x65 0x53 
0xba

通過前面的介紹,我們已經知道這是一個ASN.1格式的SubjectPublicKeyInfo的DER編碼,是一個TLV型別的二進位制資料。現在我們逐層解析下:

0x30 (SEQUENCE TAG: SubjectPublicKeyInfo) 0x59 (SEQUENCE LEN=89)
        0x30 (SEQUENCE TAG: AlgorithmIdentifier) 0x13 (SEQUENCE LEN=19)
                0x06 (OID TAG: Algorithm) 0x07 (OID LEN=7)
                        0x2a 0x86 0x48 0xce 0x3d 0x02 0x01 (OID VALUE="1.2.840.10045.2.1": ecPublicKey/Unrestricted Algorithm Identifier)
                0x06 (OID TAG: ECParameters:NamedCurve) 0x08 (OID LEN=8)
                        0x2a 0x86 0x48 0xce 0x3d 0x03 0x01 0x07 (OID VALUE="1.2.840.10045.3.1.7": Secp256r1/prime256v1)
        0x03 (BIT STRING TAG: SubjectPublicKey:ECPoint) 0x42 (BIT STRING LEN=66) 0x00 (填充bit數量為0)
                0x04 (未壓縮的ECPoint)
                0x13 0x32 0x8e 0x0c 0x11 0x8a 0x70 0x1a 0x9e 0x18 0xa3 0xa9 0xa5 0x65 0xd8 0x41 0x68 0xce 0x2f 0x5b 0x11 0x94 0x57 0xec 0xe3 0x67 0x76 0x4a 0x3f 0xb9 0xec 0xd1 (ECPoint:X)
                0x15 0xd0 0xf9 0x56 0x8b 0x15 0xe6 0x06 0x2d 0x72 0xa9 0x45 0x56 0x99 0xb0 0x9b 0xb5 0x30 0x90 0x8d 0x2e 0x31 0x0e 0x95 0x68 0xcc 0xcc 0x19 0x5c 0x65 0x53 0xba (ECPoint:Y)

refer: