メインコンテンツまでスキップ

ASN.1 と DER

ASN.1 は X.509 証明書や PKCS などの暗号分野で使われるデータ記述言語です。このドキュメントでは、ASN.1 と DER エンコーディングの基礎を解説します。


ASN.1 とは​

ASN.1(Abstract Syntax Notation One)は、データ構造を定義するための言語です。

ASN.1 の役割:

┌─────────────────────────────────────────────────────────────┐
│ │
│ ASN.1 = スキーマ定義言語(データ構造の「設計図」) │
│ │
│ 例: X.509 証明書の定義 │
│ │
│ Certificate ::= SEQUENCE { │
│ tbsCertificate TBSCertificate, │
│ signatureAlgorithm AlgorithmIdentifier, │
│ signatureValue BIT STRING │
│ } │
│ │
│ この定義に基づいて、実際のバイナリ(DER)が生成される │
│ │
└─────────────────────────────────────────────────────────────┘

ASN.1 と JSON Schema の比較​

観点ASN.1JSON Schema
データ形式バイナリ(DER/BER)テキスト(JSON)
標準化ITU-T X.680-683IETF Draft
用途暗号、通信プロトコルWeb API
歴史1984年〜2010年〜

エンコーディング規則​

ASN.1 で定義されたデータは、複数の方法でバイナリ化できます。

規則名前特徴
BERBasic Encoding Rules柔軟だが非一意
DERDistinguished Encoding Rules一意(暗号用)
CERCanonical Encoding Rulesストリーミング向け
PERPacked Encoding Rules最もコンパクト
XERXML Encoding RulesXML 形式

暗号分野では DER が標準です(署名の一意性が必要なため)。


DER の基本構造​

TLV(Tag-Length-Value)​

DER は TLV 形式でエンコードされます。

TLV 構造:

┌─────────────────────────────────────────────────────────────┐
│ │
│ Tag (1-n bytes) │ Length (1-n bytes) │ Value (n bytes) │
│ │
│ 何のデータか データの長さ 実際のデータ │
│ │
└─────────────────────────────────────────────────────────────┘

例: INTEGER 30

02 # Tag: INTEGER
01 # Length: 1 byte
1E # Value: 30

タグの構造​

タグバイトの構造:

┌───┬───┬───┬───┬───┬───┬───┬───┐
│ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │
└───┴───┴───┴───┴───┴───┴───┴───┘
└───┬───┘└─┬─┘└───────┬─────────┘
Class P/C Tag Number

Class:
00 = Universal(標準型)
01 = Application
10 = Context-specific
11 = Private

P/C:
0 = Primitive(プリミティブ)
1 = Constructed(構造体)

主要な Universal タグ​

タグ16進型
101BOOLEAN
202INTEGER
303BIT STRING
404OCTET STRING
505NULL
606OBJECT IDENTIFIER
120CUTF8String
1630SEQUENCE
1731SET
1913PrintableString
2216IA5String
2317UTCTime
2418GeneralizedTime

Length のエンコード​

Short Form(0-127 バイト):
長さをそのまま 1 バイトで表現
例: 長さ 30 → 1E

Long Form(128 バイト以上):
最初のバイト = 0x80 + 長さバイト数
続くバイト = 長さ
例: 長さ 256 → 82 01 00

Indefinite Length(BER のみ、DER では禁止):
80 ... 00 00

具体例:INTEGER​

正の整数 30:
02 01 1E
│ │ └── Value: 30
│ └───── Length: 1
└──────── Tag: INTEGER

正の整数 256:
02 02 01 00
│ │ └──── Value: 256 (0x0100)
│ └─────── Length: 2
└────────── Tag: INTEGER

正の整数 127:
02 01 7F

正の整数 128(注意!):
02 02 00 80
│ │ │ └── 128
│ │ └───── 先頭に 00 を付ける(正の数を示す)
│ └──────── Length: 2
└─────────── Tag: INTEGER

※ 0x80 は負の数と解釈されるため、00 を付ける

具体例:SEQUENCE​

SEQUENCE { name: "John", age: 30 }

ASN.1 定義:
Person ::= SEQUENCE {
name UTF8String,
age INTEGER
}

DER:
30 0B # SEQUENCE, length 11
0C 04 # UTF8String, length 4
4A6F686E # "John"
02 01 # INTEGER, length 1
1E # 30

具体例:OBJECT IDENTIFIER (OID)​

OID は階層的な識別子です。

例: sha256WithRSAEncryption = 1.2.840.113549.1.1.11

エンコード規則:
- 最初の2つ: 40 * first + second
- 残り: 7ビット可変長エンコード

1.2.840.113549.1.1.11:
06 09 # OID, length 9
2A # 1*40 + 2 = 42
86 48 # 840
86 F7 0D # 113549
01 # 1
01 # 1
0B # 11

よく使われる OID:

