ASN1编码学习

为了解决高级语言中结构化数据在网络传输中的结构关系能送达目的地进行还原,出现了以下几种数据序列化的方法:ASN.1,XML,Json等。

ASN.1本身只定义了表示信息的抽象句法,但是没有限定其编码的方法,它与语言实现和物理标识无关。各种ASN.1编码规则提供了由ASN.1描述其抽象句法的数据的值的传送语法(具体表达)。标准的ASN.1编码规则有基本编码规则(BER,Basic Encoding Rules)、规范编码规则(CER,Canonical Encoding Rules)、唯一编码规则(DER,Distinguished Encoding Rules)、压缩编码规则(PER,Packed Encoding Rules)和XML编码规则(XER,XML EncodingRules)。

1.语法

Report ::=SEQUENCE {
 
author OCTETSTRING,
 
title OCTETSTRING,
 
body OCTETSTRING,
 
biblioBibliography
 
}

"Report"是由名字类型的信息组成的,而SEQUENCE表示消息是许多数据单元构成的,前三个数据单元的类型是OCTETSTRING,而最后一个数据类型见下面的ASN.1语法表示它的意义:

Bibliography ::=SEQUENCE {
 
author OCTETSTRING
 
title OCTETSTRING
 
publisher OCTETSTRING
 
year OCTETSTRING
 
}

ASN1还能定义一些结构类型

结构(SEQUENCE)

列表(SEQUENCE OF)

类型选择(CHOICE)

表示、编码、传输和解码数据结构的关键,是要有一种足够灵活的、适应各种类型应用的标准数据结构描写方法.为此,OSI中提出了一种标记法,叫做抽象语法标记1,简称为ASN.1,发送时将ASN.1数据结构编码成位流。

2.ASN1基本类型

3.ANS1模块定义

一般协议有一个或者多个模块组成,模块用来收集数据结构定义,模块必须以大写字母开头,能以一种全局指针的方式来引用,成为对象标识符,用花括号标识在名字之后。

 

4.BER基本规则

BER是ASN.1最早定义的编码规则。BER传输语法的格式一直是TLV三元组<Type,Length,Value>,也叫做<Tag,Length,Value>。TLV每个域都是一系列八位组,对于组合结构,其中V还可以是TLV三元组。

TLV三元组

BER编码规则与机器无关,而且可以支持各种不同的整数长度,能够很好的保存抽象语法结构,BER对布尔值的显示更加的友好,如对BOOLEAN类型显示为“TRUE”,或者“FAlSE”,而不是码字。

缺点是比较冗长。

5.CER与DER

在x.400和x.500中应用接力传递消息,会用到x.509数字签名,过程如下。

在x.400和x.500中应用接力传递消息,会用到x.509数字签名,过程如下。
发送方发送v的编码结果c1(v),同时发送其数字签名o(c1(v)),中继接受到消息后,解码得到v,保留签名,发送时重新编码发送结果为c2(v),接收方收到结果后解码得到v,同时对c2计算数字签名o(c2(v)),通过比较o(c1(v))和o(c2(v))是否相同来确定消息内容是否被修改。

如果这个过程用BER编码规则,比如存在布尔值“TRUE",两次编码过程c1和c2编码不同可能对TRUE的编码不通过,从而导致数字签名也不通过。

后来从BER派生两种编码规则,CER和DER,这两种规则是BER规范的特例,因此BER解码器能编解码这两种规范编码规则的传输语法,反之则不然。CER针对不定长格式,而DER针对定长格式。因此CER常用在需要传输大量的数据的情况下。

DER适合安全数据传输,特别是数字签名方面。在电子商务上面也有独特的优势,适合传输平均大小的数据。

 

6.X.509证书的结构

6.1 X.509证书基本部分

版本号。标识证书的版本(版本1、版本2或是版本3)。

序列号。标识证书的唯一整数,由证书颁发者分配的本证书的唯一标识符。

签名。用于签证书的算法标识,由对象标识符加上相关的参数组成,用于说明本证书所用的数字签名算法。例如,SHA-1和RSA的对象标识符就用来说明该数字签名是利用RSA对SHA-1杂凑加密。

