misskey-dev / misskey

🌎 A completely free and open interplanetary microblogging platform 🚀
https://misskey-hub.net/
GNU Affero General Public License v3.0
10.06k stars 1.37k forks source link

Performance: 署名アルゴリズムの変更 / 鍵のサイズの変更 (Change of signature algorithm/cryptographic key size) #11129

Open yuriha-chan opened 1 year ago

yuriha-chan commented 1 year ago

Summary

配送ジョブにおける署名処理が重いので、暗号鍵の方式を変更して軽くしたい。

Details

Misskeyの鍵長がRSA4096bitと、MastodonのRSA2048bitとくらべセキュリティの高い設定になっているため、連合におけるノートの配送のボトルネックとなっている署名処理の計算コストが(7倍程度)大きい。

RSA2048bitで妥協するか、ECDSAやEdDSAなどの安全性を保ちつつ効率の良い署名アルゴリズムを使うことで、計算の負荷を減少させることができる。ECDSAやEdDSAを使うことにする場合、既存のサーバーは対応していないので、ユーザーの鍵はRSAとECDSAの保存しておいて、連合先サーバーとのネゴシエーションによって、渡す公開鍵を決める必要があると思われる。

参考までに各アルゴリズムのOpenSSLによる速度測定例を置いておきます。 (AMD EPYC 7B12: 1CPU当たりの性能)

Additional Info

署名用の暗号鍵はアカウント作成時に生成され、サーバー内に保管される。既存のユーザーの鍵を更新する場合、すべての連合先(一度だけメンションを送ったサーバーなども含む)に新しい鍵になったことを伝えるメッセージを、古い鍵で署名して伝える必要がある。実用的には、古い鍵を破棄せず、新しい鍵と両方持っておく必要があると思われる。

syuilo commented 1 year ago

RSA 2048bitにするか

yuriha-chan commented 1 year ago

とりあえずここを書き換えると新規ユーザーだけ2048bitにできますが、私の見た限りでは、鍵の長さが違うユーザーが混在していても特に問題なく動くみたいです。 https://github.com/misskey-dev/misskey/blob/d2f8ed95aa10bc3200b7c0186c89dee69922d0fb/packages/backend/src/core/SignupService.ts#L95

sorairolake commented 1 year ago

RSA-2048 (セキュリティ強度112 bit) は2030年末までによりセキュリティ強度の高い暗号技術や鍵長に移行することが推奨されています^1。Mastodonなどもこの期限までにRSA-2048から移行する可能性は十分にあると思うので、RSA-2048に移行した場合は再度署名アルゴリズムや鍵長を変更することになる可能性があると思います。

なので、可能であるならばセキュリティ強度が128 bitのRSA-3072に移行するか、EdDSAなどのセキュリティ強度が128 bitの楕円曲線暗号にも対応するのが良いと思います。

sorairolake commented 1 year ago

ECDSA (NIST P-256) とEdDSAなら後者の方が高速かと思ったけどそうでもない?

syuilo commented 1 year ago

とりあえず新規ユーザーだけでも2048bitにしとくか

u1-liquid commented 1 year ago

せっかく変えるならnistp256かed25519にしてほしい感ある rsa2048は2025年12月31日で5年有効期間の証明書の最終発行日となってるので、2023年にこれにするのは流石におかしいかも

syuilo commented 1 year ago

ECDSAやEdDSAを使うことにする場合、既存のサーバーは対応していないので、ユーザーの鍵はRSAとECDSAの保存しておいて、連合先サーバーとのネゴシエーションによって、渡す公開鍵を決める必要があると思われる。

が大変そう

sorairolake commented 1 year ago

セキュリティ強度が128bitの暗号でも2050年末には置き換える必要がありますが、25年以上先のことなので今から移行するなら全く問題ないと思います。なので、RSAのままにするにしても、2030年末には置き換えることになるRSA-2048にするのではなく、RSA-3072にする方が良いと思いますし、少なくともRSA-4096よりはパフォーマンスが向上するはずです。

u1-liquid commented 1 year ago

正しい https://datatracker.ietf.org/doc/draft-ietf-httpbis-message-signatures の実装が先かも 4.3. Multiple Signaturesで複数個の署名の提供ができるので、それで対応できる

