Home | History | Annotate | Download | only in ed25519
      1 // Copyright 2016 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package ed25519
      6 
      7 import (
      8 	"bufio"
      9 	"bytes"
     10 	"compress/gzip"
     11 	"crypto"
     12 	"crypto/rand"
     13 	"encoding/hex"
     14 	"os"
     15 	"strings"
     16 	"testing"
     17 
     18 	"boringssl.googlesource.com/boringssl/ssl/test/runner/ed25519/internal/edwards25519"
     19 )
     20 
     21 type zeroReader struct{}
     22 
     23 func (zeroReader) Read(buf []byte) (int, error) {
     24 	for i := range buf {
     25 		buf[i] = 0
     26 	}
     27 	return len(buf), nil
     28 }
     29 
     30 func TestUnmarshalMarshal(t *testing.T) {
     31 	pub, _, _ := GenerateKey(rand.Reader)
     32 
     33 	var A edwards25519.ExtendedGroupElement
     34 	var pubBytes [32]byte
     35 	copy(pubBytes[:], pub)
     36 	if !A.FromBytes(&pubBytes) {
     37 		t.Fatalf("ExtendedGroupElement.FromBytes failed")
     38 	}
     39 
     40 	var pub2 [32]byte
     41 	A.ToBytes(&pub2)
     42 
     43 	if pubBytes != pub2 {
     44 		t.Errorf("FromBytes(%v)->ToBytes does not round-trip, got %x\n", pubBytes, pub2)
     45 	}
     46 }
     47 
     48 func TestSignVerify(t *testing.T) {
     49 	var zero zeroReader
     50 	public, private, _ := GenerateKey(zero)
     51 
     52 	message := []byte("test message")
     53 	sig := Sign(private, message)
     54 	if !Verify(public, message, sig) {
     55 		t.Errorf("valid signature rejected")
     56 	}
     57 
     58 	wrongMessage := []byte("wrong message")
     59 	if Verify(public, wrongMessage, sig) {
     60 		t.Errorf("signature of different message accepted")
     61 	}
     62 }
     63 
     64 func TestCryptoSigner(t *testing.T) {
     65 	var zero zeroReader
     66 	public, private, _ := GenerateKey(zero)
     67 
     68 	signer := crypto.Signer(private)
     69 
     70 	publicInterface := signer.Public()
     71 	public2, ok := publicInterface.(PublicKey)
     72 	if !ok {
     73 		t.Fatalf("expected PublicKey from Public() but got %T", publicInterface)
     74 	}
     75 
     76 	if !bytes.Equal(public, public2) {
     77 		t.Errorf("public keys do not match: original:%x vs Public():%x", public, public2)
     78 	}
     79 
     80 	message := []byte("message")
     81 	var noHash crypto.Hash
     82 	signature, err := signer.Sign(zero, message, noHash)
     83 	if err != nil {
     84 		t.Fatalf("error from Sign(): %s", err)
     85 	}
     86 
     87 	if !Verify(public, message, signature) {
     88 		t.Errorf("Verify failed on signature from Sign()")
     89 	}
     90 }
     91 
     92 func TestGolden(t *testing.T) {
     93 	// sign.input.gz is a selection of test cases from
     94 	// https://ed25519.cr.yp.to/python/sign.input
     95 	testDataZ, err := os.Open("testdata/sign.input.gz")
     96 	if err != nil {
     97 		t.Fatal(err)
     98 	}
     99 	defer testDataZ.Close()
    100 	testData, err := gzip.NewReader(testDataZ)
    101 	if err != nil {
    102 		t.Fatal(err)
    103 	}
    104 	defer testData.Close()
    105 
    106 	scanner := bufio.NewScanner(testData)
    107 	lineNo := 0
    108 
    109 	for scanner.Scan() {
    110 		lineNo++
    111 
    112 		line := scanner.Text()
    113 		parts := strings.Split(line, ":")
    114 		if len(parts) != 5 {
    115 			t.Fatalf("bad number of parts on line %d", lineNo)
    116 		}
    117 
    118 		privBytes, _ := hex.DecodeString(parts[0])
    119 		pubKey, _ := hex.DecodeString(parts[1])
    120 		msg, _ := hex.DecodeString(parts[2])
    121 		sig, _ := hex.DecodeString(parts[3])
    122 		// The signatures in the test vectors also include the message
    123 		// at the end, but we just want R and S.
    124 		sig = sig[:SignatureSize]
    125 
    126 		if l := len(pubKey); l != PublicKeySize {
    127 			t.Fatalf("bad public key length on line %d: got %d bytes", lineNo, l)
    128 		}
    129 
    130 		var priv [PrivateKeySize]byte
    131 		copy(priv[:], privBytes)
    132 		copy(priv[32:], pubKey)
    133 
    134 		sig2 := Sign(priv[:], msg)
    135 		if !bytes.Equal(sig, sig2[:]) {
    136 			t.Errorf("different signature result on line %d: %x vs %x", lineNo, sig, sig2)
    137 		}
    138 
    139 		if !Verify(pubKey, msg, sig2) {
    140 			t.Errorf("signature failed to verify on line %d", lineNo)
    141 		}
    142 
    143 		priv2 := NewKeyFromSeed(priv[:32])
    144 		if !bytes.Equal(priv[:], priv2) {
    145 			t.Errorf("recreating key pair gave different private key on line %d: %x vs %x", lineNo, priv[:], priv2)
    146 		}
    147 
    148 		if pubKey2 := priv2.Public().(PublicKey); !bytes.Equal(pubKey, pubKey2) {
    149 			t.Errorf("recreating key pair gave different public key on line %d: %x vs %x", lineNo, pubKey, pubKey2)
    150 		}
    151 
    152 		if seed := priv2.Seed(); !bytes.Equal(priv[:32], seed) {
    153 			t.Errorf("recreating key pair gave different seed on line %d: %x vs %x", lineNo, priv[:32], seed)
    154 		}
    155 	}
    156 
    157 	if err := scanner.Err(); err != nil {
    158 		t.Fatalf("error reading test data: %s", err)
    159 	}
    160 }
    161 
    162 func TestMalleability(t *testing.T) {
    163 	// https://tools.ietf.org/html/rfc8032#section-5.1.7 adds an additional test
    164 	// that s be in [0, order). This prevents someone from adding a multiple of
    165 	// order to s and obtaining a second valid signature for the same message.
    166 	msg := []byte{0x54, 0x65, 0x73, 0x74}
    167 	sig := []byte{
    168 		0x7c, 0x38, 0xe0, 0x26, 0xf2, 0x9e, 0x14, 0xaa, 0xbd, 0x05, 0x9a,
    169 		0x0f, 0x2d, 0xb8, 0xb0, 0xcd, 0x78, 0x30, 0x40, 0x60, 0x9a, 0x8b,
    170 		0xe6, 0x84, 0xdb, 0x12, 0xf8, 0x2a, 0x27, 0x77, 0x4a, 0xb0, 0x67,
    171 		0x65, 0x4b, 0xce, 0x38, 0x32, 0xc2, 0xd7, 0x6f, 0x8f, 0x6f, 0x5d,
    172 		0xaf, 0xc0, 0x8d, 0x93, 0x39, 0xd4, 0xee, 0xf6, 0x76, 0x57, 0x33,
    173 		0x36, 0xa5, 0xc5, 0x1e, 0xb6, 0xf9, 0x46, 0xb3, 0x1d,
    174 	}
    175 	publicKey := []byte{
    176 		0x7d, 0x4d, 0x0e, 0x7f, 0x61, 0x53, 0xa6, 0x9b, 0x62, 0x42, 0xb5,
    177 		0x22, 0xab, 0xbe, 0xe6, 0x85, 0xfd, 0xa4, 0x42, 0x0f, 0x88, 0x34,
    178 		0xb1, 0x08, 0xc3, 0xbd, 0xae, 0x36, 0x9e, 0xf5, 0x49, 0xfa,
    179 	}
    180 
    181 	if Verify(publicKey, msg, sig) {
    182 		t.Fatal("non-canonical signature accepted")
    183 	}
    184 }
    185 
    186 func BenchmarkKeyGeneration(b *testing.B) {
    187 	var zero zeroReader
    188 	for i := 0; i < b.N; i++ {
    189 		if _, _, err := GenerateKey(zero); err != nil {
    190 			b.Fatal(err)
    191 		}
    192 	}
    193 }
    194 
    195 func BenchmarkSigning(b *testing.B) {
    196 	var zero zeroReader
    197 	_, priv, err := GenerateKey(zero)
    198 	if err != nil {
    199 		b.Fatal(err)
    200 	}
    201 	message := []byte("Hello, world!")
    202 	b.ResetTimer()
    203 	for i := 0; i < b.N; i++ {
    204 		Sign(priv, message)
    205 	}
    206 }
    207 
    208 func BenchmarkVerification(b *testing.B) {
    209 	var zero zeroReader
    210 	pub, priv, err := GenerateKey(zero)
    211 	if err != nil {
    212 		b.Fatal(err)
    213 	}
    214 	message := []byte("Hello, world!")
    215 	signature := Sign(priv, message)
    216 	b.ResetTimer()
    217 	for i := 0; i < b.N; i++ {
    218 		Verify(pub, message, signature)
    219 	}
    220 }
    221