本文へスキップ
ecdsa.com
Rust

aws-lc-rs

AWS の aws-lc-rs は、AWS-LC の C ライブラリ上に構築された ring 互換の Rust API です。ring と同じ FIXED/ASN1 のエンコーディング定数に加え、安定版 API で P-521、secp256k1、ML-KEM、ML-DSA を提供し、オプションで FIPS 140-3 ビルドも利用できます。
ライセンス
ISC AND (Apache-2.0 OR ISC)
確認したバージョン
1.18.2 ·
ソースコード
github.com/aws/aws-lc-rs
ドキュメント
docs.rs/aws-lc-rs/1.18.2/aws_lc_rs/

互換性の概要

ECDSAEdDSAポスト量子暗号

ECDSA の曲線
P-256P-384P-521secp256k1
EdDSA
Ed25519
公開鍵の形式
spki-dersec1-uncompressedsec1-compressed
秘密鍵の形式
pkcs8-dersec1-derraw-scalar

aws-lc-rs は、Amazon による BoringSSL のフォークである AWS-LC を、ring をモデルにした API で公開しており、ほとんどの ring のコードはクレート名を変えるだけでコンパイルできます。rustls のデフォルトの暗号プロバイダーであり、FIPS 140-3 の認証(fips フィーチャー)やポスト量子アルゴリズムを必要とする Rust のサービスが採用するライブラリです。C ライブラリはビルド時にコンパイルされます。チェックでは、素の rust イメージでデフォルトのフィーチャーを使って 1.18.2 をビルドしました。

署名のエンコーディングは ring とまったく同じように動作します。*_FIXED 定数は 64 バイトの生の r‖s を生成・受理し、*_ASN1 定数は DER を扱います。生の署名は ASN1 の検証用定数では失敗しました。nonce はランダムで、s は正規化されず、検証は low-S と high-S のどちらも受け入れます。ring の P-256 と P-384 に加え、P-521 と secp256k1 でも、SHA-2 と SHA-3 の各バリアントで署名と検証ができます。

1.18.2 ではポスト量子アルゴリズムが安定版 API に含まれています(チェックは unstable フィーチャーなしでビルドしました)。aws_lc_rs::kem に ML-KEM-512、ML-KEM-768、ML-KEM-1024 が、aws_lc_rs::signature に ML-DSA-44、ML-DSA-65、ML-DSA-87 があり、サンプルではこれらを使っています。サンプルが出力するサイズ(ML-DSA-65 では公開鍵 1952 バイトと署名 3309 バイト、ML-KEM-768 では暗号文 1088 バイト)は、証明書、トークン、ハンドシェイクが運ばなければならない量です。ポスト量子署名ラボと KEM ラボでは、これらを従来のアルゴリズムと比較できます。

鍵の読み込みは ring より幅広く対応しています。ECDSA の鍵は PKCS#8、SEC1(RFC 5915)の DER、公開鍵付きの生のスカラーから、公開鍵は SPKI の DER と、圧縮・非圧縮の SEC1 の点から読み込めます。ring と異なり、Ed25519KeyPair::from_pkcs8 は OpenSSL が書き出す 48 バイトの PKCS#8 v1 形式を受け入れました。

FIXED/ASN1 の取り違えが疑われるときは DER ⇄ 生形式の変換ツールを、ハイブリッドのポスト量子鍵交換の設定には TLS 設定生成ツールを使ってください。

事実とその根拠となるチェック

