package crypto_test import ( "bytes" "crypto/rand" "fmt" "io" "os" "testing" "github.com/libp2p/go-libp2p/core/crypto" crypto_pb "github.com/libp2p/go-libp2p/core/crypto/pb" ) var message = []byte("Libp2p is the _best_!") type testCase struct { keyType crypto_pb.KeyType gen func(i io.Reader) (crypto.PrivKey, crypto.PubKey, error) sigDeterministic bool } var keyTypes = []testCase{ { keyType: crypto_pb.KeyType_ECDSA, gen: crypto.GenerateECDSAKeyPair, }, { keyType: crypto_pb.KeyType_Secp256k1, sigDeterministic: true, gen: crypto.GenerateSecp256k1Key, }, { keyType: crypto_pb.KeyType_RSA, sigDeterministic: true, gen: func(i io.Reader) (crypto.PrivKey, crypto.PubKey, error) { return crypto.GenerateRSAKeyPair(2048, i) }, }, } func fname(kt crypto_pb.KeyType, ext string) string { return fmt.Sprintf("test_data/%d.%s", kt, ext) } func TestFixtures(t *testing.T) { for _, tc := range keyTypes { t.Run(tc.keyType.String(), func(t *testing.T) { pubBytes, err := os.ReadFile(fname(tc.keyType, "pub")) if err != nil { t.Fatal(err) } privBytes, err := os.ReadFile(fname(tc.keyType, "priv")) if err != nil { t.Fatal(err) } sigBytes, err := os.ReadFile(fname(tc.keyType, "sig")) if err != nil { t.Fatal(err) } pub, err := crypto.UnmarshalPublicKey(pubBytes) if err != nil { t.Fatal(err) } pubBytes2, err := crypto.MarshalPublicKey(pub) if err != nil { t.Fatal(err) } if !bytes.Equal(pubBytes2, pubBytes) { t.Fatal("encoding round-trip failed") } priv, err := crypto.UnmarshalPrivateKey(privBytes) if err != nil { t.Fatal(err) } privBytes2, err := crypto.MarshalPrivateKey(priv) if err != nil { t.Fatal(err) } if !bytes.Equal(privBytes2, privBytes) { t.Fatal("encoding round-trip failed") } ok, err := pub.Verify(message, sigBytes) if !ok || err != nil { t.Fatal("failed to validate signature with public key") } if tc.sigDeterministic { sigBytes2, err := priv.Sign(message) if err != nil { t.Fatal(err) } if !bytes.Equal(sigBytes2, sigBytes) { t.Fatal("signature not deterministic") } } }) } } func init() { // set to true to re-generate test data if false { generate() panic("generated") } } // generate re-generates test data func generate() { for _, tc := range keyTypes { priv, pub, err := tc.gen(rand.Reader) if err != nil { panic(err) } pubb, err := crypto.MarshalPublicKey(pub) if err != nil { panic(err) } privb, err := crypto.MarshalPrivateKey(priv) if err != nil { panic(err) } sig, err := priv.Sign(message) if err != nil { panic(err) } os.WriteFile(fname(tc.keyType, "pub"), pubb, 0666) os.WriteFile(fname(tc.keyType, "priv"), privb, 0666) os.WriteFile(fname(tc.keyType, "sig"), sig, 0666) } }