github.com/onflow/flow-go/crypto@v0.24.8/bls12381_utils_test.go (about) 1 //go:build relic 2 // +build relic 3 4 package crypto 5 6 import ( 7 crand "crypto/rand" 8 "encoding/hex" 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 ) 14 15 func TestDeterministicKeyGen(t *testing.T) { 16 // 2 keys generated with the same seed should be equal 17 seed := make([]byte, KeyGenSeedMinLen) 18 n, err := crand.Read(seed) 19 require.Equal(t, n, KeyGenSeedMinLen) 20 require.NoError(t, err) 21 sk1, err := GeneratePrivateKey(BLSBLS12381, seed) 22 require.Nil(t, err) 23 sk2, err := GeneratePrivateKey(BLSBLS12381, seed) 24 require.Nil(t, err) 25 assert.True(t, sk1.Equals(sk2), "private keys should be equal") 26 } 27 28 // test the deterministicity of the relic PRG (used by the DKG polynomials) 29 func TestPRGseeding(t *testing.T) { 30 blsInstance.reInit() 31 // 2 scalars generated with the same seed should be equal 32 seed := make([]byte, KeyGenSeedMinLen) 33 n, err := crand.Read(seed) 34 require.Equal(t, n, KeyGenSeedMinLen) 35 require.NoError(t, err) 36 // 1st scalar (wrapped in a private key) 37 err = seedRelic(seed) 38 require.Nil(t, err) 39 var sk1 prKeyBLSBLS12381 40 randZr(&sk1.scalar) 41 // 2nd scalar (wrapped in a private key) 42 err = seedRelic(seed) 43 require.Nil(t, err) 44 var sk2 prKeyBLSBLS12381 45 randZr(&sk2.scalar) 46 // compare the 2 scalars (by comparing the private keys) 47 assert.True(t, sk1.Equals(&sk2), "private keys should be equal") 48 } 49 50 // G1 and G2 scalar multiplication 51 func BenchmarkScalarMultG1G2(b *testing.B) { 52 blsInstance.reInit() 53 seed := make([]byte, securityBits/8) 54 _, err := crand.Read(seed) 55 require.NoError(b, err) 56 _ = seedRelic(seed) 57 var expo scalar 58 randZr(&expo) 59 60 // G1 generator multiplication 61 b.Run("G1 gen", func(b *testing.B) { 62 var res pointG1 63 b.ResetTimer() 64 for i := 0; i < b.N; i++ { 65 generatorScalarMultG1(&res, &expo) 66 } 67 b.StopTimer() 68 }) 69 70 // G1 base point multiplication 71 b.Run("G1 generic", func(b *testing.B) { 72 var res pointG1 73 b.ResetTimer() 74 for i := 0; i < b.N; i++ { 75 genericScalarMultG1(&res, &expo) 76 } 77 b.StopTimer() 78 }) 79 80 // G2 base point multiplication 81 b.Run("G2 gen", func(b *testing.B) { 82 var res pointG2 83 b.ResetTimer() 84 for i := 0; i < b.N; i++ { 85 generatorScalarMultG2(&res, &expo) 86 } 87 b.StopTimer() 88 }) 89 } 90 91 // Sanity-check of the map-to-G1 with regards to the IETF draft hash-to-curve 92 func TestMapToG1(t *testing.T) { 93 94 // test vectors from https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-14#appendix-J.9.1 95 dst := []byte("QUUX-V01-CS02-with-BLS12381G1_XMD:SHA-256_SSWU_RO_") 96 97 msgs := [][]byte{ 98 []byte{}, 99 []byte("abc"), 100 []byte("abcdef0123456789"), 101 []byte("q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"), 102 []byte("a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), 103 } 104 105 expectedPointString := []string{ 106 "052926add2207b76ca4fa57a8734416c8dc95e24501772c814278700eed6d1e4e8cf62d9c09db0fac349612b759e79a1", 107 "03567bc5ef9c690c2ab2ecdf6a96ef1c139cc0b2f284dca0a9a7943388a49a3aee664ba5379a7655d3c68900be2f6903", 108 "11e0b079dea29a68f0383ee94fed1b940995272407e3bb916bbf268c263ddd57a6a27200a784cbc248e84f357ce82d98", 109 "15f68eaa693b95ccb85215dc65fa81038d69629f70aeee0d0f677cf22285e7bf58d7cb86eefe8f2e9bc3f8cb84fac488", 110 "082aabae8b7dedb0e78aeb619ad3bfd9277a2f77ba7fad20ef6aabdc6c31d19ba5a6d12283553294c1825c4b3ca2dcfe", 111 } 112 113 for i, msg := range msgs { 114 pointBytes := hashToG1Bytes(msg, dst) 115 116 expectedPointBytes, err := hex.DecodeString(expectedPointString[i]) 117 require.NoError(t, err) 118 // skip comparing the first 3 bits that depend on the serialization scheme 119 pointBytes[0] = (expectedPointBytes[0] & 0xE0) | (pointBytes[0] & 0x1F) 120 assert.Equal(t, expectedPointBytes, pointBytes, "map to G1 should match the IETF draft test vector") 121 } 122 } 123 124 // Hashing to G1 bench 125 func BenchmarkMapToG1(b *testing.B) { 126 blsInstance.reInit() 127 input := make([]byte, expandMsgOutput) 128 for i := 0; i < len(input); i++ { 129 input[i] = byte(i) 130 } 131 b.ResetTimer() 132 for i := 0; i < b.N; i++ { 133 mapToG1(input) 134 } 135 b.StopTimer() 136 } 137 138 // test subgroup membership check in G1 and G2 139 func TestSubgroupCheck(t *testing.T) { 140 blsInstance.reInit() 141 // seed Relic PRG 142 seed := make([]byte, securityBits/8) 143 _, err := crand.Read(seed) 144 require.NoError(t, err) 145 _ = seedRelic(seed) 146 147 t.Run("G1", func(t *testing.T) { 148 var p pointG1 149 randPointG1(&p) // point in G1 150 res := checkMembershipG1(&p) 151 assert.Equal(t, res, int(valid)) 152 randPointG1Complement(&p) // point in E1\G1 153 res = checkMembershipG1(&p) 154 assert.Equal(t, res, int(invalid)) 155 }) 156 157 t.Run("G2", func(t *testing.T) { 158 var p pointG2 159 randPointG2(&p) // point in G2 160 res := checkMembershipG2(&p) 161 assert.Equal(t, res, int(valid)) 162 randPointG2Complement(&p) // point in E2\G2 163 res = checkMembershipG2(&p) 164 assert.Equal(t, res, int(invalid)) 165 }) 166 } 167 168 // subgroup membership check bench 169 func BenchmarkSubgroupCheck(b *testing.B) { 170 blsInstance.reInit() 171 172 b.Run("G1", func(b *testing.B) { 173 var p pointG1 174 randPointG1(&p) 175 b.ResetTimer() 176 for i := 0; i < b.N; i++ { 177 _ = checkMembershipG1(&p) // G1 178 } 179 b.StopTimer() 180 }) 181 182 b.Run("G2", func(b *testing.B) { 183 var p pointG2 184 randPointG2(&p) 185 b.ResetTimer() 186 for i := 0; i < b.N; i++ { 187 _ = checkMembershipG2(&p) // G2 188 } 189 b.StopTimer() 190 }) 191 }