2

Java Cardで2つの数値の間に境界のある乱数を生成する方法は? たとえば、数値は 0 から 50 の間で生成する必要があります。

4

4 に答える 4

6

SecureRandomJava SE 内を使用して、乱数の分布のみをテストしたことに注意してください。ただし、このコードが正しいことはかなり確信しています。このコードは、NIST によって定義された「単純拒否」方式を使用しています。

というわけで、コードは省略します。

package nl.owlstead.jcsecurerandom;

import javacard.framework.JCSystem;
import javacard.framework.Util;
import javacard.security.RandomData;

/**
 * Generates numbers within a range. This class uses modulo arithmetic to
 * minimize the number of calls to the random number generator without expensive
 * calculations. The class is similar in operation to the
 * {@code SecureRandom.nextInt(int)} method defined in Java SE.
 * 
 * @author owlstead
 */
public final class JCSecureRandom {

    private static final short SHORT_SIZE_BYTES = 2;
    private static final short START = 0;

    private final RandomData rnd;
    private final byte[] buf;

    /**
     * Constructor which uses the given source of random bytes. A two byte
     * buffer transient buffer is generated that is cleared on deselect.
     * 
     * @param rnd
     *            the source of random bytes
     */
    public JCSecureRandom(final RandomData rnd) {
        this.rnd = rnd;
        this.buf = JCSystem.makeTransientByteArray(SHORT_SIZE_BYTES,
                JCSystem.CLEAR_ON_DESELECT);
    }

    /**
     * Generates a single short with a random value in the range of 0
     * (inclusive) to the given parameter n (exclusive).
     * 
     * @param n
     *            the upper bound of the random value, must be positive
     *            (exclusive)
     * @return the random value in the range [0..n-1]
     */
    public short nextShort(final short n) {
        final short sn = (short) (n - 1);
        short bits, val;
        do {
            bits = next15();
            val = (short) (bits % n);
        } while ((short) (bits - val + sn) < 0);
        return val;
    }

    /**
     * Generates a single byte with a random value in the range of 0 (inclusive)
     * to the given parameter n (exclusive).
     * 
     * @param n
     *            the upper bound of the random value, must be positive
     *            (exclusive)
     * @return the random value in the range [0..n-1]
     */
    public byte nextByte(final byte n) {
        if ((n & -n) == n) {
            return (byte) ((n * next7()) >> 7);
        }

        final byte sn = (byte) (n - 1);
        byte bits, val;
        do {
            bits = next7();
            val = (byte) (bits % n);
        } while ((byte) (bits - val + sn) < 0);
        return val;
    }

    /**
     * Generates 15 bits from two bytes by setting the highest bit to zero.
     * 
     * @return the positive valued short containing 15 bits of random
     */
    private short next15() {
        this.rnd.generateData(this.buf, START, SHORT_SIZE_BYTES);
        return (short) (Util.getShort(this.buf, START) & 0x7FFF);
    }

    /**
     * Generates 7 bits from one byte by setting the highest bit to zero.
     * 
     * @return the positive valued byte containing 7 bits of random
     */
    private byte next7() {
        this.rnd.generateData(this.buf, START, SHORT_SIZE_BYTES);
        return (byte) (this.buf[START] & 0x7F);
    }
}
于 2013-06-26T00:02:28.193 に答える
1

Java Card では、ランダムなバイトを生成することしかできない javacard.security.RandomData にしかアクセスできません。

最初に正しい型の変数が必要です:

private RandomData rng;
private byte[] rndBuffer;

次に、コンストラクター/インストールに次のコードが必要です (ランダムジェネレーターとバッファーを毎回割り当てるのを避けるため):

rng = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
rndBuffer = JCSystem.getTransientByteArray(JCSystem.CLEAR_ON_DESELECT, 1);

次に、範囲内のランダムなバイトを取得するメソッドを定義できます。

byte getRandomByteInRange(byte min, byte max) {
  do {
    rng.generateData(rndBuffer,0,1);
  while ((rndBuffer[0]<min) || (rndBuffer[0]>max))
  return rndBuffer[0];
}

このメソッドを (特に小さな範囲の場合) 書くためのもっとばかばかしくない方法がある可能性が最も高いですが、それはうまくいくはずです。

于 2013-04-02T11:10:13.903 に答える