【问题标题】:Generate random number bounded between two numbers in Java Card在 Java Card 中生成两个数字之间的随机数
【发布时间】:2021-09-25 22:24:45
【问题描述】:

如何在 Java Card 中生成两个数字之间的随机数?例如数字应该在 0 到 50 之间生成。

【问题讨论】:

标签: random javacard


【解决方案1】:

请注意,我只在 Java SE 中使用 SecureRandom 测试了随机数的分布。我有理由确定这段代码是正确的。该代码使用 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);
    }
}

【讨论】:

  • 我还提出了 Java Card 的 API 更改,但遗憾的是没有被采纳。
【解决方案2】:

在 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];
}

很可能有一种不那么愚蠢的方法来编写此方法(尤其是对于小范围),但它应该可以工作。

【讨论】:

  • 请测试您的代码。 getTransientByteArray 不存在,参数顺序不正确,直接对值进行测试非常幼稚。此外,我不认为最小值和最大值都应该是互斥的。通常它是从 min(包括)到 max(不包括)。可以说从包容性到包容性,但我认为没有人会期望从 0 到 2 的范围只是为了能够提供价值 1。平均每 256 一次。
  • 对 Eric 温柔一点,@owlstead,他是 SO 的新手。 ;)
【解决方案3】:

这里有examples。以该链接中的示例 2 为例:

import java.util.Random;

/** Generate random integers in a certain range. */
public final class RandomRange {

 public static final void main(String... aArgs){
  log("Generating random integers in the range 1..10.");

  int START = 1;
  int END = 10;
  Random random = new Random();
  for (int idx = 1; idx <= 10; ++idx){
   showRandomInteger(START, END, random);
  }

  log("Done.");
}

private static void showRandomInteger(int aStart, int aEnd, Random aRandom){
  if ( aStart > aEnd ) {
    throw new IllegalArgumentException("Start cannot exceed End.");
 }
 //get the range, casting to long to avoid overflow problems
 long range = (long)aEnd - (long)aStart + 1;
 // compute a fraction of the range, 0 <= frac < range
 long fraction = (long)(range * aRandom.nextDouble());
 int randomNumber =  (int)(fraction + aStart);    
 log("Generated : " + randomNumber);
}

private static void log(String aMessage){
 System.out.println(aMessage);
 }
} 

【讨论】:

  • 那是在 java 中,我想在 javaCard 中得到同样的结果
【解决方案4】:

使用 RandomData 抽象类:

http://www.win.tue.nl/pinpasjc/docs/apis/jc222/javacard/security/RandomData.html

编辑:

这里是这个类的一个例子,

byte[] keyBytes = JCSystem.getTransientByteArray(COD,16);

RandomData rng = RandomData.getInstance(ALG_SECURE_RANDOM);
rng.generateData(keyBytes,0,16);

如果您只是在寻找随机数而不是 randomData,您可以使用这个:

    /*
    * generate a random number between 0 and 50
    */
    Random random1 = new Random();
    int card = (random1.nextInt(51));

【讨论】:

  • 我看到了这个链接,但我不知道如何使用这个功能,请你给我一个例子
  • 我用正在使用的 RandomData 类的示例编辑了我的答案
  • 感谢您的回复,我想要第二个示例的相同结果:int card = (random1.nextInt(51));但是在 javaCard 中,因为这个 Random 在 java card API 2.2.2 中不可用
  • 大部分时间都不是int
猜你喜欢
  • 1970-01-01
  • 2014-10-02
  • 2014-12-19
  • 1970-01-01
  • 2015-01-31
  • 1970-01-01
  • 2011-04-27
相关资源
最近更新 更多