package go_encryption import ( "bytes" "encoding/hex" "math/rand" "os" "path/filepath" "strings" "testing" ) type testStruct struct { BoolVal bool `json:"boolVal"` IntVal int `json:"intVal"` FloatVal float64 `json:"floatVal"` StringVal string `json:"stringVal"` } const ( defaultTestStructJSON = "{\"boolVal\":true,\"intVal\":1,\"floatVal\":0.42,\"stringVal\":\"testing\"}" defaultTestStructEncrypted = "SaRociSolutions\x80e#.\x8e\xc5M:\x90\xbe\x98\xd2\xdasA䊭\\cp%\xc4w\xea\x8bSِ\x80\xbe\xdc|o\x13\xb1JݛC\x0fG\xca\xdbc\x85I6\xbdd\x03O[a@%\x91'K\xd0r\x9e\xf1[\x8cx\xdfG\x8cc^|\x82\x95Jf[\xdaC\xd9I" contextTestStructEncrypted = "__-=SaRoci=-__\xe45\xefVFJ\xa2\x1b\xb3\x93\t\x10lar՜\x992\xaf}\x83V\xa9\xff\xfe,U\x19%\xe7\xfbvۚ\xb2\xfe\xaeH@=Q\xabX\x17\u007f\xb0\xf4\xc9\f3\x02\x84\x80\x8b\xac\x86\x97C\f\xe8)\xf7f\x1e\u05cdy\xd0|p\x936\xe5\xe3\xb9u\xf3\x01̋" ) var ( defaultTestStruct = testStruct{ BoolVal: true, IntVal: 1, FloatVal: 0.42, StringVal: "testing", } ) func getImplementation() *aes128encryption { return NewAES128EncryptionProvider().(*aes128encryption) } func Test_GetCrypter(t *testing.T) { t.Parallel() e := getImplementation() var err error if _, err = e.getCrypter(); err != nil { t.Error("unexpected error in default crypter-generation") } e.encryptionKey = e.encryptionKey[:len(e.encryptionKey)-1] if _, err = e.getCrypter(); err == nil { t.Error("expected error in crypter-generation for bad length hex-encoded key did not occur") } e.encryptionKey = e.encryptionKey[:len(e.encryptionKey)-1] if _, err = e.getCrypter(); err == nil { t.Error("expected error in crypter-generation for bad key size did not occur") } } func Test_SetEncryptionKey(t *testing.T) { t.Parallel() e := getImplementation() binaryKey := append([]byte{}, e.encryptionKey...) e.SetEncryptionKey(binaryKey) if !strings.EqualFold(defaultEncryptionKey, hex.EncodeToString(e.encryptionKey)) { t.Error("Test_SetEncryptionKey: test case 1: encryption key should not have changed") } binaryKey[4] = 42 binaryKey[5] = 42 binaryKey[6] = 42 e.SetEncryptionKey(binaryKey) if strings.EqualFold(defaultEncryptionKey, hex.EncodeToString(e.encryptionKey)) { t.Error("Test_SetEncryptionKey: test case 2: encryption key was not changed") } binaryKey = append(binaryKey, binaryKey...) e.SetEncryptionKey(binaryKey) if strings.EqualFold(defaultEncryptionKey, hex.EncodeToString(e.encryptionKey)) { t.Error("Test_SetEncryptionKey: test case 3: encryption key was not changed") } binaryKey = binaryKey[:3] e.SetEncryptionKey(binaryKey) if strings.EqualFold(defaultEncryptionKey, hex.EncodeToString(e.encryptionKey)) { t.Error("Test_SetEncryptionKey: test case 4: encryption key was not changed") } e.SetEncryptionKey(nil) if !strings.EqualFold(defaultEncryptionKey, hex.EncodeToString(e.encryptionKey)) { t.Error("Test_SetEncryptionKey: test case 5: encryption key was not reset to default") } } func randomByteArray() []byte { len := rand.Intn(32) result := make([]byte, 0) for i := 0; i < len; i++ { result = append(result, byte(rand.Intn(256))) } return result } func Fuzz_SetContext(f *testing.F) { testCases := [][]byte{ nil, {}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, } for i := 0; i < 5; i++ { testCases = append(testCases, randomByteArray()) } for _, tc := range testCases { f.Add(tc) } f.Fuzz(func(t *testing.T, a []byte) { t.Parallel() e := NewAES128EncryptionProvider() result := e.SetContext(a) if 12 > len(a) || len(a) > 16 { if result == nil { t.Errorf("got no error for %v", a) } } else if result != nil { t.Errorf("got an error for %v", a) } if e.SetContext(defaultContext) != nil { t.Error("unable to reset context") } }) } func Test_Encrypt(t *testing.T) { t.Parallel() e := getImplementation() binary := []byte(defaultTestStructJSON) blank := make([]byte, len(binary)) if encrypted, err := e.Encrypt(binary); err != nil { t.Error("unexpected error in default encryption") } else if !bytes.Equal(encrypted, []byte(defaultTestStructEncrypted)) { t.Error("unexpected data for encrypted content") } else if !bytes.Equal(binary, blank) { t.Error("binary has not been blanked out") } } func Test_Decrypt(t *testing.T) { t.Parallel() e := getImplementation() if decrypted, err := e.Decrypt([]byte(defaultTestStructEncrypted)); err != nil { t.Error("unexpected error in default decryption") } else if !bytes.Equal(decrypted, []byte(defaultTestStructJSON)) { t.Error("unexpected data for decrypted content") } if _, err := e.Decrypt([]byte(contextTestStructEncrypted)); err == nil { t.Error("expected context error did not occur") } if _, err := e.Decrypt([]byte(contextTestStructEncrypted)[:11]); err == nil { t.Error("expected length error did not occur") } } func Test_EncryptData(t *testing.T) { t.Parallel() e := NewAES128EncryptionProvider() if encrypted, err := e.EncryptData(defaultTestStruct); err != nil { t.Error("unexpected error in default data encryption") } else if !bytes.Equal(encrypted, []byte(defaultTestStructEncrypted)) { t.Error("unexpected data for encrypted content") } } func Test_DecryptData(t *testing.T) { t.Parallel() e := NewAES128EncryptionProvider() target := &testStruct{} if err := e.DecryptData([]byte(defaultTestStructEncrypted), target); err != nil { t.Error("unexpected error in default data decryption") } else if target.BoolVal != defaultTestStruct.BoolVal || target.FloatVal != defaultTestStruct.FloatVal || target.IntVal != defaultTestStruct.IntVal || target.StringVal != defaultTestStruct.StringVal { t.Error("retrieved struct does not match the expectations") } } func getTestFilePath(encrypt bool) string { fileName := "encryption_test_encrypted.data" if !encrypt { fileName = "encryption_test_decryptable.data" } return filepath.Join(os.Getenv("temp"), fileName) } func Test_EncryptToFile(t *testing.T) { t.Parallel() e := NewAES128EncryptionProvider() targetPath := getTestFilePath(true) if err := e.EncryptToFile(defaultTestStruct, targetPath); err != nil { t.Error("unexpected error in default encryption") } else if encrypted, errRead := os.ReadFile(targetPath); errRead == nil { os.Remove(targetPath) if !bytes.Equal(encrypted, []byte(defaultTestStructEncrypted)) { t.Error("unexpected data for encrypted content") } } else { t.Errorf("expected file could not be read: %s", errRead) if !os.IsNotExist(errRead) { os.Remove(targetPath) } } } func Test_DecryptFile(t *testing.T) { t.Parallel() sourcePath := getTestFilePath(false) if os.WriteFile(sourcePath, []byte(defaultTestStructEncrypted), os.ModePerm) == nil { target := &testStruct{} e := NewAES128EncryptionProvider() if err := e.DecryptFile(sourcePath, target); err != nil { t.Error("unexpected error in default decryption") } else if target.BoolVal != defaultTestStruct.BoolVal || target.FloatVal != defaultTestStruct.FloatVal || target.IntVal != defaultTestStruct.IntVal || target.StringVal != defaultTestStruct.StringVal { t.Error("retrieved struct does not match the expectations") } os.Remove(sourcePath) } else { t.Error("could not prepare test file for decryption") } }