以下の内容はドキュメントからの転記ではありません。2026年10月20日に、チェック content/libraries/verify/aws-lc-rs/run.sh がコンテナイメージ rust:1.99.1-trixie 内で aws-lc-rs 1.18.2 を実行しました。このページの内容はその出力と一致していなければならず、各事実には該当する出力行を示しています。

  • ECDSA 署名のエンコーディング

    der-or-raw

    *_FIXED 定数は 64 バイトの生の r‖s で、*_ASN1 定数は DER で署名します。生の署名は ASN1 定数では検証を通りませんでした。

    チェックによる記録
    fact ecdsa-signature-encoding = der-or-raw
    evidence ecdsa-signature-encoding: FIXED signs 64 bytes; the same bytes verify under the ASN1 constant: false
  • ECDSA の nonce

    random

    nonce はランダムです。同じメッセージの 2 つの署名は異なります。

    チェックによる記録
    fact ecdsa-nonce = random
  • 署名時の low-S

    either

    s は正規化されません。64 個の署名の中に high-S の値が現れました。

    チェックによる記録
    fact ecdsa-low-s-sign = either
  • 検証時の high-S

    accepts-high-s

    FIXED 定数による検証は、s を n − s に置き換えた署名を受け入れました。

    チェックによる記録
    fact ecdsa-low-s-verify = accepts-high-s
  • 署名呼び出しがハッシュする対象

    hashes-message

    メッセージは、定数で指定されたアルゴリズム(SHA-2 または SHA-3 のバリアント)でハッシュされます。

    チェックによる記録
    fact ecdsa-prehash = hashes-message
  • 不正な形式の ECDSA 署名

    returns-error

    形式の誤った署名や正しくない署名に対して、検証はエラー値を返します。

    チェックによる記録
    fact ecdsa-malformed-signature = returns-error
  • ECDSA の曲線

    P-256P-384P-521secp256k1

    P-256、P-384、P-521、secp256k1 で署名と検証ができました。

    チェックによる記録
    fact ecdsa-curves = P-256, P-384, P-521, secp256k1
  • EdDSA

    Ed25519

    Ed25519 です。

    チェックによる記録
    fact eddsa = Ed25519
  • Ed25519 の PKCS #8 v1 鍵

    accepted

    Ed25519KeyPair::from_pkcs8 は、ring が拒否する 48 バイトの PKCS#8 v1 形式の Ed25519 鍵を受け入れました。

    チェックによる記録
    fact ed25519-pkcs8-v1 = accepted
    evidence ed25519-pkcs8-v1: 48-byte PKCS#8 v1 Ed25519 key with from_pkcs8: Ok("ok")
  • ポスト量子アルゴリズム

    ML-KEMML-DSA

    unstable フィーチャーなしでビルドし、ML-KEM-512/768/1024 でカプセル化とデカプセル化を、ML-DSA-44/65/87 で署名と検証を行えました。

    チェックによる記録
    fact pqc = ML-KEM, ML-DSA
    evidence pqc: ML-KEM-512/768/1024 via aws_lc_rs::kem; ML-DSA-44/65/87 via aws_lc_rs::signature
  • 公開鍵の形式

    spki-dersec1-uncompressedsec1-compressed

    ParsedPublicKey による SPKI DER と、圧縮・非圧縮の SEC1 の点です。

    チェックによる記録
    fact public-key-formats = spki-der, sec1-uncompressed, sec1-compressed
  • 秘密鍵の形式

    pkcs8-dersec1-derraw-scalar

    PKCS#8 DER、SEC1(RFC 5915)DER、公開鍵と組み合わせた生のスカラーです。

    チェックによる記録
    fact private-key-formats = pkcs8-der, sec1-der, raw-scalar

使い方

ML-DSA-65 で署名と検証を行い、ML-KEM-768 のカプセル化を実行して、鍵、署名、暗号文のサイズを出力します。
use aws_lc_rs::kem::{DecapsulationKey, ML_KEM_768};
use aws_lc_rs::signature::{self, KeyPair, PqdsaKeyPair, UnparsedPublicKey};

fn main() {
    // ML-DSA-65 (FIPS 204) through the stable signature API.
    let key = PqdsaKeyPair::generate(&signature::ML_DSA_65_SIGNING).unwrap();
    let message = b"release v2.0 manifest";
    let mut sig = vec![0u8; signature::ML_DSA_65_SIGNING.signature_len()];
    let len = key.sign(message, &mut sig).unwrap();
    let ok = UnparsedPublicKey::new(&signature::ML_DSA_65, key.public_key().as_ref()).verify(message, &sig[..len]);
    println!("ML-DSA-65: public key {} bytes, signature {len} bytes, verified {}", key.public_key().as_ref().len(), ok.is_ok());

    // ML-KEM-768 (FIPS 203): the receiver publishes the encapsulation key.
    let receiver = DecapsulationKey::generate(&ML_KEM_768).unwrap();
    let (ciphertext, sender_secret) = receiver.encapsulation_key().unwrap().encapsulate().unwrap();
    let receiver_secret = receiver.decapsulate(ciphertext.as_ref().into()).unwrap();
    println!("ML-KEM-768: ciphertext {} bytes, shared secrets match {}", ciphertext.as_ref().len(), sender_secret.as_ref() == receiver_secret.as_ref());
}

スニペットのテストハーネスは、すべてのサンプルをコンテナイメージ rust:1.99.1-trixie 内でそのまま実行し、出力が一致しなければ実行は失敗します。

コマンド
cargo run --quiet --release
一致すべき出力(正規表現)
ML-DSA-65: public key 1952 bytes, signature 3309 bytes, verified true\nML-KEM-768: ciphertext 1088 bytes, shared secrets match true

ライブラリ