Ticket #35824

random マクロコマンドに大きな値を渡した場合の問題

Date d'ouverture: 2015-12-09 00:22 Dernière mise à jour: 2016-02-09 21:18

Rapporteur:
(del#1144)
Propriétaire:
Type:
État:
Atteints
Composant:
Priorité:
5 - moyen
Sévérité:
5 - moyen
Résolution:
Fixed
Fichier:
1
Vote
Score: 0
No votes
0.0% (0/0)
0.0% (0/0)

Détails

RAND_MAX が 0x7FFF(32767) のため、これより細かい粒度の乱数を得ようとしても得られない。

この方法を利用すると 0x7FFF*0x7FFF = 3FFF0001(1073676289) になる。

http://www.lab.its55.com/?p=77

Ticket History (3/8 Histories)

2015-12-09 00:22 Updated by: (del#1144)
  • New Ticket "random マクロコマンドに大きな値を渡した場合の問題" created
2015-12-09 02:09 Updated by: doda
  • Jalon Update from (Aucun) to Tera Term 4.90 (atteints)
  • Propriétaire Update from (Aucun) to doda
  • Sévérité Update from 4 to 5 - moyen
Commentaire

挙げられているURLはちょっと内容が酷いので、参考にしない方がいいです。

例えば、1~3 の乱数二つを掛けた場合、1, 2, 3, 2, 4, 6, 3, 6, 9 の9パターンとなり、 2, 3, 6が二倍の確率で出現する上に5, 7, 8がまったく出ません。

さらに 0~2 で考えた場合は 0, 0, 0, 0, 1, 2, 0, 2, 4 と半数以上が 0 になります。

このように、より大きな乱数を得ようとして二つの乱数を掛けてしまうと 一様でない値が得られるので、リンク先のページは最初の時点で誤っています。

rand() でやるとしたら、

(((unsigned int)rand()) << 15) | (unsigned int)rand()  // 30ビット
とか
unsigned int r, r1, r2, r3;
r1 = rand(); r2 = rand(); r3 = rand();
r = ((r1 & 0x6000) << 17) | (r2 << 15) | r3; // 32ビット
のようなビット演算を使う必要があります。

ただこの方法で大きな乱数を得ても元々のrand()の品質の悪さの影響は受けるので、 それよりはメルセンヌ・ツイスタのソースを持ってきたり、 ttssh でも使っている arc4random() を使う方がいいと思います。

# rand_s()が使えたら楽なのですが、XP以降でした

2015-12-09 13:19 Updated by: (del#1144)
Commentaire

#35202 random マクロコマンドに発生する偏り」に書きましたが、単に arc4random() に置き換えるだけでは端数で偏りが出る問題は残ってしまうと思います。

#35202 乱数生成のarc4random()を使っていてよいか」の件も含めて、ChaCha20 ベースの arc4random() に書き換えるか mt19937ar.sep を持ってくるかのどちらかでしょうか?

2015-12-09 17:04 Updated by: doda
Commentaire

最初は ChaCha20 ベースの arc4random() を使おうかと思っていたのですが、 新たに OpenSSL をリンクするようにする必要がある為これを避けて、 SFMT を使う方向で検討しています。

2015-12-10 01:57 Updated by: doda
  • Résolution Update from Aucun to Fixed
Commentaire

すみません。ファイルが添付されているのに今気が付きました。

  • 暗号学的乱数生成器では無いので、ttssh2 から使う事はまずない
  • Tera Term 本体でもまず使わないと思われる

という事からほぼ macro 専用になりそうだったので、 必要な部分のソースを直接取り込んじゃいました。

ライブラリとして別に分けた方がよかったですか?

2015-12-10 13:27 Updated by: (del#1144)
Commentaire

TTSSH 側では使わないんですね。それならよいと思います。

インポートすると差し替えづらくなりますし、インポート元が更新されても放置されがちなので、そこに気をつけたいところです。

別ライブラリにするかどうかの判断基準は、おおむねこんな感じかと思います。

  1. たびたび更新される
  2. よそのソースは管理上分離しておいたほうがいい
  3. 外部ライブラリとしてビルドでき、呼び出すだけで利用できる

現状でインポートしたり、イレギュラーなもの:

  • CTC (OpenSSH からインポート)
    • cipher-ctc.c
  • ed25519 (OpenSSH からインポート)
    • ed25519.c
    • ed25519_bcrypt_pbkdf.c
    • ed25519_blf.h
    • ed25519_blocks.c
    • ed25519_blowfish.c
    • ed25519_crypto_api.h
    • ed25519_fe25519.c
    • ed25519_fe25519.h
    • ed25519_ge25519.c
    • ed25519_ge25519.h
    • ed25519_hash.c
    • ed25519_sc25519.c
    • ed25519_sc25519.h
    • ed25519_verify.c
    • ge25519_base.data
  • arc4random (OpenSSH からインポート)
    • bsd-arc4random.c から ttxssh.c 内にコピー
  • putty
    • ssh.c とかファイル名がバッティングする
    • もともとライブラリじゃないのをクッションとしてライブラリ化して libputty.h/putty.lib を作成
2016-02-09 21:18 Updated by: (del#1144)
  • Ticket Close date is changed to 2016-02-09 21:18
  • État Update from Ouvert to Atteints

Attachment File List

  • buildSFMT.bat(917octets)
    • macro / ttssh2 両方から参照するとして、スタティックライブラリにするにはこんな感じでしょうか

Modifier

You are not logged in. I you are not logged in, your comment will be treated as an anonymous post. » Connexion