github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-amcl/amcl/RAND.go (about)

     1  /*
     2  Licensed to the Apache Software Foundation (ASF) under one
     3  or more contributor license agreements.  See the NOTICE file
     4  distributed with this work for additional information
     5  regarding copyright ownership.  The ASF licenses this file
     6  to you under the Apache License, Version 2.0 (the
     7  "License"); you may not use this file except in compliance
     8  with the License.  You may obtain a copy of the License at
     9  
    10    http://www.apache.org/licenses/LICENSE-2.0
    11  
    12  Unless required by applicable law or agreed to in writing,
    13  software distributed under the License is distributed on an
    14  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15  KIND, either express or implied.  See the License for the
    16  specific language governing permissions and limitations
    17  under the License.
    18  */
    19  
    20  /*
    21   *   Cryptographic strong random number generator 
    22   *
    23   *   Unguessable seed -> SHA -> PRNG internal state -> SHA -> random numbers
    24   *   Slow - but secure
    25   *
    26   *   See ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf for a justification
    27   */
    28  
    29  /* Marsaglia & Zaman Random number generator constants */
    30  
    31  
    32  package amcl
    33  
    34  
    35  
    36  const rand_NK int=21
    37  const rand_NJ int=6
    38  const rand_NV int=8
    39  
    40  type RAND struct {
    41  	ira [rand_NK]uint32  /* random number...   */
    42  	rndptr int
    43  	borrow uint32
    44  	pool_ptr int
    45  	pool [32]byte
    46  }
    47  
    48  /* Terminate and clean up */
    49  func (R *RAND) Clean() { /* kill internal state */
    50  	R.pool_ptr=0; R.rndptr=0;
    51  	for i:=0;i<32;i++ {R.pool[i]=0}
    52  	for i:=0;i<rand_NK;i++ {R.ira[i]=0}
    53  	R.borrow=0;
    54  }
    55  
    56  func NewRAND() *RAND {
    57  	R:=new(RAND)
    58  	R.Clean()
    59  	return R
    60  }
    61  
    62  func (R *RAND) sbrand() uint32 { /* Marsaglia & Zaman random number generator */
    63  	R.rndptr++
    64  	if R.rndptr<rand_NK {return R.ira[R.rndptr]}
    65  	R.rndptr=0
    66  	k:=rand_NK-rand_NJ
    67  	for i:=0;i<rand_NK;i++{ /* calculate next NK values */
    68  		if k==rand_NK {k=0}
    69  		t:=R.ira[k]
    70  		pdiff:=t-R.ira[i]-R.borrow
    71  		if pdiff<t {R.borrow=0}
    72  		if pdiff>t {R.borrow=1}
    73  		R.ira[i]=pdiff 
    74  		k++
    75  	}
    76  
    77  	return R.ira[0];
    78  }
    79  
    80  func (R *RAND) sirand(seed uint32) {
    81  	var m uint32=1;
    82  	R.borrow=0
    83  	R.rndptr=0
    84  	R.ira[0]^=seed;
    85  	for i:=1;i<rand_NK;i++ { /* fill initialisation vector */
    86  		in:=(rand_NV*i)%rand_NK;
    87  		R.ira[in]^=m;      /* note XOR */
    88  		t:=m
    89  		m=seed-m
    90  		seed=t
    91  	}
    92  	for i:=0;i<10000;i++ {R.sbrand()} /* "warm-up" & stir the generator */
    93  }
    94  
    95  func (R *RAND) fill_pool() {
    96  	sh:=NewHASH256()
    97  	for i:=0;i<128;i++ {sh.Process(byte(R.sbrand()&0xff))}
    98  	W:=sh.Hash()
    99  	for i:=0;i<32;i++ {R.pool[i]=W[i]}
   100  	R.pool_ptr=0;
   101  }
   102  
   103  func pack(b [4]byte) uint32 { /* pack 4 bytes into a 32-bit Word */
   104  	return (((uint32(b[3]))&0xff)<<24)|((uint32(b[2])&0xff)<<16)|((uint32(b[1])&0xff)<<8)|(uint32(b[0])&0xff)
   105  }
   106  
   107  /* Initialize RNG with some real entropy from some external source */
   108  func (R *RAND) Seed(rawlen int,raw []byte) { /* initialise from at least 128 byte string of raw random entropy */
   109  	var b [4]byte
   110  	sh:=NewHASH256()
   111  	R.pool_ptr=0;
   112  
   113  	for i:=0;i<rand_NK;i++ {R.ira[i]=0}
   114  	if rawlen>0 {
   115  		for i:=0;i<rawlen;i++ {
   116  			sh.Process(raw[i])
   117  		}
   118  		digest:=sh.Hash()
   119  
   120  /* initialise PRNG from distilled randomness */
   121  
   122  		for i:=0;i<8;i++  {
   123  			b[0]=digest[4*i]; b[1]=digest[4*i+1]; b[2]=digest[4*i+2]; b[3]=digest[4*i+3]
   124  			R.sirand(pack(b))
   125  		}
   126  	}
   127  	R.fill_pool()
   128  }
   129  
   130  /* get random byte */
   131  func (R *RAND) GetByte() byte { 
   132  	r:=R.pool[R.pool_ptr]
   133  	R.pool_ptr++
   134  	if R.pool_ptr>=32 {R.fill_pool()}
   135  	return byte(r&0xff)
   136  }
   137  
   138  /* test main program */
   139  /*
   140  func main() {
   141  	var raw [100]byte
   142  	rng:=NewRAND()
   143  
   144  	rng.Clean()
   145  	for i:=0;i<100;i++ {raw[i]=byte(i)}
   146  
   147  	rng.Seed(100,raw[:])
   148   
   149  	for i:=0;i<1000;i++ {
   150  		fmt.Printf("%03d ",rng.GetByte())
   151  	}
   152  }
   153  */