| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| */ |
| |
| /* |
| * Cryptographic strong random number generator |
| * |
| * Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers |
| * Slow - but secure |
| * |
| * See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification |
| */ |
| |
| /* Marsaglia & Zaman Random number generator constants */ |
| |
| |
| package org.apache.milagro.amcl; |
| |
| public class RAND { |
| /* Cryptographically strong pseudo-random number generator */ |
| |
| private static final int NK=21; |
| private static final int NJ=6; |
| private static final int NV=8; |
| private int[] ira=new int[NK]; /* random number... */ |
| private int rndptr; /* ...array & pointer */ |
| private int borrow; |
| private int pool_ptr; |
| private byte[] pool=new byte[32]; /* random pool */ |
| |
| public RAND() |
| { |
| clean(); |
| } |
| |
| private int sbrand() |
| { /* Marsaglia & Zaman random number generator */ |
| int i,k; |
| long pdiff,t; |
| |
| rndptr++; |
| if (rndptr<NK) return ira[rndptr]; |
| rndptr=0; |
| for (i=0,k=NK-NJ;i<NK;i++,k++) |
| { /* calculate next NK values */ |
| if (k==NK) k=0; |
| t=((long)ira[k])&0xffffffffL; |
| pdiff=(t - (((long)ira[i])&0xffffffffL) - (long)borrow)&0xffffffffL; |
| if (pdiff<t) borrow=0; |
| if (pdiff>t) borrow=1; |
| ira[i]=(int)(pdiff&0xffffffffL); |
| } |
| |
| return ira[0]; |
| } |
| |
| public void sirand(int seed) |
| { |
| int i,in; |
| int t,m=1; |
| borrow=0; |
| rndptr=0; |
| ira[0]^=seed; |
| for (i=1;i<NK;i++) |
| { /* fill initialisation vector */ |
| in=(NV*i)%NK; |
| ira[in]^=m; /* note XOR */ |
| t=m; |
| m=seed-m; |
| seed=t; |
| } |
| for (i=0;i<10000;i++) sbrand(); /* "warm-up" & stir the generator */ |
| } |
| |
| private void fill_pool() |
| { |
| HASH256 sh=new HASH256(); |
| for (int i=0;i<128;i++) sh.process(sbrand()); |
| pool=sh.hash(); |
| pool_ptr=0; |
| } |
| |
| private static int pack(byte[] b) |
| { /* pack 4 bytes into a 32-bit Word */ |
| return ((((int)b[3])&0xff)<<24)|(((int)b[2]&0xff)<<16)|(((int)b[1]&0xff)<<8)|((int)b[0]&0xff); |
| } |
| |
| /* Initialize RNG with some real entropy from some external source */ |
| public void seed(int rawlen,byte[] raw) |
| { /* initialise from at least 128 byte string of raw random entropy */ |
| int i; |
| byte [] digest; |
| byte [] b=new byte[4]; |
| HASH256 sh=new HASH256(); |
| pool_ptr=0; |
| for (i=0;i<NK;i++) ira[i]=0; |
| if (rawlen>0) |
| { |
| for (i=0;i<rawlen;i++) |
| sh.process(raw[i]); |
| digest=sh.hash(); |
| |
| /* initialise PRNG from distilled randomness */ |
| |
| for (i=0;i<8;i++) |
| { |
| b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3]; |
| sirand(pack(b)); |
| } |
| } |
| fill_pool(); |
| } |
| |
| /* Terminate and clean up */ |
| public void clean() |
| { /* kill internal state */ |
| int i; |
| pool_ptr=rndptr=0; |
| for (i=0;i<32;i++) pool[i]=0; |
| for (i=0;i<NK;i++) ira[i]=0; |
| borrow=0; |
| } |
| |
| /* get random byte */ |
| public int getByte() |
| { |
| int r; |
| r=pool[pool_ptr++]; |
| if (pool_ptr>=32) fill_pool(); |
| return (r&0xff); |
| } |
| |
| /* test main program */ |
| /* |
| public static void main(String[] args) { |
| int i; |
| byte[] raw=new byte[100]; |
| RAND rng=new RAND(); |
| |
| rng.clean(); |
| for (i=0;i<100;i++) raw[i]=(byte)i; |
| |
| rng.seed(100,raw); |
| |
| for (i=0;i<1000;i++) |
| System.out.format("%03d ",rng.getByte()); |
| } */ |
| } |