contentWeb上でパスワード不要のE2E暗号化してセキュアにファイル転送をしたいJavaScriptWebセキュリティなにを目指しているか?多くのクラウドストレージやメールを使ったファイル転送ではクライアントとサーバー間の暗号化はされています。その多くの場合サーバー内では生のデータもしくは暗号化されていてもサーバー内で復号可能の場合が多いと思います。そこで送受信を行う端末間でエンドツーエンド暗号化(E2E暗号化)してサーバー側にも分からない形してサーバーを信じなくても良い、より高度なセキュリティを目指したいです。それと同時に安全性かつ手軽にファイルを転送を重視したいです。一般にセキュリティを強めると不便になったりして、安全性と利便性にトレードオフがあると思います。このトレードオフをなるべく解決して、安全性と利便性の両立して安全性と手軽さを両立することを考えました。ユーザーのパスワードの入力不要で、手軽にセキュアに転送するために使った技術に関して後述します。UIと呼んでいて以下のURLでスマホやPCなどブラウザが使えるデバイスで利用できます。https://github.com/nwtgck/piping-ui-web以下に暗号化以外の話があります。UIにおけるパスワードなしのE2E暗号化パスワード不要というのはファイルを暗号化するパスワードが一切不要ということです。話題になるパスワード付きZIPのパスワードのようなものが一切不要で、転送ごとに暗号化用の鍵がランダムに変わります。115792089237316195423570985008687907853269984665640564039457584007913129639936$の組みわせがあります。通信ごとに変わる一度しか使われない鍵に115792892無量大数3731不可思議6195那由他4235阿僧祇7098恒河沙5008極6879載785正3269澗9846溝6564穣564𥝱394垓5758京4007兆9131億2963万9936の膨大な鍵の組み合わせが考えられます。ユーザーが記憶できるパスワードの数や長さの限界を超えたセキュリティが実現できるのではと思います。そのため、例え暗号データを傍受した悪い人にパスワードを言うように脅されたとしても、原理的に誰もその鍵を教えることはできなく安心です(脅されるとか多分ないけど)。この鍵を使ってブラウザ側で暗号化を施すためサーバー側を信用できなくても安心して転送が可能です。速度の心配もあるかもしれないので、ブラウザ側での暗号化周りの速度に関して後述します。(ECDH)を利用しています。ECDHでは、送信者と受信者が互いに公開鍵と秘密鍵を作って、そのうちの公開鍵同士を交換します。互いに公開鍵とそれぞれ持っている別々の秘密鍵から送信者と受信者で同じ乱数値が生成できるようになります。その送信者と受信者で同じ値になる乱数値を共有鍵として利用できます。小人さんの妄想」が分かりやすかったです。ALIS」が分かりやすかったです。(ECDH)をブラウザ上で実現するかに関してです。APIが用意されていて多くのブラウザ上で利用可能です。ECDHのキーペアは以下のようにシンプルに生成可能です。(JWK)として取得可能で、通信の時も扱いやすいJSONが手に入ります。Qiita」などにあります。鍵生成などの速度に関して後述していて、その中のCodepenもサンプルコードになるかもしれません。OpenPGP.jsECDHで送信者と受信者で共通鍵の共有ができた後、OpenPGPの形式で共通鍵での暗号化をしています。その際にOpenPGP.jsを利用しています。パスワード付きで暗号化する機能をgpgコマンドとcurlコマンドでCLIからでもブラウザからでも扱いやすくするためにOpenPGPを使っています。Ota」にまとめています。どれぐらいブラウザでの暗号化などは速いのか?最初、ブラウザで鍵生成したり暗号化・復号って時間かかりそうと思っていましたが、実際のところかなり速いです。Cryptoで以下の一連の処理を100回しても220ミリ秒ぐらいです。miniでも624ミリ秒でした。CryptoでのECDHの鍵生成やJSONへのエクスポートなど方法の参考にもなると思います。Qiita」を参考にしています。この速度ならWebフロントエンドで暗号化/復号しても良さそうだと思いました。OpenPGP.jsだとReadableStreamを暗号化/復号可能で、たとえばダウンロードと復号を同時に行うことが可能です。UIにおける鍵共有と暗号化の流れECDHの公開鍵を送信者と受信者間で交換する。送信者と受信者がそれぞれ公開鍵から共有鍵を算出する。送信するユーザーが受信者の確認コードを確認する。送信するユーザーの確認して送信を開始する。以下が鍵共有に対応するコードです。https://github.com/nwtgck/piping-ui-web/blob/37e302e031ec11582401684194419268fd5adabc/src/piping-ui-utils.ts#L96-L149確認コードがある理由は中間者攻撃が防ぐためです。暗号化していても悪意のある中間者に向かって暗号化して送信する可能性があるため、送信者が想定している受信者なのかを確認できるようにしています。防ぎたいのはデータが想定してない受信者に漏れることなので送信者が受信者を確認するようになっています。クライアントとサーバー間はHTTPSで通信路は守られていて、中間者攻撃するためにはサーバーをクラックするか、もともと悪意のあるサーバーでないといけないなど中間者攻撃の可能性は低いかもしれません。(https://github.com/nwtgck/piping-ui-web/blob/37e302e031ec11582401684194419268fd5adabc/src/piping-ui-utils.ts#L151-L159)。UIの転送は、自分の他のデバイスや物理的に近くの人や電話越しの相手など想定しているため、その時に確認コードを伝えること想定しています。その場で転送をするという点でAirDropのマルチデバイス間で使える版に近いかもしれません。Serverを使っています。Qiita」が参考になると思います。runですぐに立てる方法を紹介しています。UIで転送できるようになりました。パスワードなしでE2E暗号化するということは特に新しくなく枯れた技術なのではないかと思います。広まっているHTTPSも、当たり前ですがデータを暗号化するためにユーザーのパスワードはなく、クライアントとサーバー間で暗号化していて同じことなのではと思います。upLoginユーザーは見つかりませんでした。