1 poin oleh GN⁺ 2025-10-25 | 1 komentar | Bagikan ke WhatsApp
  • Seorang pengembang membagikan perjalanan teknis dan mental saat mengimplementasikan sendiri kompilator ASN.1 (dasn1) dengan bahasa D
  • Proyek ini menargetkan implementasi sertifikat x.509 dan TLS 1.3, serta mendukung penanganan encoding DER ASN.1 yang kompleks
  • Tulisan ini membahas secara rinci kerumitan struktural ASN.1, tingkat kesulitan implementasi spesifikasi x.680~x.683, serta cara memanfaatkan metaprogramming di bahasa D
  • Dijelaskan secara konkret bagaimana fitur D seperti static import, mixin template, typeof(), alias this berguna untuk pembuatan kode dan perancangan AST/IR
  • Tulisan ini menyampaikan dengan jujur bahwa “ASN.1 itu menyakitkan tetapi sangat mendidik”, sekaligus menggambarkan kesulitan nyata dan kepuasan dalam membuat kompilator

Gambaran proyek dan motivasi

  • Penulis sedang mengembangkan framework I/O asinkron berbasis D bernama Juptune, dan untuk implementasi TLS ia perlu menangani encoding ASN.1 DER secara langsung
    • Untuk mem-parsing struktur sertifikat x.509 pada TLS, perlu memahami cara representasi data ASN.1 yang rumit
  • Proyek ini dimulai sebagai tantangan pribadi untuk belajar dan bersenang-senang, dan sudah mencapai tahap berhasil mem-parsing beberapa sertifikat
  • ASN.1 adalah standar lama dari tahun 1990-an, tetapi masih digunakan luas di sistem modern seperti TLS, SNMP, dan LDAP
  • Penulis menyebut bahwa “ASN.1 digunakan luas di dunia, tetapi kebanyakan pengembang bahkan tidak tahu ia ada”

Apa itu ASN.1

  • ASN.1 (Abstract Syntax Notation One) adalah bahasa untuk mendefinisikan dan meng-encode struktur data, semacam “nenek moyang protobuf”
  • Standarnya terdiri dari notasi (x.680~x.683) dan aturan encoding (BER, CER, DER, PER, XER, JER, dan lain-lain)
    • BER: format TLV dasar, mendukung panjang tak terbatas
    • CER: bentuk terbatas dari BER, selalu memakai panjang tak terbatas
    • DER: subset deterministik dari BER, dipakai sebagai standar dalam kriptografi
    • PER/OER: encoding kompresi berbasis bit
    • XER/JER: encoding berbasis XML dan JSON
  • Jenis encoding yang banyak membuatnya kompleks, tetapi juga memberi fleksibilitas dan ekstensibilitas yang tinggi

Kompleksitas notasi ASN.1

  • Standar dasar ASN.1 adalah x.680, sementara spesifikasi ekstensi (x.681~x.683) ditulis dengan gaya akademis yang sangat sulit dipahami
  • Implementasi dimungkinkan hanya dengan x.680, tetapi aturan transformasi makna dan variasi sintaksnya membuat tingkat kesulitannya tinggi
  • x.681 mendefinisikan sistem Information Object Class, dan mendukung sintaks inisialisasi tersendiri
    • Contoh: CALLED &name [WHO IS &age YEARS OLD]
  • x.682 mendefinisikan Table Constraint, dan x.683 mendefinisikan tipe parameterized
    • Konsep ini mirip generic di bahasa D, karena bisa menerima tipe maupun nilai sebagai parameter

Fitur menarik ASN.1

  • Sistem constraint: memungkinkan rentang nilai atau ukuran dinyatakan langsung saat mendefinisikan tipe
    • Contoh: UInt8 ::= INTEGER (0..255)
    • Mendukung operator SIZE, UNION(|), INTERSECTION(^)
  • Sistem versioning: membedakan versi modul secara jelas melalui OBJECT IDENTIFIER
    • Contoh: id-pkix1-implicit(19) vs id-mod-pkix1-implicit-02(59)
    • Memungkinkan identifikasi modul yang jelas tanpa benturan nama

Mengapa bahasa D cocok untuk pembuatan kode

  • Static import di D mencegah benturan nama, sambil memungkinkan nama tipe ASN.1 dipertahankan apa adanya
  • Fitur module local lookup (.Type1) memperjelas pembatasan pencarian simbol
  • typeof() memungkinkan inferensi tipe otomatis sehingga tidak perlu pengelolaan manual saat menghasilkan kode
  • Dukungan trailing comma menyederhanakan pembuatan kode
  • Berkat penggabungan konstanta saat compile time, penggabungan string tetap bisa dilakukan bahkan di fungsi @nogc

Contoh implementasi yang memanfaatkan fitur bahasa D

Node AST berbasis mixin template

  • Menggunakan fitur mixin template di D untuk mendefinisikan node pohon sintaks ASN.1 (AST)
    • Setiap tipe node (List, Container, OneOf) dapat dipakai ulang sebagai template
    • Dibanding pewarisan yang kompleks, ini disederhanakan dengan penyalinan kode saat compile time

API berbasis template dan verifikasi saat compile time

  • Node Container memuat beberapa node turunan, dan melakukan verifikasi tipe saat compile time
    • Akses aman dimungkinkan dalam bentuk node.getNode!Asn1TagDefaultNode
  • Node OneOf menyimpan salah satu dari beberapa tipe, dan mendukung pattern matching melalui fungsi match
    • Karena semua handler tipe wajib didefinisikan, keamanan compile time dapat dijamin

Pemanfaatan paket eksperimental pengelolaan memori D

  • Menggunakan std.experimental.allocator untuk mengimplementasikan pembuatan/penghapusan objek di lingkungan @nogc
    • Menggabungkan komponen seperti Region dan StatsCollector untuk membangun allocator kustom
    • Namun, statusnya masih eksperimental bahkan setelah 10 tahun

Fitur alias this

  • Menggunakan alias this agar struct pembungkus dapat bertindak seperti field internalnya
    • Contoh: casting ringkas seperti cast(Asn1ValueReferenceIr)item

version(unittest)

  • Kata kunci version(unittest) dipakai untuk mendefinisikan fungsi khusus pengujian, dan tidak akan disertakan dalam build sebenarnya

Test harness dengan template + with()

  • Logika pengujian umum dijadikan template, dan pernyataan with() dipakai untuk menulis kode uji yang ringkas
    • Bisa dipanggil sebagai T() alih-alih Harness.T()

Kesulitan utama selama implementasi

Sintaks value sequence

  • Berbagai bentuk sintaks nilai yang dimulai dengan {} bersifat ambigu tergantung konteks
    • Sampai-sampai ada komentar di parser yang menyatakan “ini tidak menyenangkan”
  • Karena analisis sintaks dan analisis semantik dipisahkan, tingkat kesulitannya meningkat

Ketidakjelasan spesifikasi

  • Ada perilaku yang tidak dijelaskan eksplisit di dokumen, misalnya aturan bahwa tag harus diperlakukan sebagai EXPLICIT dalam kondisi tertentu
  • Cara versioning modul juga tidak didefinisikan dengan jelas

Constraint perlu diimplementasikan tiga kali

  1. Untuk validasi sintaks
  2. Untuk validasi nilai
  3. Untuk pembuatan kode saat runtime
  • Saat menangani UNION dan INTERSECTION, penyusunan pesan error juga menjadi rumit

Ilusi node IR yang immutable

  • Penulis sempat mengira setelah AST diubah menjadi IR, tidak perlu ada modifikasi lagi,
    tetapi proses transformasi makna seperti AUTOMATIC TAGS tetap membutuhkan perubahan data

Kompleksitas ASN.1 secara menyeluruh

  • x.509 relatif sederhana karena hanya memakai sintaks lama, tetapi spesifikasi modern mewajibkan implementasi x.681~x.683
    • Karena itu ASN.1 nyaris tidak dipakai di luar ranah akademik dan komersial tertentu

Masalah ANY DEFINED BY

  • ANY DEFINED BY adalah struktur yang tipenya berubah sesuai nilai field lain
    • dasn1 tidak mengimplementasikannya, dan menggantinya dengan intrinsic kustom Dasn1-Any
    • Saat decoding nyata, penanganannya tetap perlu dilakukan manual

Kelebihan beban informasi

  • Karena mengerjakan beberapa proyek sekaligus seperti ASN.1, x.68x, x.690, dan Juptune, menjaga konteks codebase menjadi sulit

Realitas membuat kompilator

  • Ada ribuan visitor node, kode yang berulang, dan implementasi dengan perbedaan sangat kecil, sehingga ini menjadi pekerjaan yang membosankan dan melelahkan
  • Namun, di setiap tahap ada rasa pencapaian besar dan efek belajar yang kuat
  • Penulis mengenang bahwa “tak akan ada yang memakainya, tetapi saya benar-benar mendapatkan pengalaman kompilator yang nyata”
  • Di akhir, tulisan ditutup dengan candaan: “jangan main ASN.1, hidupmu akan berubah”

Kesimpulan

  • Meski sudah dikerjakan selama 1 tahun, dasn1 masih belum selesai, tetapi pengalaman ini menjadi momen untuk memahami secara mendalam potensi bahasa D dan kompleksitas ASN.1
  • Penulis menutup tulisan dengan nada humoris, sambil bermimpi suatu hari bisa menulis “pengalaman membuat kompilator ASN.1 + implementasi TLS 1.3” di resume, dan meninjau kembali pertumbuhan seorang pengembang serta realitas industri

1 komentar

 
GN⁺ 2025-10-25
Komentar Hacker News
  • Singkatnya, penulis ingin membahas ASN.1, bahasa D, dan compiler itu sendiri
    Namun karena tidak menemukan format yang konsisten, berbagai pemikiran terkait akhirnya dikumpulkan menjadi tulisan blog
    Hasil akhirnya memang belum sepenuhnya matang, tetapi topiknya memang sulit dibahas secara singkat, jadi harap maklum

    • Contoh intersection sepertinya tidak bekerja seperti yang dimaksud
      Secara matematis, {0} ∪ ({2} ∩ {4,5,6,7,8}) = {0}, jadi pada akhirnya hanya satu nilai yang diperbolehkan
    • Begitu membahas bahasa D, rasanya seperti memanggil Walter Bright
      Secara pribadi saya sangat menyukai D, tetapi secara realistis Go dan Rust jauh lebih banyak digunakan
    • Saya juga pernah menangani data ASN.1, dan pekerjaan yang terkait sertifikat terutama sangat menyiksa
      Saya benar-benar bisa memahami perjuangan penulis
    • Saya sangat menikmati membaca tulisan ini
      Saya suka D, tetapi sudah lama tidak menggunakannya
      Saya juga pernah mengerjakan parser dan implementasi protokol, jadi rasanya makin menarik
    • Blog pada akhirnya adalah ruang milik sendiri, jadi semoga penulis terus melanjutkannya dengan caranya sendiri
  • “OMG ASN.1”, topik yang benar-benar menyenangkan untuk dilihat lagi
    Saya ingat masa ketika internet sedang tumbuh dan IETF masih mengembangkan protokol
    Saat itu perusahaan-perusahaan belum tertarik pada internet, dan dunia akademik serta IETF yang memimpin
    Namun ketika perusahaan menyadari bahwa ini bisa menghasilkan uang, dimulailah Protocol Wars
    ASN.1 adalah hasil dari perang itu sekaligus contoh benturan budaya korporat dan budaya akademik
    Korporasi bisa dianalogikan sebagai ‘budaya resep’, sedangkan akademisi sebagai ‘budaya fungsi’
    Perbedaan cara berpikir ini juga memberi perspektif menarik pada budaya pengembangan AI masa kini

    • Dulu saya pernah menonton film Father of the Bride dan terkejut ketika ada pembahasan soal jaringan X.25
      Memikirkan bahwa kita mungkin saja berakhir dengan sistem alamat seperti “CN=wikipedia, OU=org, C=US” alih-alih internet yang sekarang terasa agak mengerikan
    • Saya jadi berpikir “OMG ASN.1” cocok dijadikan nama band saya berikutnya
    • Sebagian ceritanya memang benar, tetapi menyebut pelaku utamanya sebagai ‘korporasi’ terasa agak kurang tepat
      Yang sebenarnya menjadi pusat adalah ITU dan ISO
      Lalu pada akhir 1990-an ada lagi ‘perang protokol’ lain, dan kali ini IETF yang kalah
    • Perang ini juga merupakan bagian dari komersialisasi awal internet (en-shittification)
      ISO terlalu mengejar kesempurnaan sampai menjadi lambat, sedangkan IETF bergerak cepat dengan sikap “nanti diperbaiki belakangan”
      Akibatnya, muncul masalah ketika protokol keburu membeku
      Implementasi ASN.1 untuk C pada 1990-an yang sangat buruk juga menjadi masalah besar
    • Intinya, sudut pandang korporat pada akhirnya adalah sudut pandang mainframe
  • Ada pepatah Turki yang berbunyi, “Ini bukan barang untuk dipakai manusia!”
    Saya ingin menjadikannya moto filsafat desain
    Dan seperti kalimat di Game of Thrones, “orang yang menjatuhkan vonis harus mengayunkan pedangnya sendiri,”
    orang yang membuat spesifikasi harus mengimplementasikan parser-nya sendiri
    Jika persetujuan spesifikasi baru diberikan setelah parser yang benar-benar berjalan dan test ikut diserahkan, kualitasnya sepertinya akan jauh lebih baik

  • Saya sangat menyukai bahasa D
    Saya sedang membuat sendiri editor teks bergaya vim yang hanya bergantung pada Raylib
    Kelebihan D antara lain sebagai berikut

    • Bisa menulis unit test di mana saja
    • Mudah mengelola kode khusus test dengan blok version(unittest)
    • Dukungan bahasa untuk enum, union, assert, contract programming, dan lain-lain sangat bagus
      Tiap kali membaca dokumentasi atau bertanya ke ChatGPT, saya selalu bisa menemukan solusi yang elegan
    • D bagi saya adalah bahasa yang manis-pahit
      Dari sisi filosofi desain, bahasanya nyaris sempurna, tetapi jika tooling dan ekosistemnya setara dengan Rust atau Go, pasti akan jauh lebih sukses
    • Fitur-fitur D memang bagus, tetapi bahasanya makin cenderung ramai/noisy
      Standard library Phobos punya terlalu banyak gangguan kecil, sampai akhirnya saya menyerah
      Versi baru, Phobos V3, memang sedang dikembangkan, tetapi karena orangnya sedikit saya antara berharap dan khawatir
  • “Apakah saya pernah bilang ASN.1 itu rumit?”
    Baik skema maupun format datanya memang kompleks, tetapi sebagian besar kerumitannya bisa diabaikan
    Saya tidak memakai notasi skema ASN.1, melainkan menulis sendiri implementasi DER dalam C
    Menurut saya DER adalah satu-satunya encoding standar yang benar-benar layak dipakai
    Saya juga membuat format encoding sendiri seperti DSER, SDSER, dan TER
    Struktur seperti ANY DEFINED BY juga masih saya gunakan dengan berguna,
    dan untuk encoding yang lebih efisien saya bahkan menambahkan fitur nonstandar OBJECT IDENTIFIER RELATIVE TO

  • Saya juga pernah membuat compiler ASN.1
    Saya hanya mengimplementasikan sebagian fitur dari X.681 hingga X.683, tetapi saya membuatnya bisa mendekode seluruh sertifikat secara rekursif hanya dengan satu pemanggilan codec
    ASN.1 bukan sekadar sintaks sederhana, melainkan sistem tipe yang kuat
    Teknologi ini sering diremehkan, padahal sebenarnya sangat keren

  • Dulu saya pernah membuat compiler ASN.1 untuk Swift
    Itu adalah proyek ASN1Codable, yang memanfaatkan Heimdal libasn1
    ASN.1 diubah menjadi JSON AST agar parsing menjadi lebih sederhana

    • README libasn1 terasa memancarkan kebencian halus terhadap ASN.1
      Kalimat “ubah saja jadi JSON” terdengar seperti jeritan developer yang sudah terluka 😄
  • Anehnya, bekerja dengan ASN.1 terasa menyenangkan
    Suatu hari saya ingin membuat sendiri compiler ASN.1 untuk Rust
    Implementasi Rust saat ini kebanyakan masih memakai derive macro atau chaining manual, dan itu terasa kurang memuaskan

  • Secara umum, saat mengimplementasikan standar, 80% fitur bisa selesai dalam 20% waktu,
    tetapi 20% sisanya dari ASN.1 mungkin bisa memakan seumur hidup

  • Saya dulu pernah memperluas parser ASN.1 di codebase Netscape untuk menambahkan dukungan PKCS#12
    Saya jadi tahu terlalu dalam soal standar RSA dan definisi ASN.1, dan agak menyesal karenanya,
    tetapi saya tetap menghormati ketekunan dan sedikit sifat masokis dari penulis blog ini

    • Dengan pengalaman seperti itu, pasti ada banyak sekali kisah pengembangan yang terasa seperti perang