新機能
post-quantum署名アルゴリズムML-DSA(FIPS 204)を実装するcrypto/mldsaパッケージを新設し、crypto/x509・crypto/tlsにもML-DSA鍵・証明書・TLS 1.3署名のサポートを追加する。
New crypto/mldsa package
この項目の注釈は AI により生成されており、誤りを含む場合があります。
使用例のコンパイル検証: 検証済み
概要
新しいcrypto/mldsaパッケージが、FIPS 204で規定されたpost-quantum署名アルゴリズムML-DSAを実装する。Go 1.26で内部実装(crypto/internal/fips140/mldsa)として追加されていたML-DSAが、Go 1.27でようやく公開APIとして利用可能になる。
あわせてcrypto/x509がML-DSAの秘密鍵・公開鍵・署名に対応し、crypto/tlsもTLS 1.3のハンドシェイク署名としてMLDSA44・MLDSA65・MLDSA87の各SignatureScheme値をサポートする。これにより、量子コンピュータ耐性を持つデジタル署名を標準ライブラリのみで生成・検証でき、証明書の発行やTLS通信にも組み込めるようになる。
導入経緯
本機能は2件のproposalの合意内容を統合したものである。
- #77626「crypto/mldsa: new package」は、Go 1.26で内部実装のみだったML-DSAを公開APIとして
crypto/mldsaに切り出す提案である。提案者はGoのセキュリティチームの一員で、事前にfilippo.io/mldsaとしてプレビュー実装を公開し動作検証を済ませていた。 - #78888「crypto/x509,crypto/tls: add ML-DSA support」は、#77626のAPIを前提として
crypto/x509とcrypto/tlsにML-DSA対応を追加する提案である。量子コンピュータ(CRQC)の実用化タイムラインが前倒しになっていること、WebPKIが検討するMerkle Tree Certificatesへの移行が2027年頃になる見込みで、プライベートPKIの移行はそれより早急に必要であることが動機として挙げられている。コンポジット署名(従来署名との組み合わせ)は意図的にスコープ外とされた。
議論タイムライン
- 2026-02-25: #77626がproposal reviewの active リストに追加される。
- 2026-04-15: #77626が、ドキュメントコメントの修正を条件に likely accept と判定される。
- 2026-04-22: #77626がコンセンサス変更なしとして accepted となる。同日、#78888が active リストに追加される。
- 2026-04-29: #78888が likely accept と判定される。
- 2026-05-06: #78888がコンセンサス変更なしとして accepted となる。
議論のハイライト
Parameters型はポインタでなく値型:MLDSA44()等がシングルトンを返す設計であることから、aclementsの指摘により*Parametersではなく値型Parametersを返すよう変更された。*MLDSA44() = MLDSA65()のような誤操作を防ぐためである。- 秘密鍵はseed形式のみサポート: NISTが規定した「semi-expanded形式」はサイズが大きく読み込みも遅い上に危険性が高いとして、Goは32バイトのseedのみをサポートする方針を採った。BoringSSLも同方針である。
- HashML-DSAは非サポート: 外部ハッシュ済みメッセージの利用は、RFC 9881が推奨する「External μ」方式で代替する。これを表現するため
crypto.Hashに実装を持たないセンチネル値crypto.MLDSAMuを追加する設計とし、crypto.MD5SHA1に前例があるとされた。 SignDeterministicを独立メソッドにした理由: 決定論的署名はSignにのみ関係しVerifyとは無関係なため、両者で共有するOptions構造体のフィールドにはせず、専用メソッドとして分離した。NewPrivateKeyの命名: 実体は seed のアンマーシャリング関数であり名前から分かりにくいという指摘があったが、crypto/ecdhのCurve.NewPrivateKeyやcrypto/mlkemのNewDecapsulationKey768に前例があるとして現状の名前を維持した。- X.509証明書サポートの分離: #77626の時点ではWebPKI・ブラウザ側のポスト量子署名の扱いが未定だったためコア機能のみとし、X.509対応は#78888として別提案にした。
使用例
Before
package main
import (
"crypto/ed25519"
"crypto/rand"
"fmt"
"log"
)
func main() {
pub, priv, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
log.Fatal(err)
}
message := []byte("hello, world")
sig := ed25519.Sign(priv, message)
if !ed25519.Verify(pub, message, sig) {
log.Fatal("invalid signature")
}
fmt.Printf("public key: %d bytes, signature: %d bytes\n", len(pub), len(sig))
}
After
package main
import (
"crypto/mldsa"
"fmt"
"log"
)
func main() {
sk, err := mldsa.GenerateKey(mldsa.MLDSA44())
if err != nil {
log.Fatal(err)
}
message := []byte("hello, world")
opts := &mldsa.Options{Context: "example"}
sig, err := sk.Sign(nil, message, opts)
if err != nil {
log.Fatal(err)
}
pk := sk.PublicKey()
if err := mldsa.Verify(pk, message, sig, opts); err != nil {
log.Fatal("invalid signature: ", err)
}
fmt.Printf("public key: %d bytes, signature: %d bytes\n", len(pk.Bytes()), len(sig))
}
移行時の注意
- 秘密鍵は32バイトのseedのみサポートする。semi-expanded形式には対応しない。
- 署名時と検証時で
Options.Context(最大255バイト)を一致させる必要がある。 - FIPS 140-3 Go Cryptographic Moduleのv1.0.0を使用している場合、
crypto/mldsaは利用できず、GenerateKey・NewPrivateKey・NewPublicKey・Verifyはエラーを返す。v1.26.0以降であれば利用可能である。 crypto/x509・crypto/tlsが対応するのはpure ML-DSA署名のみで、コンポジット署名(従来アルゴリズムとの組み合わせ)は対象外である。crypto/tlsのMLDSA44/MLDSA65/MLDSA87(0x0904〜0x0906)はIANAのTLS SignatureSchemeレジストリに登録済みのコードポイントだが、対応するTLS仕様のdraft-ietf-tls-mldsa-02自体はまだドラフト段階である。
実装解説
crypto/mldsaの公開APIは、パラメータ表現と鍵・署名処理の2つのファイルに分かれている。
Parametersはname・publicKeySize・signatureSizeを保持する値型で、MLDSA44/MLDSA65/MLDSA87がそれぞれ対応する定数値を詰めた構造体を返すシングルトン関数になっている。PrivateKey/PublicKeyは内部実装crypto/internal/fips140/mldsaの型を1フィールドでラップするだけの薄いラッパーである(mldsa_fips140v1.26.go:20)。PrivateKey.Signはopts.HashFunc()の値で分岐しており、ゼロ値なら通常のメッセージ署名(mldsa.Sign)、crypto.MLDSAMuならExternal μの事前ハッシュ済み署名(mldsa.SignExternalMu)に処理を振り分ける。SignDeterministic(同ファイル:125)も同様の分岐を持つ。crypto/x509側では、PublicKeyAlgorithmにMLDSA定数、SignatureAlgorithmにMLDSA44/MLDSA65/MLDSA87定数が既存のiota列挙に追加され、対応するASN.1 OID(oidPublicKeyMLDSA44ほか)と紐付けられている。crypto/tls側では、MLDSA44/MLDSA65/MLDSA87SignatureScheme定数(0x0904〜0x0906)が追加され、ハンドシェイク署名の検証パス(common.go:1800)で他の署名方式と同様に扱われている。
関連リンク
- go.dev リリースノート (go1.27) go.dev
- Proposal Issue #77626 github.com/golang/go
- Proposal Issue #78888 github.com/golang/go
- pkg.go.dev/crypto/mldsa pkg.go.dev
- pkg.go.dev/crypto/x509 pkg.go.dev
- pkg.go.dev/crypto/tls pkg.go.dev
- 2026 W09 ダイジェスト(active) digest
- 2026 W16 ダイジェスト(active → likely_accept) digest
- 2026 W17 ダイジェスト(likely_accept → accepted) digest
- 2026 W17 ダイジェスト(active) digest
- 2026 W18 ダイジェスト(active → likely_accept) digest
- 2026 W19 ダイジェスト(likely_accept → accepted) digest