git.gammaspectra.live/P2Pool/consensus/v3@v3.8.0/monero/crypto/random.go (about)

     1  package crypto
     2  
     3  import (
     4  	"crypto/rand"
     5  	"encoding/binary"
     6  	"git.gammaspectra.live/P2Pool/consensus/v3/types"
     7  	"git.gammaspectra.live/P2Pool/edwards25519"
     8  	"unsafe"
     9  )
    10  
    11  func RandomScalar() *edwards25519.Scalar {
    12  	buf := make([]byte, 32)
    13  	for {
    14  		if _, err := rand.Read(buf); err != nil {
    15  			return nil
    16  		}
    17  
    18  		if !less32(buf, limit) {
    19  			continue
    20  		}
    21  
    22  		scalar := BytesToScalar(buf)
    23  		if scalar.Equal(zeroScalar) == 0 {
    24  			return scalar
    25  		}
    26  	}
    27  }
    28  
    29  // DeterministicScalar consensus way of generating a deterministic scalar from given entropy
    30  // Slice entropy will have data appended
    31  func DeterministicScalar(entropy []byte) *edwards25519.Scalar {
    32  
    33  	var counter uint32
    34  
    35  	entropy = append(entropy, make([]byte, int(unsafe.Sizeof(counter)))...)
    36  	n := len(entropy) - int(unsafe.Sizeof(counter))
    37  	h := GetKeccak256Hasher()
    38  	defer PutKeccak256Hasher(h)
    39  	var hash types.Hash
    40  
    41  	scalar := GetEdwards25519Scalar()
    42  
    43  	for {
    44  		h.Reset()
    45  		counter++
    46  		binary.LittleEndian.PutUint32(entropy[n:], counter)
    47  		_, _ = h.Write(entropy)
    48  		HashFastSum(h, hash[:])
    49  		if !less32(hash[:], limit) {
    50  			continue
    51  		}
    52  		scReduce32(hash[:])
    53  		scalar, _ = scalar.SetCanonicalBytes(hash[:])
    54  
    55  		if scalar.Equal(zeroScalar) == 0 {
    56  			return scalar
    57  		}
    58  	}
    59  }