std.crypto

ハッシュと、安全な乱数。

ハッシュは、元に戻せない短い指紋を作る。中身が同じか比べたり、覚えておいて後で見比べたりするのに使う。乱数は、当てられては困るもの(合言葉、鍵、印)に使う。さいころのような、当てられてもよい乱数は std.math の方が速い。

ハッシュは bytes で返る。目に見える形にするには bytes の to_hex() を使い、戻すには string の from_hex() を使う。

import std.crypto;
print(crypto.sha256("さめ").to_hex());
// b413c5bcae54c44566a68120d42e6f4801fa98d375ff61442d2f628e69cdf6b6
crypto.sha256 crypto.sha512 crypto.sha1 crypto.md5 crypto.hmac_sha256 crypto.hmac_sha512 crypto.equal crypto.random_bytes crypto.random_int crypto.uuid4 crypto.source
crypto.sha256(data: bytes) → bytes

SHA-256 のハッシュ。32 バイト返す。

迷ったらこれを使う。string を渡すと、その UTF-8 の並びをそのまま数える。

オーバーロード: crypto.sha256(data: string) -> bytes

databytesハッシュにしたいもの
print(crypto.sha256("abc").to_hex());
// ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
crypto.sha512(data: bytes) → bytes

SHA-512 のハッシュ。64 バイト返す。

オーバーロード: crypto.sha512(data: string) -> bytes

print(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) -> bytes

sha1 よりもっと安全ではない。取り違えを見つけるためだけに使う。

合言葉や署名には使わない。

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) -> bytes crypto.hmac_sha256(key: string, data: bytes) -> bytes crypto.hmac_sha256(key: string, data: string) -> bytes

keybytes合言葉。人に見せない
databytes印を付けたいもの
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) -> bytes crypto.hmac_sha512(key: string, data: bytes) -> bytes crypto.hmac_sha512(key: string, data: string) -> bytes

print(crypto.hmac_sha512("key", "さめ").len());   // 64
crypto.equal(a: bytes, b: bytes) → bool

同じ中身かどうかを、時間の差が出ない形で比べる。

== と結果は同じだが、掛かる時間が中身で変わらない。合言葉や印を見比べるときは、こちらを使う。途中まで合っているほど返事が遅い、という差から中身を当てられるため。

オーバーロード: crypto.equal(a: string, b: string) -> bool

var 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() で分かる。弱い乱数で埋めてごまかすことはしない(もとが無ければ実行時エラー)。

nintほしいバイト数。0 から 1048576 まで

乱数のもとを持たない処理系では実行時エラーになる。

先に source() を見れば、持っているかどうかが分かる。

print(crypto.random_bytes(16).len());   // 16
crypto.random_int(lo: int, hi: int) → int

lo 以上 hi 以下の乱数を1つ。random_bytes と同じもとから取る。

どの数も同じ出やすさになるよう、偏る分は引き直している。

loint下限。この数も出る
hiint上限。この数も出る
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(乱数を使える処理系)