ちなみにマストドンはrsa-256とhs2019だけをサポートしてる https://github.com/mastodon/mastodon/blob/1e3b19230a48174acf524cf1a9f5a498e220ea7d/app/controllers/concerns/signature_verification.rb#L83 hs2019はdraft-ietf-httpbis-message-signaturesの03版以降draft-ietf-httpbis-message-signaturesからは消えているが、既に複数のソフトウェアが実装しているもので、 中身のアルゴリズムの名前を出さないことで安全性を高めようとしてたものらしい。実際の中身はなんでも良かったみたい

nvsofts commented 1 year ago

既にリプライがありますが、 RSA-3072にするのがCRYPTREC「暗号強度要件(アルゴリズム及び鍵長選択)に関する設定基準」を考慮した上での、ある程度長期的に安全な方法だと考えます。

tamaina commented 10 months ago

up (ioの配送が大変)

tamaina commented 8 months ago

正しい https://datatracker.ietf.org/doc/draft-ietf-httpbis-message-signatures の実装が先かも

https://datatracker.ietf.org/doc/rfc9421/ になった

HTTPシグネチャで複数の方式で署名できるのはいいとして、"https://www.w3.org/ns/activitystreams" / "https://w3id.org/security/v1" においてユーザーの公開鍵を複数(種類)含めることはできないような…(そういう運用は想定されてないか)

tamaina commented 8 months ago

「publicKeyには今まで通りのRSA4096公開鍵」「拡張したプロパティ(additionalPublicKeys?)に"publicKeyで署名された"楕円曲線等の公開鍵情報(の配列)」を含めるとかどうかしら

tamaina commented 8 months ago

鍵を別の鍵で署名して渡す←RSS3がそんな実装してた気がする

tamaina commented 8 months ago

(というかTLSの証明書チェーンもそうか

tamaina commented 8 months ago

nodeinfoに解釈できる署名関数の種類が入っていてそれに基づいて署名を渡すのが望ましい?

mei23 commented 8 months ago

「publicKeyには今まで通りのRSA4096公開鍵」「拡張したプロパティ(additionalPublicKeys?)に"publicKeyで署名された"楕円曲線等の公開鍵情報(の配列)」を含めるとかどうかしら

名称はともかく多分そんな感じ

nodeinfoに解釈できる署名関数の種類が入っていてそれに基づいて署名を渡すのが望ましい?

「署名を渡す」がなんなのかわからないけど、Activityに署名する際に、相手が何を解釈出来るか (例えばnodeinfo等で) 提供する必要があるわね。

tamaina commented 8 months ago

「署名を渡す」がなんなのか

= ヘッダのSignatureを作る

mei23 commented 8 months ago

実データで検証したのがあったのだわ

image

用語 Sign (Node crypto) → 署名 Verify (Joyent) → 検証 (現行のhttp-signatureモジュール経由のエンジン) Verify (Node crypto) → 検証 (Node標準を使用しての実装)

考察 鍵アルゴリズム間の違いは概ね一般的に言われてる通り。 しかし、Node v16 (OpenSSL v1) に比べて v18 (OpenSSL v3) 以降は性能が大幅に劣化 しかし、JoyentのEdDSAの検証が異様に遅いのでNode標準で実装したほうがいいかも

どのアルゴリズムがいい? RSA vs 楕円曲線 (ECDSA or EdDSA) 楕円曲線系強い、RSAのメリットの検証の速さはOpenSSL3がおうんこになったのでなくなった。

ECDSA vs EdDSA EdDSA強い、ただ現状のJoyent実装の検証は異様に遅いのでNode標準で書き直した方がいい ECDSAは利用可能曲線名のメタデータ連携しなければならなそうなので使いたくないかも (なお現状JoyentのサポートはNISTの3曲線のみ) EdDSAは署名関数が固定なので、現状の署名関数SHA256 or SHA512決め打ちのような面倒がないかも

mei23 commented 8 months ago

上記検証コード https://github.com/mei23/crytest

あと、現状のhttp-signatureモジュールのままed25519にすると、署名が10倍速くなって検証が40倍遅くなるので本末転倒感があるのだわ

KisaragiEffective commented 3 months ago

337b42bcb179bdfb993888ed94342a0158e8f3cb