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  }