OID意味
1.2.840.113549.1.1.1rsaEncryption
1.2.840.113549.1.1.11sha256WithRSAEncryption
1.2.840.10045.2.1ecPublicKey
1.2.840.10045.3.1.7secp256r1 (P-256)
2.5.4.3commonName (CN)
2.5.4.6countryName (C)
2.5.4.10organizationName (O)

X.509 証明書の構造​

X.509 証明書の ASN.1 定義(簡略版):

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,
...
}

実際の証明書(DER)​

30 82 03 A3                   # SEQUENCE (certificate)
30 82 02 8B # SEQUENCE (tbsCertificate)
A0 03 # [0] EXPLICIT (version)
02 01 02 # INTEGER 2 (v3)
02 10 # INTEGER (serialNumber)
...
30 0D # SEQUENCE (signature algorithm)
06 09 # OID
2A 86 48 86 F7 0D 01 01 0B # sha256WithRSA
05 00 # NULL
30 ... # SEQUENCE (issuer)
30 1E # SEQUENCE (validity)
17 0D # UTCTime
...
30 ... # SEQUENCE (subject)
30 ... # SEQUENCE (subjectPublicKeyInfo)
30 0D # SEQUENCE (signatureAlgorithm)
...
03 82 01 01 # BIT STRING (signature)
00 ...

PEM 形式​

DER バイナリを Base64 でテキスト化した形式。

-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIUZ...(Base64エンコードされたDER)
...
-----END CERTIFICATE-----

BEGIN/END の種類:
- CERTIFICATE: 証明書
- PRIVATE KEY: 秘密鍵(PKCS#8)
- RSA PRIVATE KEY: RSA秘密鍵(PKCS#1)
- PUBLIC KEY: 公開鍵
- CERTIFICATE REQUEST: CSR

PEM ↔ DER 変換​

# PEM → DER
openssl x509 -in cert.pem -outform DER -out cert.der

# DER → PEM
openssl x509 -in cert.der -inform DER -outform PEM -out cert.pem

デバッグツール​

OpenSSL​

# 証明書の内容を表示
openssl x509 -in cert.pem -text -noout

# ASN.1 構造を表示
openssl asn1parse -in cert.pem

# DER ファイルを解析
openssl asn1parse -in cert.der -inform DER

# 特定オフセットから解析
openssl asn1parse -in cert.pem -strparse 19

オンラインツール​

dumpasn1​

# インストール (macOS)
brew install dumpasn1

# 使用
dumpasn1 cert.der

よくあるエンコーディング​

RSA 公開鍵 (PKCS#1)​

RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER -- e
}

30 ... # SEQUENCE
02 ... # INTEGER (n)
00 ... # modulus
02 03 # INTEGER (e)
01 00 01 # 65537

RSA 公開鍵 (X.509/SPKI)​

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

30 ... # SEQUENCE
30 0D # SEQUENCE (algorithm)
06 09 # OID: rsaEncryption
2A 86 48 86 F7 0D 01 01 01
05 00 # NULL
03 ... # BIT STRING
00 # unused bits
30 ... # SEQUENCE (RSAPublicKey)
...

EC 公開鍵​

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

30 59 # SEQUENCE
30 13 # SEQUENCE (algorithm)
06 07 # OID: ecPublicKey
2A 86 48 CE 3D 02 01
06 08 # OID: secp256r1
2A 86 48 CE 3D 03 01 07
03 42 # BIT STRING
00 # unused bits
04 # uncompressed point
[32 bytes X]
[32 bytes Y]

CBOR/COSE との比較​

観点ASN.1/DERCBOR
設計年代1984年2013年
複雑さ高い低い
スキーマ必須オプション
用途暗号、通信IoT、Web
デバッグ難しい比較的容易
採用領域X.509、PKCSWebAuthn、mdoc
なぜ両方存在するか:

ASN.1/DER:
- PKI(証明書)の標準
- 歴史的に確立されたエコシステム
- 変更が困難

CBOR:
- 新しい技術(WebAuthn、mdoc)で採用
- よりシンプル
- JSON との親和性

実務では両方を理解する必要がある

まとめ​

ASN.1/DER の特徴:

┌─────────────────────────────────────────────────────────────┐
│ │
│ 何者か: │
│ データ構造を定義する言語(ASN.1)と │
│ そのバイナリ表現(DER) │
│ │
│ 使われる場所: │
│ - X.509 証明書 │
│ - PKCS(#1, #7, #8, #12) │
│ - CRL、OCSP │
│ │
│ 構造: │
│ TLV(Tag-Length-Value)形式 │
│ │
│ デバッグ: │
│ - openssl asn1parse │
│ - lapo.it/asn1js │
│ │
│ 注意点: │
│ - 複雑で学習コストが高い │
│ - 新規設計では CBOR が推奨されることが多い │
│ - ただし証明書関連では必須の知識 │
│ │
└─────────────────────────────────────────────────────────────┘

参考リンク​