Generate random number bounded between two numbers in Java Card

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-11 02:17:30

问题


How to generate random number bounded between two number in Java Card? For example number should be generated between 0 and 50.


回答1:


Note that I have only tested the distribution of the random numbers using SecureRandom within Java SE. I'm reasonably sure that this code is correct though. The code uses the "simple reject" method defined by NIST.

So without further ado, the code.

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);
    }
}



回答2:


In Java Card, you only have access to the javacard.security.RandomData, which is only able to generate random bytes.

You first need a variable of the right type:

private RandomData rng;
private byte[] rndBuffer;

Then, you need the following code in your constructor/install (to avoid allocating a random generator and buffer every time):

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

And then, you can define your method to get a random byte in a range:

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

There is most likely a less stupid way to write this method (especially for small ranges), but it should work.




回答3:


There are examples here. Taking the example 2 from that link:

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);
 }
} 



回答4:


use RandomData abstract class:

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

Edit:

here is an exaple of this class in use,

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

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

If you are simply looking for random number instead of randomData you can use this:

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


来源:https://stackoverflow.com/questions/15749186/generate-random-number-bounded-between-two-numbers-in-java-card

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!