gitlab.com/SiaPrime/SiaPrime@v1.4.1/crypto/signatures_test.go (about)

     1  package crypto
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     6  
     7  	"gitlab.com/NebulousLabs/fastrand"
     8  	"gitlab.com/SiaPrime/SiaPrime/encoding"
     9  )
    10  
    11  // TestUnitSignatureEncoding creates and encodes a public key, and verifies
    12  // that it decodes correctly, does the same with a signature.
    13  func TestUnitSignatureEncoding(t *testing.T) {
    14  	// Create a dummy key pair.
    15  	var sk SecretKey
    16  	sk[0] = 4
    17  	sk[32] = 5
    18  	pk := sk.PublicKey()
    19  
    20  	// Marshal and unmarshal the public key.
    21  	marshalledPK := encoding.Marshal(pk)
    22  	var unmarshalledPK PublicKey
    23  	err := encoding.Unmarshal(marshalledPK, &unmarshalledPK)
    24  	if err != nil {
    25  		t.Fatal(err)
    26  	}
    27  
    28  	// Test the public keys for equality.
    29  	if pk != unmarshalledPK {
    30  		t.Error("pubkey not the same after marshalling and unmarshalling")
    31  	}
    32  
    33  	// Create a signature using the secret key.
    34  	var signedData Hash
    35  	fastrand.Read(signedData[:])
    36  	sig := SignHash(signedData, sk)
    37  
    38  	// Marshal and unmarshal the signature.
    39  	marshalledSig := encoding.Marshal(sig)
    40  	var unmarshalledSig Signature
    41  	err = encoding.Unmarshal(marshalledSig, &unmarshalledSig)
    42  	if err != nil {
    43  		t.Fatal(err)
    44  	}
    45  
    46  	// Test signatures for equality.
    47  	if sig != unmarshalledSig {
    48  		t.Error("signature not same after marshalling and unmarshalling")
    49  	}
    50  
    51  }
    52  
    53  // TestUnitSigning creates a bunch of keypairs and signs random data with each of
    54  // them.
    55  func TestUnitSigning(t *testing.T) {
    56  	if testing.Short() {
    57  		t.SkipNow()
    58  	}
    59  
    60  	// Try a bunch of signatures because at one point there was a library that
    61  	// worked around 98% of the time. Tests would usually pass, but 200
    62  	// iterations would normally cause a failure.
    63  	iterations := 200
    64  	for i := 0; i < iterations; i++ {
    65  		// Create dummy key pair.
    66  		sk, pk := GenerateKeyPair()
    67  
    68  		// Generate and sign the data.
    69  		var randData Hash
    70  		fastrand.Read(randData[:])
    71  		sig := SignHash(randData, sk)
    72  
    73  		// Verify the signature.
    74  		err := VerifyHash(randData, pk, sig)
    75  		if err != nil {
    76  			t.Fatal(err)
    77  		}
    78  
    79  		// Attempt to verify after the data has been altered.
    80  		randData[0]++
    81  		err = VerifyHash(randData, pk, sig)
    82  		if err != ErrInvalidSignature {
    83  			t.Fatal(err)
    84  		}
    85  
    86  		// Restore the data and make sure the signature is valid again.
    87  		randData[0]--
    88  		err = VerifyHash(randData, pk, sig)
    89  		if err != nil {
    90  			t.Fatal(err)
    91  		}
    92  
    93  		// Attempt to verify after the signature has been altered.
    94  		sig[0]++
    95  		err = VerifyHash(randData, pk, sig)
    96  		if err != ErrInvalidSignature {
    97  			t.Fatal(err)
    98  		}
    99  	}
   100  }
   101  
   102  // TestIntegrationSigKeyGenerate is an integration test checking that
   103  // GenerateKeyPair and GenerateKeyPairDeterminisitc accurately create keys.
   104  func TestIntegrationSigKeyGeneration(t *testing.T) {
   105  	if testing.Short() {
   106  		t.SkipNow()
   107  	}
   108  	message := HashBytes([]byte{'m', 's', 'g'})
   109  
   110  	// Create a random key and use it.
   111  	randSecKey, randPubKey := GenerateKeyPair()
   112  	sig := SignHash(message, randSecKey)
   113  	err := VerifyHash(message, randPubKey, sig)
   114  	if err != nil {
   115  		t.Error(err)
   116  	}
   117  	// Corrupt the signature
   118  	sig[0]++
   119  	err = VerifyHash(message, randPubKey, sig)
   120  	if err == nil {
   121  		t.Error("corruption failed")
   122  	}
   123  
   124  	// Create a deterministic key and use it.
   125  	var detEntropy [EntropySize]byte
   126  	detEntropy[0] = 35
   127  	detSecKey, detPubKey := GenerateKeyPairDeterministic(detEntropy)
   128  	sig = SignHash(message, detSecKey)
   129  	err = VerifyHash(message, detPubKey, sig)
   130  	if err != nil {
   131  		t.Error(err)
   132  	}
   133  	// Corrupt the signature
   134  	sig[0]++
   135  	err = VerifyHash(message, detPubKey, sig)
   136  	if err == nil {
   137  		t.Error("corruption failed")
   138  	}
   139  }
   140  
   141  // TestReadWriteSignedObject tests the ReadSignObject and WriteSignedObject
   142  // functions, which are inverses of each other.
   143  func TestReadWriteSignedObject(t *testing.T) {
   144  	sk, pk := GenerateKeyPair()
   145  
   146  	// Write signed object into buffer.
   147  	b := new(bytes.Buffer)
   148  	err := WriteSignedObject(b, "foo", sk)
   149  	if err != nil {
   150  		t.Fatal(err)
   151  	}
   152  	// Keep a copy of b's bytes.
   153  	buf := b.Bytes()
   154  
   155  	// Read and verify object.
   156  	var read string
   157  	err = ReadSignedObject(b, &read, 11, pk)
   158  	if err != nil {
   159  		t.Fatal(err)
   160  	}
   161  	if read != "foo" {
   162  		t.Fatal("encode/decode mismatch: expected 'foo', got", []byte(read))
   163  	}
   164  
   165  	// Check that maxlen is being respected.
   166  	b = bytes.NewBuffer(buf) // reset b
   167  	err = ReadSignedObject(b, &read, 10, pk)
   168  	if err == nil || err.Error() != "length 11 exceeds maxLen of 10" {
   169  		t.Fatal("expected length error, got", err)
   170  	}
   171  
   172  	// Disrupt the decoding to get coverage on the failure branch.
   173  	err = ReadSignedObject(b, &read, 11, pk)
   174  	if err == nil || err.Error() != "could not decode type crypto.Signature: unexpected EOF" {
   175  		t.Fatal(err)
   176  	}
   177  
   178  	// Try with an invalid signature.
   179  	buf[0]++                 // alter the first byte of the signature, invalidating it.
   180  	b = bytes.NewBuffer(buf) // reset b
   181  	err = ReadSignedObject(b, &read, 11, pk)
   182  	if err != ErrInvalidSignature {
   183  		t.Fatal(err)
   184  	}
   185  }
   186  
   187  // TestUnitPublicKey tests the PublicKey method
   188  func TestUnitPublicKey(t *testing.T) {
   189  	for i := 0; i < 1000; i++ {
   190  		sk, pk := GenerateKeyPair()
   191  		if sk.PublicKey() != pk {
   192  			t.Error("PublicKey does not match actual public key:", pk, sk.PublicKey())
   193  		}
   194  	}
   195  }