github.com/status-im/status-go@v1.1.0/waku/common/helpers.go (about) 1 package common 2 3 import ( 4 "crypto/ecdsa" 5 crand "crypto/rand" 6 "errors" 7 "fmt" 8 mrand "math/rand" 9 10 "github.com/ethereum/go-ethereum/common" 11 ) 12 13 // IsPubKeyEqual checks that two public keys are equal 14 func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool { 15 if !ValidatePublicKey(a) { 16 return false 17 } else if !ValidatePublicKey(b) { 18 return false 19 } 20 // the curve is always the same, just compare the points 21 return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0 22 } 23 24 // ValidatePublicKey checks the format of the given public key. 25 func ValidatePublicKey(k *ecdsa.PublicKey) bool { 26 return k != nil && k.X != nil && k.Y != nil && k.X.Sign() != 0 && k.Y.Sign() != 0 27 } 28 29 // BytesToUintLittleEndian converts the slice to 64-bit unsigned integer. 30 func BytesToUintLittleEndian(b []byte) (res uint64) { 31 mul := uint64(1) 32 for i := 0; i < len(b); i++ { 33 res += uint64(b[i]) * mul 34 mul *= 256 35 } 36 return res 37 } 38 39 // BytesToUintBigEndian converts the slice to 64-bit unsigned integer. 40 func BytesToUintBigEndian(b []byte) (res uint64) { 41 for i := 0; i < len(b); i++ { 42 res *= 256 43 res += uint64(b[i]) 44 } 45 return res 46 } 47 48 // ContainsOnlyZeros checks if the data contain only zeros. 49 func ContainsOnlyZeros(data []byte) bool { 50 for _, b := range data { 51 if b != 0 { 52 return false 53 } 54 } 55 return true 56 } 57 58 // GenerateSecureRandomData generates random data where extra security is required. 59 // The purpose of this function is to prevent some bugs in software or in hardware 60 // from delivering not-very-random data. This is especially useful for AES nonce, 61 // where true randomness does not really matter, but it is very important to have 62 // a unique nonce for every message. 63 func GenerateSecureRandomData(length int) ([]byte, error) { 64 x := make([]byte, length) 65 y := make([]byte, length) 66 res := make([]byte, length) 67 68 _, err := crand.Read(x) 69 if err != nil { 70 return nil, err 71 } else if !ValidateDataIntegrity(x, length) { 72 return nil, errors.New("crypto/rand failed to generate secure random data") 73 } 74 _, err = mrand.Read(y) // nolint: gosec 75 if err != nil { 76 return nil, err 77 } else if !ValidateDataIntegrity(y, length) { 78 return nil, errors.New("math/rand failed to generate secure random data") 79 } 80 for i := 0; i < length; i++ { 81 res[i] = x[i] ^ y[i] 82 } 83 if !ValidateDataIntegrity(res, length) { 84 return nil, errors.New("failed to generate secure random data") 85 } 86 return res, nil 87 } 88 89 // GenerateRandomID generates a random string, which is then returned to be used as a key id 90 func GenerateRandomID() (id string, err error) { 91 buf, err := GenerateSecureRandomData(KeyIDSize) 92 if err != nil { 93 return "", err 94 } 95 if !ValidateDataIntegrity(buf, KeyIDSize) { 96 return "", fmt.Errorf("error in generateRandomID: crypto/rand failed to generate random data") 97 } 98 id = common.Bytes2Hex(buf) 99 return id, err 100 } 101 102 // ValidateDataIntegrity returns false if the data have the wrong or contains all zeros, 103 // which is the simplest and the most common bug. 104 func ValidateDataIntegrity(k []byte, expectedSize int) bool { 105 if len(k) != expectedSize { 106 return false 107 } 108 if expectedSize > 3 && ContainsOnlyZeros(k) { 109 return false 110 } 111 return true 112 }