简体   繁体   中英

ASN.1 tag meaning

I have a tag with the following value: Tag(nr=16, typ=32, cls=0)

What do each of those values mean?

Based on https://en.wikipedia.org/wiki/X.690#Types , I think typ=32 should mean TIME-OF-DAY, but that doesn't make sense in my context.

So what is my context? I'm glad you asked: I'm unpacking an ECDH_SECP256R1 private key created with the following:

>>> import asn1
>>> from Crypto.IO.PKCS8 import unwrap
>>> import binascii
>>> from CryptoMobile.EC import *
>>> ec_B = ECDH_SECP256R1()
>>> ec_B.get_privkey()
b'0\x81\x87\x02\x01\x000\x13\x06\x07*\x86H\xce=\x02\x01\x06\x08*\x86H\xce=\x03\x01\x07\x04m0k\x02\x01\x01\x04 Wj\x80L\t\xc5\xa1oW\xd9\xbbFs{TH\xea\xe1*\x9a\x95\xf6\xe1\xd1\xe1\x9a%\xc8\xb7\xb3~h\xa1D\x03B\x00\x04\xf0T\xear^x\xb6\xa8\xe8\x04T \xf1\xbe\x81\xac\xba\xfdJ\xa10Y_\x0b\xb5^\x140\xaf\xa1S\x14|@\xfaV\x08\x15\x05Cr\xa7\xd1F\xcevq(H\x8a\x8d\xa2\xce\x84\xaa<\x0b>\xf5\xe0\xf1\xed\x9f\x90'
>>> unwrap(ec_B.get_privkey())
('1.2.840.10045.2.1', b'0k\x02\x01\x01\x04 Wj\x80L\t\xc5\xa1oW\xd9\xbbFs{TH\xea\xe1*\x9a\x95\xf6\xe1\xd1\xe1\x9a%\xc8\xb7\xb3~h\xa1D\x03B\x00\x04\xf0T\xear^x\xb6\xa8\xe8\x04T \xf1\xbe\x81\xac\xba\xfdJ\xa10Y_\x0b\xb5^\x140\xaf\xa1S\x14|@\xfaV\x08\x15\x05Cr\xa7\xd1F\xcevq(H\x8a\x8d\xa2\xce\x84\xaa<\x0b>\xf5\xe0\xf1\xed\x9f\x90', b'\x06\x08*\x86H\xce=\x03\x01\x07')
>>> 
>>> 
>>> decoder = asn1.Decoder()
>>> decoder.start(unwrap(ec_B.get_privkey())[1])
>>> tag, value = decoder.read()
>>> tag
Tag(nr=16, typ=32, cls=0)
>>> value
b'\x02\x01\x01\x04 Wj\x80L\t\xc5\xa1oW\xd9\xbbFs{TH\xea\xe1*\x9a\x95\xf6\xe1\xd1\xe1\x9a%\xc8\xb7\xb3~h\xa1D\x03B\x00\x04\xf0T\xear^x\xb6\xa8\xe8\x04T \xf1\xbe\x81\xac\xba\xfdJ\xa10Y_\x0b\xb5^\x140\xaf\xa1S\x14|@\xfaV\x08\x15\x05Cr\xa7\xd1F\xcevq(H\x8a\x8d\xa2\xce\x84\xaa<\x0b>\xf5\xe0\xf1\xed\x9f\x90'

I'm thinking that tag tells me how to understand the value. Or perhaps Python has already understood the value from the tag? Is this the final decoded value?

>>> print(binascii.hexlify(value))
b'0201010420576a804c09c5a16f57d9bb46737b5448eae12a9a95f6e1d1e19a25c8b7b37e68a14403420004f054ea725e78b6a8e8045420f1be81acbafd4aa130595f0bb55e1430afa153147c40fa560815054372a7d146ce767128488a8da2ce84aa3c0b3ef5e0f1ed9f90'

Or do I have to use knowledge of the tag to further decode that?

Note that, in ASN.1, the tag has no meaning... it is just used to encode and decode data (and only in BER, DER, CER encoding rules)

To have the meaning of the data, you always need the ASN.1 specification ( ECPrivateKey in @Crypt32 answer)

The all concept of encoding and decoding BER is explained in document x.690

When you encode a tag (see 8.1.2 in the x.690 doc), you need 3 pieces of information:

  • Class: Universal, Application, Context or Private
  • The primitive/constructed flag
  • The tag number

Let's take ECPrivateKey ...

  • Class is Universal ('00'B) which is the class reserved for ASN.1 types provided by the spec (SEQUENCE)
  • Flag is constructed. Because a SEQUENCE is a container of components
  • Tag number is 16 (provided by ASN.1)

So, back to your question:

Tag(nr=16, typ=32, cls=0)

  • nr is the tag number
  • typ is the primitive/constructed flag
  • cls is the class

Note that the names are from the tool you are using and not ASN.1 vocabulary

EDIT: it is actually well summarized in the link you provided https://en.wikipedia.org/wiki/X.690#Types

Go to https://asn1.io/asn1playground/ and compile following specification...

Example DEFINITIONS EXPLICIT TAGS ::= 
BEGIN
ECPrivateKey ::= SEQUENCE {
    version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
    privateKey     OCTET STRING,
    -- parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, --
    publicKey  [1] BIT STRING OPTIONAL
}                                          
END

Decode following value (I just put 306B before your value)... which means a SEQUENCE of 107 bytes

306B0201010420576a804c09c5a16f57d9bb46737b5448eae12a9a95f6e1d1e19a25c8b7b37e68a14403420004f054ea725e78b6a8e8045420f1be81acbafd4aa130595f0bb55e1430afa153147c40fa560815054372a7d146ce767128488a8da2ce84aa3c0b3ef5e0f1ed9f90

You see that your value is a sequence of version, privateKey and publicKey (the optional parameters is absent)

ECPrivateKey SEQUENCE: tag = [UNIVERSAL 16] constructed; length = 107
  version INTEGER: tag = [UNIVERSAL 2] primitive; length = 1
    1
  privateKey OCTET STRING: tag = [UNIVERSAL 4] primitive; length = 32
    0x576a804c09c5a16f57d9bb46737b5448ea ...
  publicKey : tag = [1] constructed; length = 68
    BIT STRING: tag = [UNIVERSAL 3] primitive; length = 66
      0x0004f054ea725e78b6a8e8045420f1be81 ...
Successfully decoded 109 bytes.
rec1value ECPrivateKey ::= 
{
  version ecPrivkeyVer1,
  privateKey '576A804C09C5A16F57D9BB46737B5448EA ...'H,
  publicKey '00000100 11110000 01010100 11101010 011 ...'B
}

Tag 16 is SEQUENCE or SEQUENCE OF . typ=32 suggests that bit 6 is set to 1, so SEQUENCE is in constructed form. In fact, in cryptography messages, SEQUENCE is always used in constructed form. I have no idea what cls=0 means (I'm not familiar with Python).

SEQUENCE is a struct with arbitrary fields. SEQUENCE OF is an ordered array of elements of same type (primitive or constructed). Exact type ( SEQUENCE of SEQUENCE OF ) is determined by ASN.1 module definition.

value in your case is a valid ECPrivateKey (as per RFC 5915 ) struct as defined below:

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

and the dump in ASN.1 Editor:

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM