Go 1.27 มี ML-DSA ใน Standard Library: เซ็นข้อมูลให้พร้อมยุค Post-Quantum
ลายเซ็นดิจิทัลที่เราใช้วันนี้อาศัยโจทย์คณิตศาสตร์ซึ่งคอมพิวเตอร์ทั่วไปแก้ยาก แต่คอมพิวเตอร์ควอนตัมขนาดใหญ่ในอนาคตอาจทำลายสมมติฐานของ RSA และ elliptic curve ได้ เอกสารที่ต้องตรวจสอบอีกหลายปี เช่น firmware, audit artifact หรือใบอนุมัติระยะยาว จึงควรเริ่มมีทางย้ายก่อนวันที่ภัยนั้นมาถึง
Go 1.27 เพิ่ม package crypto/mldsa สำหรับ ML-DSA ตามมาตรฐาน FIPS 204 ของ NIST เข้ามาใน standard library จุดสำคัญไม่ใช่ให้เปลี่ยนระบบทั้งหมดวันนี้ แต่ให้ทีมทดลอง format, ขนาด key/signature และ migration path ด้วย API ที่มีเจ้าของและวงจรอัปเดตเดียวกับ Go
WHY: ลายเซ็นปกป้องความถูกต้อง ไม่ได้ซ่อนข้อมูล
ลายเซ็นดิจิทัลทำหน้าที่เหมือนตราประทับบนซอง ผู้รับยังเห็นเนื้อหา แต่ตรวจได้ว่าใครเซ็นและเนื้อหาไม่ถูกเปลี่ยน ML-DSA อาศัยปัญหาบน lattice ซึ่งออกแบบให้ต้านการโจมตีจาก quantum computer ที่ทราบในปัจจุบัน ต่างจาก encryption ซึ่งทำให้คนที่ไม่มีกุญแจอ่านข้อมูลไม่ได้
อย่ามองคำว่า post-quantum เป็นสวิตช์เปิดแล้วปลอดภัยทุกเรื่อง Algorithm ใหม่มี key และ signature ใหญ่กว่าแบบ elliptic curve ต้องคิดถึง database column, protocol frame, certificate chain, bandwidth และ hardware keystore ด้วย การเริ่มจาก artifact ภายในที่อายุยาวจึงเสี่ยงน้อยกว่าการเปลี่ยน public protocol ทั้งระบบทันที
HOW: ใช้ Context กันลายเซ็นข้ามงาน
สมมติบริษัทเซ็น payload เดียวกันในสองระบบ: อนุมัติ invoice กับอนุมัติ deployment หากเซ็นแต่ bytes ของ payload ผู้โจมตีอาจยกลายเซ็นจากระบบหนึ่งไปใช้อีกระบบได้ mldsa.Options.Context ผูกจุดประสงค์เข้าไปในลายเซ็น เหมือนตราประทับที่ระบุว่าซองนี้เข้าได้เฉพาะประตูใด
package signatures
import (
"crypto/mldsa"
"testing"
)
func TestMLDSAContextSeparatesPurposes(t *testing.T) {
privateKey, err := mldsa.GenerateKey(mldsa.MLDSA44())
if err != nil {
t.Fatal(err)
}
publicKey := privateKey.PublicKey()
message := []byte("invoice:4821:approved")
invoice := &mldsa.Options{Context: "invoice-approval"}
signature, err := privateKey.Sign(nil, message, invoice)
if err != nil {
t.Fatal(err)
}
parsed, err := mldsa.NewPublicKey(mldsa.MLDSA44(), publicKey.Bytes())
if err != nil {
t.Fatal(err)
}
if err := mldsa.Verify(parsed, message, signature, invoice); err != nil {
t.Fatalf("valid signature rejected: %v", err)
}
deployment := &mldsa.Options{Context: "deployment-approval"}
if err := mldsa.Verify(parsed, message, signature, deployment); err == nil {
t.Fatal("signature was accepted in the wrong context")
}
}
test นี้ตรวจทั้ง happy path และ misuse path หากลบบริบทหรือใช้ค่าเดียวกันทั้งสองงาน assertion หลังต้องจับความผิดปกติได้ ตัวอย่างเลือก ML-DSA-44 ซึ่งเป็น parameter set ระดับเริ่มต้นของ package ไม่ได้แปลว่าเหมาะกับทุก policy ให้ทีม security เลือกตาม threat model และ ecosystem ที่ต้อง interoperate
แผนย้ายที่ไม่ผูกตัวเองกับ Algorithm เดียว
เก็บ algorithm identifier, public key identifier และ context ไปพร้อม signature เสมอ อย่าฝังความหมายว่า column นี้เป็น ML-DSA-44 ตลอดชีวิต เพราะ migration ครั้งหน้าอาจต้องใช้ parameter set อื่นหรือ hybrid signature ที่เซ็นด้วย algorithm เดิมและใหม่คู่กัน
private key ต้องอยู่ในระบบจัดการกุญแจที่มี access control, rotation และ audit ไม่ควร serialize ลง config หรือ log แม้ตัวอย่างจะสร้าง key ใน memory ก็ตาม ส่วน public key ต้องกระจายผ่านช่องทางที่ยืนยันแหล่งที่มาได้ มิฉะนั้นผู้โจมตีเปลี่ยนทั้งเอกสารและ public key แล้วการ verify ก็ยังผ่าน
สุดท้ายคือ interoperability: ทดสอบ known-answer vector และแลกตัวอย่างกับ implementation ภาษาอื่นก่อนใช้ข้ามองค์กร Cryptography ที่ unit test ฝั่งเดียวผ่านอาจยังผิดที่ encoding, context หรือ parameter set ได้
Recap
crypto/mldsa ใน Go 1.27 เปิดทางให้ทีมเริ่มสำรวจลายเซ็น post-quantum ด้วย standard library แต่การพร้อมจริงต้องรวม context separation, key management, algorithm agility และการทดสอบข้าม implementation
พรุ่งนี้ลองเลือก artifact อายุยาวหนึ่งชนิด วัดขนาด key/signature และเพิ่ม metadata ที่บอก algorithm กับ context ก่อนคิดถึง rollout ใหญ่ เราจะเห็นต้นทุนจริงเร็วกว่าเดาจากชื่อ algorithm ครับ