読者です 読者をやめる 読者になる 読者になる

cryptoモジュールの乱数生成関数を使う

Erlang

ErlangでセッションID生成のような用途に耐えうる十分安全な乱数生成関数はないものかと調べていたら、どうやらcryptoモジュールのrand_bytes/1rand_uniform/2あたりが近いらしい。

1> crypto:rand_bytes(16).
<<216,145,169,69,119,62,52,12,70,173,20,98,154,143,17,13>>
2> crypto:rand_uniform(0, 9223372036854775807).
1968736488688755614

erlang-questionsに流れていた以下の書き込みを探し当てて気がついた。

cryptoモジュールはOpenSSLのバインディングのようになっていて、rand_bytesの実装はlib/crypto/c_src/crypto.cの688行目あたりにある。

static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Bytes) */
    unsigned bytes;
    unsigned char* data;
    ERL_NIF_TERM ret;
    if (!enif_get_uint(env, argv[0], &bytes)) {
	return enif_make_badarg(env);
    }
    data = enif_make_new_binary(env, bytes, &ret);
    RAND_pseudo_bytes(data, bytes);
    ERL_VALGRIND_MAKE_MEM_DEFINED(data, bytes);
    return ret;
}

OpenSSLのRAND_pseudo_bytesを使っているってことか。RAND_bytesのmanによると、

RAND_pseudo_bytes() puts num pseudo-random bytes into buf. Pseudo-random byte sequences generated by
RAND_pseudo_bytes() will be unique if they are of sufficient length, but are not necessarily
unpredictable. They can be used for non-cryptographic purposes and for certain purposes in
cryptographic protocols, but usually not for key generation etc.

「必ずしも予測不可能というわけではないから、非暗号学的な目的ならば使ってもいいかもね」ということらしい。うむぅ。

他の言語のOpenSSLのバインディングがどうなっているかが気になるところだ。

【追記】PythonpyOpenSSLruby1.9.2のopensslの実装を見たらどちらもRAND_pseudo_bytesではなく、RAND_bytesを使っていた。わざわざOpenSSLを使いたいわけだから、RAND_bytesの方が自然だよねぇ。Erlangのcryptoモジュールの方が謎実装な気がする。