颁发者。证书颁发者的可识别名(DN)。

有效期。证书有效期的时间段。本字段由”Not Before”和”Not After”两项组成,它们分别由UTC时间或一般的时间表示(在RFC2459中有详细的时间表示规则)。

主体。证书拥有者的可识别名,这个字段必须是非空的,除非你在证书扩展中有别名。

主体公钥信息。主体的公钥(以及算法标识符)。

颁发者唯一标识符。标识符—证书颁发者的唯一标识符,仅在版本2和版本3中有要求,属于可选项。

主体唯一标识符。证书拥有者的唯一标识符,仅在版本2和版本3中有要求,属于可选项。

6.2 X.509证书扩展部分

可选的标准和专用的扩展(仅在版本2和版本3中使用),扩展部分的元素都有这样的结构:

  Extension ::= SEQUENCE {
 
       extnID      OBJECT IDENTIFIER,
 
       critical    BOOLEAN DEFAULT FALSE,
 
       extnValue   OCTET STRING }
 
extnID:表示一个扩展元素的OID
 
critical:表示这个扩展元素是否极重要
 
extnValue:表示这个扩展元素的值,字符串类型。

发行者密钥标识符。证书所含密钥的唯一标识符,用来区分同一证书拥有者的多对密钥。

密钥使用。一个比特串,指明(限定)证书的公钥可以完成的功能或服务,如:证书签名、数据加密等。如果某一证书将 KeyUsage 扩展标记为“极重要”,而且设置为“keyCertSign”,则在 SSL 通信期间该证书出现时将被拒绝,因为该证书扩展表示相关私钥应只用于签写证书,而不应该用于 SSL。

CRL分布点。指明CRL的分布地点。

私钥的使用期。指明证书中与公钥相联系的私钥的使用期限,它也有Not Before和Not After组成。若此项不存在时,公私钥的使用期是一样的。

证书策略。由对象标识符和限定符组成,这些对象标识符说明证书的颁发和使用策略有关。

策略映射。表明两个CA域之间的一个或多个策略对象标识符的等价关系,仅在CA证书里存在。

主体别名。指出证书拥有者的别名,如电子邮件地址、IP地址等,别名是和DN绑定在一起的。

颁发者别名。指出证书颁发者的别名,如电子邮件地址、IP地址等,但颁发者的DN必须出现在证书的颁发者字段。

主体目录属性。指出证书拥有者的一系列属性。可以使用这一项来传递访问控制信息。

 

7. X.509证书ASN1描述

Certificate ::= SEQUENCE {
        tbsCertificate       TBSCertificate, -- 证书主体
        signatureAlgorithm   AlgorithmIdentifier, -- 证书签名算法标识
        signatureValue       BIT STRING --证书签名值,是使用signatureAlgorithm部分指定的签名算法对tbsCertificate证书主题部分签名后的值.
         }
TBSCertificate ::= SEQUENCE {
        version         [0] EXPLICIT Version DEFAULT v1, -- 证书版本号
        serialNumber         CertificateSerialNumber, -- 证书序列号,对同一CA所颁发的证书,序列号唯一标识证书
        signature            AlgorithmIdentifier, --证书签名算法标识
        issuer               Name,                --证书发行者名称
        validity             Validity,            --证书有效期
        subject              Name,                --证书主体名称
        subjectPublicKeyInfo SubjectPublicKeyInfo,--证书公钥
        issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
                             -- 证书发行者ID(可选),只在证书版本2、3中才有
        subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
                             -- 证书主体ID(可选),只在证书版本2、3中才有
        extensions      [3] EXPLICIT Extensions OPTIONAL
                             -- 证书扩展段(可选),只在证书版本3中才有
        }
Version ::= INTEGER { v1(0), v2(1), v3(2) }
 
CertificateSerialNumber ::= INTEGER
AlgorithmIdentifier ::= SEQUENCE {
        algorithm               OBJECT IDENTIFIER,
        parameters              ANY DEFINED BY algorithm OPTIONAL }
Parameters:
  	Dss-Parms ::= SEQUENCE { -- parameters ,DSA(DSS)算法时的parameters,
RSA算法没有此参数
        p             INTEGER,
        q             INTEGER,
        g             INTEGER }
