前回記事で Rust を使って WebAssembly を作りましたが、実はこれが目的でした。
deno 向けパッケージでちょうどいいものが無かったので、Rust の csrf クレートを使えないかと考えていたわけです。
いろいろ試して実現できたので、メモがてら書いていきます。
参考
- docs.rs - Crate getrandom
- mdn - Crypto.getRandomValues()
- training.linuxfoundation.org - サーバー側で Rust で記述された Web アセンブリを使用する
- The
wasm-bindgen
Guide - The
wasm-bindgen
Guide - Deploying Rust and WebAssembly - crates.io - rust-csrf
- docs.rs - Crate csrf
- stackoverflow - How do I “use” or import a local Rust file? [duplicate]
- github - rust-random/getrandom
- docs.rs - Struct rand::rngs::OsRng
- github - rust-random/rand - WASM support
- github - rust-lang/rust-bindgen
- Rust By Example – Extended Edition
- The Rust Rand Book
- github - chronotope/chrono
- docs.rs - Struct csrf::AesGcmCsrfProtection
- qiita - wasm-bindgen で Rust から JS へ JSON を渡す
- stackoverflow - How to create a JS array of Strings from Rust using web_sys?
- 色の輪 - Rust で文字列・ファイル、両方から byte を読みたいだけなのに
- zenn - RustCoder ―― AtCoder と Rust で始める競技プログラミング入門
- kanejaku.org - Rust で wasm 用カスタムアロケータを書く
- stackoverflow - How do I convert between String, &str, Vec
and &[u8]? - users.rust-lang.org - Is it safe to transmute slices of transparent structs of byte arrays from byte slices?
やろうとしたこと
- Rust の csrf パッケージを使って、WASM をコンパイル[1]
- deno で、作った WASM を使って CSRF 用のトークンの発行/検証を行う[2]
実行環境
今回は WASM を作る Rust 側と実行する Deno 側をまとめて作ります。
1 | version: "3" |
以下それぞれの Dockerfile です。
1 | FROM rust:latest |
1 | FROM denoland/deno:centos |
WASM を作る
コンパイル用スクリプト
今回、コマンドを度々打ちたくなかったので、コンパイル用スクリプトとして以下のものを用意しました。
1 |
|
以前の記事では wasm-pack
コマンドでコンパイルして一部書き換えをしましたが、本来こちらが正しいようです。
WASM 本体実装
WASM の実装は以下の通りです。
1 | // rust-csrf を deno から使うための WASM 実装 |
Cargo.toml
実は Cargo.toml の記述を調べるのが一番大変でした。
1 | [package] |
時刻や乱数など、一部 OS が提供するようなリソース/機能を WASM から呼ぶときには、features = ~~~
など詳細な指定が必要でした。
コンパイル
用意していたコマンドで、コンパイルします。
1 | $ docker-compose build |
Deno で実行
作成した csrf トークン発行/検証機能を持つ WASM を使う deno のコードが次の通りです。
1 | import { generateTokenPair, verifyTokenPair } from "./pkg/csrf_wasm.js"; |
実行すると次の通りです。
1 | # コンテナは起動済み |
トークンの発行と検証ができました。
実は、BASE64 デコードの失敗時などの対応が取られておらず、クラッシュすることが度々起こります。
TypeScript 側での例外処理が必要なコードになっていますが、とりあえず「作れた」ということが収穫です。
今回は、WASM を使って deno で CSRF の検証機能を実装しました。
Rust 周りの調査を始めると、どうにも日本語情報が多くなく、実働でここまでに 4 日程かかってしまいました。
ただ、ノウハウとしてかなり身についたところを感じているので、かなり収穫だったと感じています。
近日こちらのライブラリは、deno.land で公開する予定です。
公開しました。
github - Octo8080/deno-csrf
ではでは。