gitlab.com/jokerrs1/Sia@v1.3.2/crypto/encrypt_test.go (about)

     1  package crypto
     2  
     3  import (
     4  	"bytes"
     5  	"compress/gzip"
     6  	"testing"
     7  
     8  	"github.com/NebulousLabs/fastrand"
     9  )
    10  
    11  // TestTwofishEncryption checks that encryption and decryption works correctly.
    12  func TestTwofishEncryption(t *testing.T) {
    13  	// Get a key for encryption.
    14  	key := GenerateTwofishKey()
    15  
    16  	// Encrypt and decrypt a zero plaintext, and compare the decrypted to the
    17  	// original.
    18  	plaintext := make([]byte, 600)
    19  	ciphertext := key.EncryptBytes(plaintext)
    20  	decryptedPlaintext, err := key.DecryptBytes(ciphertext)
    21  	if err != nil {
    22  		t.Fatal(err)
    23  	}
    24  	if !bytes.Equal(plaintext, decryptedPlaintext) {
    25  		t.Fatal("Encrypted and decrypted zero plaintext do not match")
    26  	}
    27  
    28  	// Try again with a nonzero plaintext.
    29  	plaintext = fastrand.Bytes(600)
    30  	ciphertext = key.EncryptBytes(plaintext)
    31  	decryptedPlaintext, err = key.DecryptBytes(ciphertext)
    32  	if err != nil {
    33  		t.Fatal(err)
    34  	}
    35  	if !bytes.Equal(plaintext, decryptedPlaintext) {
    36  		t.Fatal("Encrypted and decrypted zero plaintext do not match")
    37  	}
    38  
    39  	// Try to decrypt using a different key
    40  	key2 := GenerateTwofishKey()
    41  	_, err = key2.DecryptBytes(ciphertext)
    42  	if err == nil {
    43  		t.Fatal("Expecting failed authentication err", err)
    44  	}
    45  
    46  	// Try to decrypt using bad ciphertexts.
    47  	ciphertext[0]++
    48  	_, err = key.DecryptBytes(ciphertext)
    49  	if err == nil {
    50  		t.Fatal("Expecting failed authentication err", err)
    51  	}
    52  	_, err = key.DecryptBytes(ciphertext[:10])
    53  	if err != ErrInsufficientLen {
    54  		t.Error("Expecting ErrInsufficientLen:", err)
    55  	}
    56  
    57  	// Try to trigger a panic or error with nil values.
    58  	key.EncryptBytes(nil)
    59  	_, err = key.DecryptBytes(nil)
    60  	if err != ErrInsufficientLen {
    61  		t.Error("Expecting ErrInsufficientLen:", err)
    62  	}
    63  }
    64  
    65  // TestReaderWriter probes the NewReader and NewWriter methods of the key type.
    66  func TestReaderWriter(t *testing.T) {
    67  	// Get a key for encryption.
    68  	key := GenerateTwofishKey()
    69  
    70  	// Generate plaintext.
    71  	const plaintextSize = 600
    72  	plaintext := fastrand.Bytes(plaintextSize)
    73  
    74  	// Create writer and encrypt plaintext.
    75  	buf := new(bytes.Buffer)
    76  	key.NewWriter(buf).Write(plaintext)
    77  
    78  	// There should be no overhead present.
    79  	if buf.Len() != plaintextSize {
    80  		t.Fatalf("encryption introduced %v bytes of overhead", buf.Len()-plaintextSize)
    81  	}
    82  
    83  	// Create reader and decrypt ciphertext.
    84  	var decrypted = make([]byte, plaintextSize)
    85  	key.NewReader(buf).Read(decrypted)
    86  
    87  	if !bytes.Equal(plaintext, decrypted) {
    88  		t.Error("couldn't decrypt encrypted stream")
    89  	}
    90  }
    91  
    92  // TestTwofishEntropy encrypts and then decrypts a zero plaintext, checking
    93  // that the ciphertext is high entropy.
    94  func TestTwofishEntropy(t *testing.T) {
    95  	if testing.Short() {
    96  		t.SkipNow()
    97  	}
    98  
    99  	// Encrypt a larger zero plaintext and make sure that the outcome is high
   100  	// entropy. Entropy is measured by compressing the ciphertext with gzip.
   101  	// 10 * 1000 bytes was chosen to minimize the impact of gzip overhead.
   102  	const cipherSize = 10e3
   103  	key := GenerateTwofishKey()
   104  	plaintext := make([]byte, cipherSize)
   105  	ciphertext := key.EncryptBytes(plaintext)
   106  
   107  	// Gzip the ciphertext
   108  	var b bytes.Buffer
   109  	zip := gzip.NewWriter(&b)
   110  	_, err := zip.Write(ciphertext)
   111  	if err != nil {
   112  		t.Fatal(err)
   113  	}
   114  	zip.Close()
   115  	if b.Len() < cipherSize {
   116  		t.Error("supposedly high entropy ciphertext has been compressed!")
   117  	}
   118  }
   119  
   120  // TestUnitCiphertextUnmarshalInvalidJSON tests that Ciphertext.UnmarshalJSON
   121  // correctly fails on invalid JSON marshalled Ciphertext.
   122  func TestUnitCiphertextUnmarshalInvalidJSON(t *testing.T) {
   123  	// Test unmarshalling invalid JSON.
   124  	invalidJSONBytes := [][]byte{
   125  		nil,
   126  		{},
   127  		[]byte("\""),
   128  	}
   129  	for _, jsonBytes := range invalidJSONBytes {
   130  		var ct Ciphertext
   131  		err := ct.UnmarshalJSON(jsonBytes)
   132  		if err == nil {
   133  			t.Errorf("expected unmarshall to fail on the invalid JSON: %q\n", jsonBytes)
   134  		}
   135  	}
   136  }
   137  
   138  // TestCiphertextMarshalling tests that marshalling Ciphertexts to JSON results
   139  // in the expected JSON. Also tests that marshalling that JSON back to
   140  // Ciphertext results in the original Ciphertext.
   141  func TestCiphertextMarshalling(t *testing.T) {
   142  	// Ciphertexts and corresponding JSONs to test marshalling and
   143  	// unmarshalling.
   144  	ciphertextMarshallingTests := []struct {
   145  		ct        Ciphertext
   146  		jsonBytes []byte
   147  	}{
   148  		{ct: Ciphertext(nil), jsonBytes: []byte("null")},
   149  		{ct: Ciphertext(""), jsonBytes: []byte(`""`)},
   150  		{ct: Ciphertext("a ciphertext"), jsonBytes: []byte(`"YSBjaXBoZXJ0ZXh0"`) /* base64 encoding of the Ciphertext */},
   151  	}
   152  	for _, test := range ciphertextMarshallingTests {
   153  		expectedCt := test.ct
   154  		expectedJSONBytes := test.jsonBytes
   155  
   156  		// Create a copy of expectedCt so Unmarshalling does not modify it, as
   157  		// we need it later for comparison.
   158  		var ct Ciphertext
   159  		if expectedCt == nil {
   160  			ct = nil
   161  		} else {
   162  			ct = make(Ciphertext, len(expectedCt))
   163  			copy(ct, expectedCt)
   164  		}
   165  
   166  		// Marshal Ciphertext to JSON.
   167  		jsonBytes, err := ct.MarshalJSON()
   168  		if err != nil {
   169  			t.Fatal(err)
   170  		}
   171  		if !bytes.Equal(jsonBytes, expectedJSONBytes) {
   172  			// Use %#v instead of %v because %v prints Ciphertexts constructed
   173  			// with nil and []byte{} identically.
   174  			t.Fatalf("Ciphertext %#v marshalled incorrectly: expected %q, got %q\n", ct, expectedJSONBytes, jsonBytes)
   175  		}
   176  
   177  		// Unmarshal back to Ciphertext.
   178  		err = ct.UnmarshalJSON(jsonBytes)
   179  		if err != nil {
   180  			t.Fatal(err)
   181  		}
   182  		// Compare resulting Ciphertext with expected Ciphertext.
   183  		if expectedCt == nil && ct != nil || expectedCt != nil && ct == nil || !bytes.Equal(expectedCt, ct) {
   184  			// Use %#v instead of %v because %v prints Ciphertexts constructed
   185  			// with nil and []byte{} identically.
   186  			t.Errorf("Ciphertext %#v unmarshalled incorrectly: got %#v\n", expectedCt, ct)
   187  		}
   188  	}
   189  }
   190  
   191  // TestTwofishNewCipherAssumption tests that the length of a TwofishKey is 16,
   192  // 24, or 32 as these are the only cases where twofish.NewCipher(key[:])
   193  // doesn't return an error.
   194  func TestTwofishNewCipherAssumption(t *testing.T) {
   195  	// Generate key.
   196  	key := GenerateTwofishKey()
   197  	// Test key length.
   198  	keyLen := len(key)
   199  	if keyLen != 16 && keyLen != 24 && keyLen != 32 {
   200  		t.Errorf("TwofishKey must have length 16, 24, or 32, but generated key has length %d\n", keyLen)
   201  	}
   202  }
   203  
   204  // TestCipherNewGCMAssumption tests that the BlockSize of a cipher block is 16,
   205  // as this is the only case where cipher.NewGCM(block) doesn't return an error.
   206  func TestCipherNewGCMAssumption(t *testing.T) {
   207  	// Generate a key and then cipher block from key.
   208  	key := GenerateTwofishKey()
   209  	// Test block size.
   210  	block := key.NewCipher()
   211  	if block.BlockSize() != 16 {
   212  		t.Errorf("cipher must have BlockSize 16, but generated cipher has BlockSize %d\n", block.BlockSize())
   213  	}
   214  }