std.crypto
ハッシュと、安全な乱数。
ハッシュは、元に戻せない短い指紋を作る。中身が同じか比べたり、覚えておいて後で見比べたりするのに使う。乱数は、当てられては困るもの(合言葉、鍵、印)に使う。さいころのような、当てられてもよい乱数は std.math の方が速い。
ハッシュは bytes で返る。目に見える形にするには bytes の to_hex() を使い、戻すには string の from_hex() を使う。
import std.crypto;
print(crypto.sha256("さめ").to_hex());
// b413c5bcae54c44566a68120d42e6f4801fa98d375ff61442d2f628e69cdf6b6
- crypto.sha256(data: bytes) → bytes¶
-
SHA-256 のハッシュ。32 バイト返す。
迷ったらこれを使う。string を渡すと、その UTF-8 の並びをそのまま数える。
オーバーロード:
crypto.sha256(data: string) -> bytesdata bytes ハッシュにしたいもの print(crypto.sha256("abc").to_hex()); // ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
- crypto.sha512(data: bytes) → bytes¶
-
SHA-512 のハッシュ。64 バイト返す。
オーバーロード:
crypto.sha512(data: string) -> bytesprint(crypto.sha512("abc").to_hex().len()); // 128
- crypto.sha1(data: bytes) → bytes¶
-
SHA-1 のハッシュ。20 バイト返す。
オーバーロード:
crypto.sha1(data: string) -> bytesもう安全ではない。中身が違うのに同じ指紋になるものを、人が作れてしまう。
古い決まりに合わせるときだけ使い、新しく作るものには sha256 を使う。
print(crypto.sha1("abc").to_hex()); // a9993e364706816aba3e25717850c26c9cd0d89d
- crypto.md5(data: bytes) → bytes¶
-
MD5 のハッシュ。16 バイト返す。
オーバーロード:
crypto.md5(data: string) -> bytessha1 よりもっと安全ではない。取り違えを見つけるためだけに使う。
合言葉や署名には使わない。
print(crypto.md5("abc").to_hex()); // 900150983cd24fb0d6963f7d28e17f72
- crypto.hmac_sha256(key: bytes, data: bytes) → bytes¶
-
鍵つきのハッシュ(HMAC-SHA-256)。32 バイト返す。
鍵を知っている人だけが同じ値を作れる。「確かに自分が作った」という印になる。鍵を知らずに sha256 で作り直すことはできない。
オーバーロード:
crypto.hmac_sha256(key: bytes, data: string) -> bytescrypto.hmac_sha256(key: string, data: bytes) -> bytescrypto.hmac_sha256(key: string, data: string) -> byteskey bytes 合言葉。人に見せない data bytes 印を付けたいもの print(crypto.hmac_sha256("key", "さめ").to_hex()); // 77cef4ed2af2a6624a09211542a025748180c17022b7eeb0b5880fd03dcab152
- crypto.hmac_sha512(key: bytes, data: bytes) → bytes¶
-
鍵つきのハッシュ(HMAC-SHA-512)。64 バイト返す。
オーバーロード:
crypto.hmac_sha512(key: bytes, data: string) -> bytescrypto.hmac_sha512(key: string, data: bytes) -> bytescrypto.hmac_sha512(key: string, data: string) -> bytesprint(crypto.hmac_sha512("key", "さめ").len()); // 64
- crypto.equal(a: bytes, b: bytes) → bool¶
-
同じ中身かどうかを、時間の差が出ない形で比べる。
== と結果は同じだが、掛かる時間が中身で変わらない。合言葉や印を見比べるときは、こちらを使う。途中まで合っているほど返事が遅い、という差から中身を当てられるため。
オーバーロード:
crypto.equal(a: string, b: string) -> boolvar a = crypto.hmac_sha256("key", "さめ"); var b = crypto.hmac_sha256("key", "さかな"); print(crypto.equal(a, a)); // true print(crypto.equal(a, b)); // false
- crypto.random_bytes(n: int) → bytes¶
-
当てられては困る乱数を、n バイト取る。
機器の真の乱数を先に試し、取れなければ暗号学的に安全な乱数で埋める。どちらから取れたかは source() で分かる。弱い乱数で埋めてごまかすことはしない(もとが無ければ実行時エラー)。
n int ほしいバイト数。0 から 1048576 まで 乱数のもとを持たない処理系では実行時エラーになる。
先に source() を見れば、持っているかどうかが分かる。
print(crypto.random_bytes(16).len()); // 16
- crypto.random_int(lo: int, hi: int) → int¶
-
lo 以上 hi 以下の乱数を1つ。random_bytes と同じもとから取る。
どの数も同じ出やすさになるよう、偏る分は引き直している。
lo int 下限。この数も出る hi int 上限。この数も出る var d = crypto.random_int(1, 6); print(d >= 1 && d <= 6); // true
- crypto.uuid4() → string¶
-
重ならない名前を作る。UUID の版4(乱数から作る形)で、36 文字の文字列。
名前に 4 が付いているのは、この形が版4だという意味。時刻や機器の番号からは作らないので、いつどこで作ったかは残らない。
print(crypto.uuid4().len()); // 36 print(crypto.uuid4() == crypto.uuid4()); // false
- crypto.source() → string¶
-
乱数エントロピー源の種別を判定して返す。
戻り値: "true" ハードウェア真性乱数(TRNG)。エントロピー源に基づく予測不可能な乱数 "secure" 暗号学的に安全な擬似乱数(CSPRNG)。ハードウェア乱数生成器が利用できない場合のフォールバック "none" 乱数生成器が利用不可。乱数生成関数呼び出し時はパニックが発生する
var s = crypto.source(); print(s == "true" || s == "secure"); // true(乱数を使える処理系)