DERUNPACK(3)
β¨ DERUNPACK(3) β¨
okay bestie, pull up a chair, we're talking about derunpack (version 1.0, the manual page, DERUNPACK section 3) and honestly? it's giving decoder core π
π NAME π
packet.derunpack β the DER decoding module π¦
πΈ DESCRIPTION πΈ
So what it does is decode using ASN.1 DER β that's Distinguished Encoding Representation, and ASN.1 stands for Abstract Syntax Notation 1. Yes the acronyms are doing the most, we move.
Important tea though: this module does not completely decode all DER data types. It's a picky eater, and here's exactly the list of data types it supports in this implementation:
INTEGERBIT_STRINGNULLOBJECT_IDENTIFIERGeneralizedTime- Strings (
OCTET STRING,PrintableString, etc.) SEQUENCE OFSEQUENCE
π CLASSES π
class DERunpack(packet.unpack.Unpack)
the DER unpack object itself, the main character π
Usage:
from packet.derunpack import DERunpack
x = DERunpack(buffer)
# Get the decoded object structure for the stream bytes in buffer
obj = x.get_item()
Where obj is of the form:
obj = {
application = {
context-tag0 = int|list|dictionary,
context-tag1 = int|list|dictionary,
...
context-tagN = int|list|dictionary,
}
}
Example:
For the following ASN.1 definition:
TEST ::= [APPLICATION 10] SEQUENCE {
id [0] INTEGER,
numbers [1] SEQUENCE OF INTEGER,
data [2] SEQUENCE {
-- NOTE: first tag is [1], not [0]
type [1] INTEGER,
value [2] PrintableString,
},
}
Using the streamed bytes of the above ASN.1 definition, the following is returned by get_item():
obj = {
10 = { # Application 10
0: 53, # id: context-tag=0, value=53
1: [1,2,3], # numbers: context-tag=1, value=[1,2,3]
2: { # data: context-tag=1, value=structure
1: 2, # id: context-tag=1, value=2
2: "test", # id: context-tag=2, value="test"
}
}
}
π§ Methods defined here:
der_date(self, size)
Returns a date time of type GeneralizedTime. β¨
Type GeneralizedTime takes values of the year, month, day, hour, minute, second, and second fraction in any of following three forms:
- Local time:
"YYYYMMDDHH[MM[SS[.fff]]]" - Universal time (UTC):
"YYYYMMDDHH[MM[SS[.fff]]]Z" - Difference between local and UTC times":
"YYYYMMDDHH[MM[SS[.fff]]]+|-HHMM".
Where the optional fff is accurate to three decimal places. π
der_integer(self, size=None, unsigned=False)
Returns an integer given the size of the integer in bytes.
size: Number of bytes for the integer. If this option is not given, the methodget_size()is used to get the size of the integer.unsigned: Usually an unsigned integer is encoded with a leading byte of all zeros, but when decoding data ofBIT_STRINGtype all decoded bytes must be unsigned so they can be concatenated correctly.
der_oid(self, size)
Returns an object identifier (OID). π
get_item(self, oid=None)
Get item from the byte stream using TLV. π₯
This is a recursive function where the tag and length are decoded, and then this function is called to get the value if tag is one of primitive or non-constructed types.
Pro tip from the page itself: calling this method right after instantiation of the object will decode the whole ASN.1 representation.
get_size(self)
Get the size of element (length in TLV).
- Short form:
bit8=0, one octet, length given by bits7-1(0-127) - Long form:
bit8=1,2-127octet, bits7-1give number of length objects
Example:
- Short form (
bit8=0):0x0f(0b00001111): length is0x0f(15) - Long form (
bit8=1of first byte):0x820123(0b100000100000000100100011): length is given by the next 2 bytes (first7-1bits0x02) Next two bytes gives the length0x0123= 291
get_tag(self)
Get the tag along with the tag class and form or P/C bit.
The first byte(s) of the TLV (Type, Length, Value) is the type, which has the following format:
- First byte:
- bits
8-7: tag class - bit
6: form or P/C (Constructed if bit is set) - bits
5-1: tag number (0-30) β if all bits are 1's (decimal 31) then one or more bytes are required for the tag
- bits
If bits 5-1 are all 1's in the first byte, the tag is given in the following bytes:
- Extra byes for tag:
- bit
8: next byte is part of tag - bits
7-1: tag bits
- bit
Examples:
0xa1 (0b10100001): Short form
- tag class:
0b10= 2 (CONTEXT) - P/C:
0b0= 0 (not constructed)
0x1f8107 (0b000111111000000100000111): Long form
- tag class:
0b00= 0 (UNIVERSAL -- standard tag) - P/C:
0b0= 0 (not constructed) - tag:
0b11111= 31 (tag is given in following bytes) - First extra byte:
0x81(0b10000001)bit8=1: there is an extra byte after this- bits
7-1:0b0000001(0x01most significant 7 bits of tag)
- Second extra byte:
0x07(0b00000111)bit8=1: this is the last byte- bits
7-1:0b0000111(0x07least significant 7 bits of tag)
- Tag number: big-endian bits from extra bytes (7 bits each) 14 bits:
0x0087(0x01<< 7 +0x07) = 135
π«Ά SEE ALSO π«Ά
π BUGS π
No known bugs. we love a clean bill of health, periodt β¨
π AUTHOR π
Jorge Mora (mora@netapp.com) π
and that's the whole vibe, bestie β this page came to you from NFStest 3.2, dated 21 March 2023. go forth and decode, you absolute icon π
π¦ where this page comes from
- debian trixie: nfstest 3.2-3
- fedora 43: NFStest 3.2-14.fc43 Β· GPL-2.0-or-later
- fedora 44: NFStest 3.2-16.fc44 Β· GPL-2.0-or-later
- ubuntu noble: nfstest 3.2-2
- ubuntu questing: nfstest 3.2-3
- ubuntu resolute: nfstest 3.2-3build1
- ubuntu stonking: nfstest 3.2-5
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms