GoSuda

Penggunaan MLDSA dan MLKEM dalam Go Language

By snowmerak
views ...

Gambaran Umum

Latar Belakang

Sudah cukup lama, komputasi cepat dari komputer kuantum telah diakui sebagai ancaman bagi sistem kriptografi yang ada. Ini karena RSA atau ECC yang ada berpotensi diretas karena kemampuan komputasi komputer kuantum tersebut. Namun, sejak beberapa tahun yang lalu, konsep komputer kuantum mulai terwujud, dan alternatif-alternatifnya mulai diteliti dan dikembangkan, serta NIST telah melakukan standardisasi PQC (Post-Quantum Cryptography).

MLDSA dan MLKEM

Akhirnya, pada bulan Agustus 2024, NIST mengadopsi MLKEM dan MLDSA sebagai standar, yang didasarkan pada CRYSTALS-Kyber dan CRYSTALS-Dilithium. Kedua algoritma ini beroperasi berdasarkan masalah yang disebut MLWE (Module Learning with Errors). Format ini kami sebut sebagai kriptografi berbasis kisi.

Kriptografi berbasis kisi, sesuai namanya, adalah sistem kriptografi yang didasarkan pada kesulitan masalah matematika pada kisi. Saya sendiri tidak memiliki pengetahuan matematika yang mendalam tentang ini, tetapi jika diringkas dalam satu kalimat, ini adalah masalah memecahkan persamaan linear dengan noise dalam kisi modul. Meskipun saya tidak dapat merasakan seberapa sulitnya itu, masalah ini dikatakan sangat sulit sehingga tidak dapat dipecahkan bahkan oleh komputer kuantum.

MLDSA

Sekarang, mari kita bahas tentang MLDSA.

Komposisi

MLDSA, seperti yang terlihat dari namanya, adalah algoritma tanda tangan asimetris yang melalui 2 tahap berikut:

  1. Pembuatan Tanda Tangan: Menggunakan kunci privat untuk membuat tanda tangan untuk pesan.
  2. Verifikasi Tanda Tangan: Menggunakan kunci publik untuk memverifikasi validitas tanda tangan yang dibuat.

Dan MLDSA memiliki 3 karakteristik berikut:

  1. strong existential unforgeability: Dengan satu tanda tangan dan kunci publik, tanda tangan valid lainnya tidak dapat dibuat.
  2. chosen message attack: Tanda tangan valid baru tidak dapat dibuat dengan kunci publik dari tanda tangan untuk pesan apa pun.
  3. side-channel attack: Keamanan tinggi karena nilai acak baru dan nilai pseudo-acak yang berasal dari pesan terus-menerus digunakan saat menandatangani.
  4. domain separation: Mencegah masalah keamanan berulang dengan menggunakan seed yang berbeda untuk parameter yang berbeda.

Kode

Sekarang, saya akan menunjukkan contoh kode Go sederhana. Dalam contoh ini, saya menggunakan mldsa dari cloudflare/circl.

 1package main
 2
 3import (
 4	"crypto"
 5	"crypto/rand"
 6	"encoding/base64"
 7	"fmt"
 8
 9	"github.com/cloudflare/circl/sign/mldsa/mldsa44"
10)
11
12func main() {
13    // Membuat kunci dengan spesifikasi mldsa44.
14	pub, priv, err := mldsa44.GenerateKey(rand.Reader)
15	if err != nil {
16		panic(err)
17	}
18
19	message := []byte("Hello, World!")
20
21    // Membuat tanda tangan.
22    // Satu hal yang perlu diperhatikan adalah bahwa pada versi saat ini, 22 Desember 2024, jika bukan crypto.Hash(0), akan terjadi error.
23	signature, err := priv.Sign(rand.Reader, message, crypto.Hash(0))
24	if err != nil {
25		panic(err)
26	}
27
28	encodedSignature := base64.URLEncoding.EncodeToString(signature)
29	fmt.Println(len(encodedSignature), encodedSignature)
30
31    // Memverifikasi dengan memanggil skema kunci publik.
32	ok := pub.Scheme().Verify(pub, message, signature, nil)
33	fmt.Println(ok)
34}
13228 oaSaOA-...
2true

Nilai tanda tangan terlalu panjang sehingga disingkat. Jika Anda ingin melihat teks lengkapnya, silakan jalankan di playground.

Meskipun di-encode dengan base64, ukuran 3228 byte mungkin sedikit memberatkan. Agak memberatkan untuk berpikir bahwa sebentar lagi kita mungkin harus menukar tanda tangan sebesar ini untuk melawan komputer kuantum..

MLKEM

Komposisi

MLKEM adalah Mekanisme Kapsulasi Kunci (Key Encapsulation Mechanism). KEM adalah algoritma yang memungkinkan pembuatan kunci bersama antara dua pihak menggunakan metode kriptografi kunci publik. Mekanisme pertukaran kunci MLKEM melalui proses berikut:

  1. Kapsulasi Kunci: Pengirim menggunakan kunci publik penerima untuk membuat pesan terenkripsi (cipher text) dan kunci bersama (shared key). Pesan terenkripsi ini awalnya dikirimkan kepada penerima untuk digunakan.
  2. Dekapsulasi Kunci: Penerima menggunakan kunci privatnya untuk mengekstrak kunci bersama dari pesan terenkripsi.

MLKEM memiliki total 3 parameter. Ada MLKEM-512, MLKEM-768, MLKEM-1024, di mana semakin kecil angkanya, semakin kecil kunci dan teks terenkripsi yang dihasilkan, dan semakin besar angkanya, semakin panjang kunci dan teks terenkripsi yang dihasilkan, serta tingkat keamanannya lebih tinggi.

Kode

MLKEM akan ditambahkan di go 1.24, jadi saya menggunakan go 1.24rc1 yang tersedia saat ini.

 1package main
 2
 3import (
 4	"crypto/mlkem"
 5	"encoding/base64"
 6	"fmt"
 7)
 8
 9func main() {
10    // Membuat PrivateKey penerima.
11	receiverKey, err := mlkem.GenerateKey1024()
12	if err != nil {
13		panic(err)
14	}
15
16    // Dalam MLKEM, istilah yang digunakan adalah EncapsulationKey, bukan PublicKey.
17	receiverPubKey := receiverKey.EncapsulationKey()
18
19    // Ini hanyalah untuk menunjukkan bahwa kunci dapat diekstrak dan digunakan kembali dengan Bytes() EncapsulationKey dan NewEncapsulationKeyX.
20    // Tentu saja, dalam kenyataan, proses ini dapat dianggap sebagai proses di mana pengirim membuat objek dari EncapsulationKey penerima yang telah dipublikasikan sebagai teks.
21	clonedReceiverPubKey, err := mlkem.NewEncapsulationKey1024(receiverPubKey.Bytes())
22	if err != nil {
23		panic(err)
24	}
25
26    // Pengirim membuat cipherText dan SenderSharedKey dengan Encapsulate.
27	cipherText, SenderSharedKey := clonedReceiverPubKey.Encapsulate()
28
29    // Saya sengaja mengkloning ini untuk menunjukkan cara menyimpan dan mengambil kunci privat penerima.
30	clonedReceiverKey, err := mlkem.NewDecapsulationKey1024(receiverKey.Bytes())
31	if err != nil {
32		panic(err)
33	}
34
35    // Penerima mendekapsulasi cipherText menggunakan kunci privatnya untuk membuat shared key lainnya.
36	sharedKeyReceiver, err := clonedReceiverKey.Decapsulate(cipherText)
37	if err != nil {
38		panic(err)
39	}
40
41	fmt.Println(base64.StdEncoding.EncodeToString(SenderSharedKey))
42	fmt.Println(base64.StdEncoding.EncodeToString(sharedKeyReceiver))
43}
1Q1ciS818WFHTK7D4MTvsQvciMTGF+dSGqMllOxW80ew=
2Q1ciS818WFHTK7D4MTvsQvciMTGF+dSGqMllOxW80ew=

Sebagai hasilnya, kita dapat melihat bahwa kunci bersama dengan ukuran yang sama dihasilkan!

Kode ini juga dapat ditemukan di playground.

Kesimpulan

Spesifikasi, tingkat keamanan, ukuran kunci privat, kunci publik, tanda tangan atau ciphertext dari setiap algoritma dapat diringkas sebagai berikut. Masing-masing memiliki ukuran yang besar, sesuai dengan nama PQC.

AlgoritmaTingkat Keamanan NISTUkuran Kunci PrivatUkuran Kunci PublikUkuran Tanda Tangan/Ciphertext
ML-DSA-4422,5601,3122,420
ML-DSA-6534,0321,9523,309
ML-DSA-8754,8962,5924,627
ML-KEM-51211,632800768
ML-KEM-76832,4001,1841,088
ML-KEM-102453,1681,5681,568

Dengan algoritma-algoritma ini, kami berharap dapat menggunakan internet yang cukup aman bahkan di komputer kuantum, tetapi tampaknya tidak dapat dihindari bahwa akan ada lebih banyak komputasi karena ukuran kunci dan tanda tangan/ciphertext yang relatif lebih besar.

Namun, karena setiap algoritma diimplementasikan secara efektif dalam bahasa Go, kami berharap algoritma ini akan digunakan secara aktif untuk melindungi keamanan Anda di tempat yang tepat!