github.com/cloudflare/circl@v1.5.0/sign/ed25519/extra_test.go (about)

     1  package ed25519_test
     2  
     3  import (
     4  	"bytes"
     5  	"crypto"
     6  	"crypto/rand"
     7  	"errors"
     8  	"fmt"
     9  	"testing"
    10  
    11  	"github.com/cloudflare/circl/internal/test"
    12  	"github.com/cloudflare/circl/sign/ed25519"
    13  )
    14  
    15  func TestWrongPublicKey(t *testing.T) {
    16  	wrongPublicKeys := [...][ed25519.PublicKeySize]byte{
    17  		{ // y = p
    18  			0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    19  			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    20  			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    21  			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
    22  		},
    23  		{ // y > p
    24  			0xed + 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    25  			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    26  			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    27  			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
    28  		},
    29  		{ // x^2 = u/v = (y^2-1)/(dy^2+1) is not a quadratic residue
    30  			0x9a, 0x0a, 0xbe, 0xc6, 0x23, 0xcb, 0x5a, 0x23,
    31  			0x4e, 0x49, 0xd8, 0x92, 0xc2, 0x72, 0xd5, 0xa8,
    32  			0x27, 0xff, 0x42, 0x07, 0x7d, 0xe3, 0xf2, 0xb4,
    33  			0x74, 0x75, 0x9d, 0x04, 0x34, 0xed, 0xa6, 0x70,
    34  		},
    35  		{ // y = 1 and x^2 = u/v = 0, and the sign of X is 1
    36  			0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    37  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    38  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    39  			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | 0x80,
    40  		},
    41  		{ // y = -1 and x^2 = u/v = 0, and the sign of X is 1
    42  			0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    43  			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    44  			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    45  			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f | 0x80,
    46  		},
    47  	}
    48  	sig := (&[ed25519.SignatureSize]byte{})[:]
    49  	for _, public := range wrongPublicKeys {
    50  		got := ed25519.Verify(public[:], []byte(""), sig)
    51  		want := false
    52  		if got != want {
    53  			test.ReportError(t, got, want, public)
    54  		}
    55  	}
    56  }
    57  
    58  func TestSigner(t *testing.T) {
    59  	seed := (&[ed25519.SeedSize]byte{})[:]
    60  	_, _ = rand.Read(seed)
    61  	key := ed25519.NewKeyFromSeed(seed)
    62  
    63  	priv := key.Seed()
    64  	if !bytes.Equal(seed, priv) {
    65  		got := priv
    66  		want := seed
    67  		test.ReportError(t, got, want)
    68  	}
    69  
    70  	for _, o := range []ed25519.SignerOptions{
    71  		{Scheme: ed25519.ED25519, Hash: crypto.Hash(0), Context: ""},
    72  		{Scheme: ed25519.ED25519Ph, Hash: crypto.SHA512, Context: ""},
    73  		{Scheme: ed25519.ED25519Ph, Hash: crypto.SHA512, Context: "non-empty"},
    74  		{Scheme: ed25519.ED25519Ctx, Hash: crypto.Hash(0), Context: "non-empty"},
    75  	} {
    76  		testSigner(t, key, o)
    77  	}
    78  }
    79  
    80  func testSigner(t *testing.T, signer crypto.Signer, ops ed25519.SignerOptions) {
    81  	msg := make([]byte, 64)
    82  	_, _ = rand.Read(msg)
    83  
    84  	sig, err := signer.Sign(nil, msg, ops)
    85  	if err != nil {
    86  		got := err
    87  		var want error
    88  		test.ReportError(t, got, want, ops)
    89  	}
    90  
    91  	if len(sig) != ed25519.SignatureSize {
    92  		got := len(sig)
    93  		want := ed25519.SignatureSize
    94  		test.ReportError(t, got, want, ops)
    95  	}
    96  
    97  	pubSigner, ok := signer.Public().(ed25519.PublicKey)
    98  	if !ok {
    99  		got := ok
   100  		want := true
   101  		test.ReportError(t, got, want, ops)
   102  	}
   103  
   104  	got := ed25519.VerifyAny(pubSigner, msg, sig, ops)
   105  	want := true
   106  	if got != want {
   107  		test.ReportError(t, got, want, ops)
   108  	}
   109  }
   110  
   111  type badReader struct{}
   112  
   113  func (badReader) Read([]byte) (int, error) { return 0, errors.New("cannot read") }
   114  
   115  func TestErrors(t *testing.T) {
   116  	t.Run("badHash", func(t *testing.T) {
   117  		var msg [16]byte
   118  		ops := crypto.SHA224
   119  		_, priv, _ := ed25519.GenerateKey(nil)
   120  		_, got := priv.Sign(nil, msg[:], ops)
   121  		want := errors.New("ed25519: bad hash algorithm")
   122  		if got.Error() != want.Error() {
   123  			test.ReportError(t, got, want)
   124  		}
   125  	})
   126  	t.Run("badReader", func(t *testing.T) {
   127  		_, _, got := ed25519.GenerateKey(badReader{})
   128  		want := errors.New("cannot read")
   129  		if got.Error() != want.Error() {
   130  			test.ReportError(t, got, want)
   131  		}
   132  	})
   133  	t.Run("wrongSeedSize", func(t *testing.T) {
   134  		var seed [256]byte
   135  		var want error
   136  		got := test.CheckPanic(func() { ed25519.NewKeyFromSeed(seed[:]) })
   137  		if got != want {
   138  			test.ReportError(t, got, want)
   139  		}
   140  	})
   141  }
   142  
   143  func BenchmarkEd25519Ph(b *testing.B) {
   144  	msg := make([]byte, 128)
   145  	_, _ = rand.Read(msg)
   146  
   147  	b.Run("Sign", func(b *testing.B) {
   148  		_, key, _ := ed25519.GenerateKey(rand.Reader)
   149  		ctx := ""
   150  		b.ResetTimer()
   151  		for i := 0; i < b.N; i++ {
   152  			_ = ed25519.SignPh(key, msg, ctx)
   153  		}
   154  	})
   155  	b.Run("Verify", func(b *testing.B) {
   156  		pub, priv, _ := ed25519.GenerateKey(rand.Reader)
   157  		ctx := ""
   158  		sig := ed25519.SignPh(priv, msg, ctx)
   159  		b.ResetTimer()
   160  		for i := 0; i < b.N; i++ {
   161  			ed25519.VerifyPh(pub, msg, sig, ctx)
   162  		}
   163  	})
   164  }
   165  
   166  func BenchmarkEd25519Ctx(b *testing.B) {
   167  	ctx := "a context"
   168  	msg := make([]byte, 128)
   169  	_, _ = rand.Read(msg)
   170  	b.Run("Sign", func(b *testing.B) {
   171  		_, priv, _ := ed25519.GenerateKey(rand.Reader)
   172  		b.ResetTimer()
   173  		for i := 0; i < b.N; i++ {
   174  			_ = ed25519.SignWithCtx(priv, msg, ctx)
   175  		}
   176  	})
   177  	b.Run("Verify", func(b *testing.B) {
   178  		pub, priv, _ := ed25519.GenerateKey(rand.Reader)
   179  		sig := ed25519.SignWithCtx(priv, msg, ctx)
   180  		b.ResetTimer()
   181  		for i := 0; i < b.N; i++ {
   182  			ed25519.VerifyWithCtx(pub, msg, sig, ctx)
   183  		}
   184  	})
   185  }
   186  
   187  func Example_ed25519() {
   188  	// import "github.com/cloudflare/circl/sign/ed25519"
   189  	// import "crypto/rand"
   190  
   191  	// Generating Alice's key pair
   192  	pub, priv, err := ed25519.GenerateKey(rand.Reader)
   193  	if err != nil {
   194  		panic("error on generating keys")
   195  	}
   196  
   197  	// Alice signs a message.
   198  	message := []byte("A message to be signed")
   199  	signature := ed25519.Sign(priv, message)
   200  
   201  	// Anyone can verify the signature using Alice's public key.
   202  	ok := ed25519.Verify(pub, message, signature)
   203  	fmt.Println(ok)
   204  	// Output: true
   205  }
   206  
   207  func ExampleSignPh() {
   208  	// import "github.com/cloudflare/circl/sign/ed25519"
   209  	// import "crypto/rand"
   210  
   211  	// Generating Alice's key pair
   212  	pub, priv, err := ed25519.GenerateKey(rand.Reader)
   213  	if err != nil {
   214  		panic("error on generating keys")
   215  	}
   216  
   217  	// Alice signs a message.
   218  	message := []byte("A message to be signed")
   219  	ctx := "an optional context string"
   220  
   221  	signature := ed25519.SignPh(priv, message, ctx)
   222  
   223  	// Anyone can verify the signature using Alice's public key.
   224  	ok := ed25519.VerifyPh(pub, message, signature, ctx)
   225  	fmt.Println(ok)
   226  	// Output: true
   227  }
   228  
   229  func ExampleSignWithCtx() {
   230  	// import "github.com/cloudflare/circl/sign/ed25519"
   231  	// import "crypto/rand"
   232  
   233  	// Generating Alice's key pair
   234  	pub, priv, err := ed25519.GenerateKey(rand.Reader)
   235  	if err != nil {
   236  		panic("error on generating keys")
   237  	}
   238  
   239  	// Alice signs a message.
   240  	message := []byte("A message to be signed")
   241  	ctx := "a non-empty context string"
   242  
   243  	signature := ed25519.SignWithCtx(priv, message, ctx)
   244  
   245  	// Anyone can verify the signature using Alice's public key.
   246  	ok := ed25519.VerifyWithCtx(pub, message, signature, ctx)
   247  	fmt.Println(ok)
   248  	// Output: true
   249  }