github.com/line/ostracon@v1.0.10-0.20230328032236-7f20145f065d/crypto/vrf/compatibility_keys_test.go (about) 1 //go:build libsodium 2 // +build libsodium 3 4 package vrf 5 6 import ( 7 "bytes" 8 "crypto/ed25519" 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 14 coniks "github.com/coniks-sys/coniks-go/crypto/vrf" 15 ed25519consensus "github.com/hdevalence/ed25519consensus" 16 libsodium "github.com/line/ostracon/crypto/vrf/internal/vrf" 17 xed25519 "golang.org/x/crypto/ed25519" 18 ) 19 20 var secret [SEEDBYTES]byte 21 var message []byte = []byte("hello, world") 22 23 func TestKeygen(t *testing.T) { 24 for i := 0; i < SEEDBYTES; i++ { 25 secret[i] = uint8(i) 26 } 27 privateKey, publicKey := keygenByEd25519(secret) 28 29 t.Run("ed25519 and x/ed25519 have compatibility", 30 func(t *testing.T) { 31 testKeygenCompatibility(t, privateKey, publicKey, 32 keygenByXed25519, require.Equal, require.Equal) 33 }) 34 t.Run("ed25519 and coniks have NOT compatibility", 35 func(t *testing.T) { 36 testKeygenCompatibility(t, privateKey, publicKey, 37 keygenByConiksEd25519, require.NotEqual, require.NotEqual) 38 }) 39 t.Run("ed25519 and libsodium have compatibility", 40 func(t *testing.T) { 41 testKeygenCompatibility(t, privateKey, publicKey, 42 keygenByLibsodiumEd25519, require.Equal, require.Equal) 43 }) 44 } 45 46 func testKeygenCompatibility( 47 t *testing.T, 48 sk1 ed25519.PrivateKey, pk1 ed25519.PublicKey, 49 keyGen2 func(secret [SEEDBYTES]byte) (ed25519.PrivateKey, ed25519.PublicKey), 50 skTest func(t require.TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}), 51 pkTest func(t require.TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}), 52 ) { 53 sk2, pk2 := keyGen2(secret) 54 skTest(t, sk1, sk2) 55 pkTest(t, pk1, pk2) 56 } 57 58 func keygenByEd25519(secret [SEEDBYTES]byte) (ed25519.PrivateKey, ed25519.PublicKey) { 59 privateKey := ed25519.NewKeyFromSeed(secret[:]) 60 publicKey := privateKey.Public().(ed25519.PublicKey) 61 return privateKey, publicKey 62 } 63 64 func keygenByXed25519(secret [SEEDBYTES]byte) (ed25519.PrivateKey, ed25519.PublicKey) { 65 publicKey, privateKey, _ := xed25519.GenerateKey(bytes.NewReader(secret[:])) 66 return privateKey, publicKey 67 } 68 69 func keygenByConiksEd25519(secret [SEEDBYTES]byte) (ed25519.PrivateKey, ed25519.PublicKey) { 70 privKey, _ := coniks.GenerateKey(bytes.NewReader(secret[:])) 71 pubKey, _ := privKey.Public() 72 privateKey := make([]byte, coniks.PrivateKeySize) 73 copy(privateKey, privKey[:]) 74 publicKey := make([]byte, coniks.PublicKeySize) 75 copy(publicKey, pubKey[:]) 76 return privateKey, publicKey 77 } 78 79 func keygenByLibsodiumEd25519(secret [SEEDBYTES]byte) (ed25519.PrivateKey, ed25519.PublicKey) { 80 var seed [libsodium.SEEDBYTES]byte 81 copy(seed[:], secret[:]) 82 pubKey, privKey := libsodium.KeyPairFromSeed(&seed) 83 privateKey := make([]byte, libsodium.SECRETKEYBYTES) 84 copy(privateKey, privKey[:]) 85 publicKey := make([]byte, libsodium.PUBLICKEYBYTES) 86 copy(publicKey, pubKey[:]) 87 return privateKey, publicKey 88 } 89 90 func TestKeypair(t *testing.T) { 91 privateKey, publicKey := keygenByEd25519(secret) 92 93 t.Run("ed25519 and x/ed25519 have compatibility", 94 func(t *testing.T) { 95 testKeypairCompatibilityWithXed25519(t, privateKey, publicKey, 96 require.EqualValues, require.EqualValues) 97 }) 98 t.Run("ed25519 and coniks have NOT compatibility", 99 func(t *testing.T) { 100 testKeypairCompatibilityWithConiksEd25519(t, privateKey, publicKey, 101 require.EqualValues, require.NotEqualValues) 102 }) 103 t.Run("ed25519 and libsodium have compatibility", 104 func(t *testing.T) { 105 testKeypairCompatibilityWithLibsodiumEd25519(t, privateKey, publicKey, 106 require.EqualValues, require.EqualValues) 107 }) 108 } 109 110 func testKeypairCompatibilityWithXed25519( 111 t *testing.T, 112 sk ed25519.PrivateKey, pk ed25519.PublicKey, 113 toPkTest func(t require.TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}), 114 fromSkTest func(t require.TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}), 115 ) { 116 pk1, sk1, _ := xed25519.GenerateKey(bytes.NewReader(secret[:])) 117 118 sk2 := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize)) 119 copy(sk2[:], sk1[:]) 120 pk2 := sk2.Public().(ed25519.PublicKey) 121 122 toPkTest(t, pk1[:], pk2[:]) 123 124 copy(sk1[:], sk[:]) 125 pk1 = sk1.Public().(xed25519.PublicKey) 126 127 fromSkTest(t, pk1[:], pk2[:]) 128 } 129 130 func testKeypairCompatibilityWithConiksEd25519( 131 t *testing.T, 132 sk ed25519.PrivateKey, pk ed25519.PublicKey, 133 toPkTest func(t require.TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}), 134 fromSkTest func(t require.TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}), 135 ) { 136 sk1, _ := coniks.GenerateKey(bytes.NewReader(secret[:])) 137 pk1, _ := sk1.Public() 138 139 sk2 := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize)) 140 copy(sk2[:], sk1[:]) 141 pk2 := sk2.Public().(ed25519.PublicKey) 142 143 toPkTest(t, pk1[:], pk2[:]) 144 145 copy(sk1[:], sk[:]) 146 pk1, _ = sk1.Public() 147 148 fromSkTest(t, pk1[:], pk2[:]) 149 } 150 151 func testKeypairCompatibilityWithLibsodiumEd25519( 152 t *testing.T, 153 sk ed25519.PrivateKey, pk ed25519.PublicKey, 154 toPkTest func(t require.TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}), 155 fromSkTest func(t require.TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}), 156 ) { 157 var seed [libsodium.SEEDBYTES]byte 158 copy(seed[:], secret[:]) 159 pk1, sk1 := libsodium.KeyPairFromSeed(&seed) 160 161 sk2 := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize)) 162 copy(sk2[:], sk1[:]) 163 pk2 := sk2.Public().(ed25519.PublicKey) 164 165 toPkTest(t, pk1[:], pk2[:]) 166 167 copy(sk1[:], sk[:]) 168 pk1 = libsodium.SkToPk(sk1) 169 170 fromSkTest(t, pk1[:], pk2[:]) 171 } 172 173 func TestSignVerify(t *testing.T) { 174 sk, pk := keygenByEd25519(secret) 175 t.Run("ed25519( and ed25519consensus.Verify) and xed25119 have compatibility", func(t *testing.T) { 176 pk1, sk1, _ := xed25519.GenerateKey(bytes.NewReader(secret[:])) 177 178 signature := ed25519.Sign(sk, message) 179 valid := xed25519.Verify(pk1, message, signature) 180 assert.True(t, valid) 181 182 signature = xed25519.Sign(sk1, message) 183 valid = ed25519.Verify(pk, message, signature) 184 assert.True(t, valid) 185 186 valid = ed25519consensus.Verify(pk, message, signature) 187 assert.True(t, valid) 188 }) 189 } 190 191 func BenchmarkKeyGenByEd25519(b *testing.B) { 192 b.ResetTimer() 193 for i := 0; i < b.N; i++ { 194 keygenByEd25519(secret) 195 } 196 } 197 198 func BenchmarkKeyGenByConiksEd25519(b *testing.B) { 199 b.ResetTimer() 200 for i := 0; i < b.N; i++ { 201 keygenByConiksEd25519(secret) 202 } 203 } 204 205 func BenchmarkKeyGenByLibsodiumEd25519(b *testing.B) { 206 b.ResetTimer() 207 for i := 0; i < b.N; i++ { 208 keygenByLibsodiumEd25519(secret) 209 } 210 }