web-dev-qa-db-ja.com

X25519秘密鍵のASN.1エンコード

Curve25519を使用するECDH鍵合意に mbed TLS を使用しています。秘密鍵と公開鍵は、mbed TLSで簡単に生成できるように、16進文字列として保存および送信されます。これらの文字列はビッグエンディアンです。これまでのところ、これでかなりうまくいきました。

今誰かがOpenSSLを使ってキーペアを作成しようとしました

openssl genpkey -algorithm X25519 -out priv.pem
openssl pkey -in priv.pem -pubout -out pub.pem

そこから直接16進文字列にキーを抽出しました。したがって、ASN.1ビューアを使用してキーバイトをコピーするだけです。 I2OSPがキーエンコーディングのビッグエンディアンを定義しているため、これは問題なく機能するはずだという印象を受けました。

明らかにそれは機能しませんでしたが、有効なキーペアを解析できるようにするには、文字列のバイト順を逆にする必要があります。

私はOpenSSLがこれを正しく行うと信じる傾向がありますが、RFCを掘り下げて証拠といくつかの明確化を見つけ始めました。なぜこれがX25519(おそらくX448)とRSAまたは他のEC曲線のキー(secp)と異なるのか...)

秘密鍵のエンコード方法は、アルゴリズム自体を説明するドキュメントに残されています

しかし、アルゴリズムを定義するドキュメントを再び参照する非対称キーパッケージも参照します。 ECPrivateKeyのRFC5915はビッグエンディアンバイトオーダー(I2OSP)を定義していますが、 RFC7748 および RFC8031 はどちらも、キーのフォーマットのリトルエンディアンバイトオーダーにのみ言及しています。 - draft-ietf-curdle-pkix-1

さて、これはOpenSSLが正しいことをどういうわけか私に確認しますが、他のすべてのアルゴリズムによって行われるようにネットワーク順序を使用するだけでなく、正反対の理由をまだ見逃しています。

それに関する考えや詳細情報はありますか?

1
signpainter

* 25519アルゴはリトルエンディアンを指定します。私自身、そのことにびっくりしたので、その理由を理解しようとしました。私の理解では、Ed25519とその関連のポイントは、可能な曲線の広い空間と実装のサブセットから効率的で多くの攻撃に対して耐性のあるサブセットを選択することです。そのために、計算ステップ、プリミティブ、および使用する表現の両方を指定しています。これはリトルエンディアンです。

したがって、ここで取得するキー表現は、アルゴリズムで使用されるものとまったく同じです。それを逆にする(そして使用する前に再び逆にする必要がある)唯一のポイントは、キー表現の一貫性と、リトルエンディアンの嫌悪感です。

そして、私たち全員が成熟しようとしているので、誰かが、アルゴリズムが使用することを期待するようにキーを保持し、他の不要な変換と混乱を保存することを決定しました。

2
foo