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 }