SignatureValue:
Dss-Sig-Value ::= SEQUENCE { -- sha1DSA签名算法时,签名值
                   r       INTEGER,
                     s       INTEGER }
 
Name ::= CHOICE {
     RDNSequence }
 
RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
 
RelativeDistinguishedName ::=  SET OF AttributeTypeAndValue
 
AttributeTypeAndValue ::= SEQUENCE {
     type     AttributeType,
     value    AttributeValue }
 
AttributeType ::= OBJECT IDENTIFIER
AttributeValue ::= ANY DEFINED BY AttributeType
 
Validity ::= SEQUENCE {
        notBefore      Time,  -- 证书有效期起始时间
        notAfter       Time  -- 证书有效期终止时间 }
 
Time ::= CHOICE {
        utcTime        UTCTime,
        generalTime    GeneralizedTime }
 
UniqueIdentifier ::= BIT STRING
 
SubjectPublicKeyInfo ::= SEQUENCE {
        algorithm            AlgorithmIdentifier, -- 公钥算法
        subjectPublicKey     BIT STRING            -- 公钥值
        }
SubjectPublicKey:
RSAPublicKey ::= SEQUENCE { -- RSA算法时的公钥值
         modulus            INTEGER, -- n
         publicExponent     INTEGER -- e -- }
 
Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
Extension ::= SEQUENCE {
        extnID      OBJECT IDENTIFIER,
        critical    BOOLEAN DEFAULT FALSE,
        extnValue   OCTET STRING }
 

8. 测试获取证书信息

Bouncycastle提供了TBSCertificate将二进制转化为证书对象。TBSCertificate又包含了一些实体类。

public class TBSCertificate extends ASN1Object {
    ASN1Sequence seq;//描述
ASN1Integer version;//版本号
ASN1Integer serialNumber;//序列号
AlgorithmIdentifier signature; //签名算法
X500Name issuer;//颁发者信息
Time startDate;//有效期
Time endDate;//有效期
X500Name subject;//主题信息
SubjectPublicKeyInfo subjectPublicKeyInfo;//公钥及参数
DERBitString issuerUniqueId;//颁发者唯一oid
DERBitString subjectUniqueId;//主题唯一oid
Extensions extensions;//扩展
```

测试证书读取:

以一个crt证书为例。

byte[] cert1 = Base64.decode(
        "MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx"
                + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY"
                + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB"
                + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ"
                + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2"
                + "MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW"
                + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM"
                + "dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l"
                + "Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv"
                + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re"
                + "Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO"
                + "Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE"
                + "7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy"
                + "QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0"
                + "ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw"
                + "DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL"
                + "iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4"
                + "yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF"
                + "5/8=");
解析代码:
 
ByteArrayInputStream bIn = new ByteArrayInputStream(cert1);
        ASN1InputStream aIn = new ASN1InputStream(bIn);
 
        ASN1Sequence seq = (ASN1Sequence) aIn.readObject();
        Certificate obj = Certificate.getInstance(seq);
        TBSCertificate tbsCert = obj.getTBSCertificate();
        System.out.println(JSON.toJSONString(tbsCert));
 

解析结果

测试组装:

try{
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    //创建ByteArrayOutputStream,用于放置输出的byte流
    DEROutputStream derOutputStream = new DEROutputStream(outputStream);
    derOutputStream.writeObject(new ASN1Integer(10111));
    derOutputStream.writeObject(new X500Name("CN=hangzhou"));
    derOutputStream.flush();
    //将输出的bytearray转换为直观显示的Hex格式输出
    System.out.println(Hex.encodeHex(outputStream.toByteArray()));
} catch (Exception e) {
    e.printStackTrace();
}

结果是:02 02 27 7f 30 13 31 11 30 0f 06 03 55 04 03 0c 08 68 61 6e 67 7a 68 6f 75
02是类型Integer
02表示Len
27 7f表示10111
30表示BPMString
13表示Len
31 11 30 0f 06 03 55 04 03 0c 08 68 61 6e 67 7a 68 6f 75 表示CN=hangzhou

猜你喜欢

转载自blog.csdn.net/whatday/article/details/89096652