package symm import ( "bytes" "encoding/hex" "testing" ) func TestEncryptAesDefaultModeCBC(t *testing.T) { key := []byte("0123456789abcdef") iv := []byte("abcdef9876543210") plain := []byte("aes-default-mode-cbc") encDefault, err := EncryptAes(plain, key, iv, "", "") if err != nil { t.Fatalf("EncryptAes default failed: %v", err) } encCBC, err := EncryptAesCBC(plain, key, iv, "") if err != nil { t.Fatalf("EncryptAesCBC failed: %v", err) } if !bytes.Equal(encDefault, encCBC) { t.Fatalf("default mode should match CBC mode") } } func TestAESCBCRoundTripDefaultPKCS7(t *testing.T) { key := []byte("0123456789abcdef") iv := []byte("abcdef9876543210") plain := []byte("aes-cbc-with-default-padding") enc, err := EncryptAesCBC(plain, key, iv, "") if err != nil { t.Fatalf("EncryptAesCBC failed: %v", err) } dec, err := DecryptAesCBC(enc, key, iv, "") if err != nil { t.Fatalf("DecryptAesCBC failed: %v", err) } if !bytes.Equal(dec, plain) { t.Fatalf("aes cbc mismatch, got %q want %q", dec, plain) } } func TestAESCFBRoundTrip(t *testing.T) { key := []byte("0123456789abcdef") plain := []byte("aes-cfb-roundtrip") enc, err := CustomEncryptAesCFB(plain, key) if err != nil { t.Fatalf("CustomEncryptAesCFB failed: %v", err) } dec, err := CustomDecryptAesCFB(enc, key) if err != nil { t.Fatalf("CustomDecryptAesCFB failed: %v", err) } if !bytes.Equal(dec, plain) { t.Fatalf("aes cfb mismatch, got %q want %q", dec, plain) } } func TestAesGenericModesRoundTrip(t *testing.T) { key := []byte("0123456789abcdef") iv := []byte("abcdef9876543210") plain := []byte("generic-aes-mode-roundtrip") modes := []string{MODEECB, MODECBC, MODECFB, MODEOFB, MODECTR} for _, mode := range modes { t.Run(mode, func(t *testing.T) { useIV := iv if mode == MODEECB { useIV = nil } enc, err := EncryptAes(plain, key, useIV, mode, "") if err != nil { t.Fatalf("EncryptAes(%s) failed: %v", mode, err) } dec, err := DecryptAes(enc, key, useIV, mode, "") if err != nil { t.Fatalf("DecryptAes(%s) failed: %v", mode, err) } if !bytes.Equal(dec, plain) { t.Fatalf("aes %s mismatch", mode) } }) } } func TestAesDerivedFunctionsRoundTrip(t *testing.T) { key := []byte("0123456789abcdef") iv := []byte("abcdef9876543210") plain := []byte("aes-derived-func-roundtrip") ecbEnc, err := EncryptAesECB(plain, key, "") if err != nil { t.Fatalf("EncryptAesECB failed: %v", err) } ecbDec, err := DecryptAesECB(ecbEnc, key, "") if err != nil { t.Fatalf("DecryptAesECB failed: %v", err) } if !bytes.Equal(ecbDec, plain) { t.Fatalf("aes ecb mismatch") } cfbEnc, err := EncryptAesCFB(plain, key, iv) if err != nil { t.Fatalf("EncryptAesCFB failed: %v", err) } cfbDec, err := DecryptAesCFB(cfbEnc, key, iv) if err != nil { t.Fatalf("DecryptAesCFB failed: %v", err) } if !bytes.Equal(cfbDec, plain) { t.Fatalf("aes cfb mismatch") } ofbEnc, err := EncryptAesOFB(plain, key, iv) if err != nil { t.Fatalf("EncryptAesOFB failed: %v", err) } ofbDec, err := DecryptAesOFB(ofbEnc, key, iv) if err != nil { t.Fatalf("DecryptAesOFB failed: %v", err) } if !bytes.Equal(ofbDec, plain) { t.Fatalf("aes ofb mismatch") } ctrEnc, err := EncryptAesCTR(plain, key, iv) if err != nil { t.Fatalf("EncryptAesCTR failed: %v", err) } ctrDec, err := DecryptAesCTR(ctrEnc, key, iv) if err != nil { t.Fatalf("DecryptAesCTR failed: %v", err) } if !bytes.Equal(ctrDec, plain) { t.Fatalf("aes ctr mismatch") } } func TestAesStreamRoundTrip(t *testing.T) { key := []byte("0123456789abcdef") iv := []byte("abcdef9876543210") plain := []byte("streaming-aes-mode-roundtrip-content") modes := []string{MODEECB, MODECBC, MODECFB, MODEOFB, MODECTR} for _, mode := range modes { t.Run(mode, func(t *testing.T) { encBuf := &bytes.Buffer{} decBuf := &bytes.Buffer{} useIV := iv if mode == MODEECB { useIV = nil } if err := EncryptAesStream(encBuf, bytes.NewReader(plain), key, useIV, mode, ""); err != nil { t.Fatalf("EncryptAesStream(%s) failed: %v", mode, err) } if err := DecryptAesStream(decBuf, bytes.NewReader(encBuf.Bytes()), key, useIV, mode, ""); err != nil { t.Fatalf("DecryptAesStream(%s) failed: %v", mode, err) } if !bytes.Equal(decBuf.Bytes(), plain) { t.Fatalf("aes stream %s mismatch", mode) } }) } } func TestAesStreamInvalidMode(t *testing.T) { key := []byte("0123456789abcdef") iv := []byte("abcdef9876543210") err := EncryptAesStream(&bytes.Buffer{}, bytes.NewReader([]byte("x")), key, iv, "BAD", "") if err == nil { t.Fatalf("expected invalid mode error") } } func TestSM4CBCRoundTripDefaultPKCS7(t *testing.T) { key := []byte("0123456789abcdef") iv := []byte("abcdef9876543210") plain := []byte("sm4-cbc-with-default-padding") enc, err := EncryptSM4CBC(plain, key, iv, "") if err != nil { t.Fatalf("EncryptSM4CBC failed: %v", err) } dec, err := DecryptSM4CBC(enc, key, iv, "") if err != nil { t.Fatalf("DecryptSM4CBC failed: %v", err) } if !bytes.Equal(dec, plain) { t.Fatalf("sm4 cbc mismatch, got %q want %q", dec, plain) } } func TestSM4CFBRoundTrip(t *testing.T) { key := []byte("0123456789abcdef") plain := []byte("sm4-cfb-roundtrip") enc, err := EncryptSM4CFB(plain, key) if err != nil { t.Fatalf("EncryptSM4CFB failed: %v", err) } dec, err := DecryptSM4CFB(enc, key) if err != nil { t.Fatalf("DecryptSM4CFB failed: %v", err) } if !bytes.Equal(dec, plain) { t.Fatalf("sm4 cfb mismatch, got %q want %q", dec, plain) } } func TestSM4StreamRoundTrip(t *testing.T) { key := []byte("0123456789abcdef") iv := []byte("abcdef9876543210") plain := []byte("sm4-stream-roundtrip-data") encCBC := &bytes.Buffer{} if err := EncryptSM4CBCStream(encCBC, bytes.NewReader(plain), key, iv, ""); err != nil { t.Fatalf("EncryptSM4CBCStream failed: %v", err) } decCBC := &bytes.Buffer{} if err := DecryptSM4CBCStream(decCBC, bytes.NewReader(encCBC.Bytes()), key, iv, ""); err != nil { t.Fatalf("DecryptSM4CBCStream failed: %v", err) } if !bytes.Equal(decCBC.Bytes(), plain) { t.Fatalf("sm4 cbc stream mismatch") } encCFB := &bytes.Buffer{} if err := EncryptSM4CFBStream(encCFB, bytes.NewReader(plain), key, iv); err != nil { t.Fatalf("EncryptSM4CFBStream failed: %v", err) } decCFB := &bytes.Buffer{} if err := DecryptSM4CFBStream(decCFB, bytes.NewReader(encCFB.Bytes()), key, iv); err != nil { t.Fatalf("DecryptSM4CFBStream failed: %v", err) } if !bytes.Equal(decCFB.Bytes(), plain) { t.Fatalf("sm4 cfb stream mismatch") } } func TestDESCBCRoundTripDefaultPKCS5(t *testing.T) { key := []byte("12345678") iv := []byte("abcdefgh") plain := []byte("des-cbc") enc, err := EncryptDESCBC(plain, key, iv, "") if err != nil { t.Fatalf("EncryptDESCBC failed: %v", err) } dec, err := DecryptDESCBC(enc, key, iv, "") if err != nil { t.Fatalf("DecryptDESCBC failed: %v", err) } if !bytes.Equal(dec, plain) { t.Fatalf("des cbc mismatch, got %q want %q", dec, plain) } } func Test3DESCBCRoundTripDefaultPKCS5(t *testing.T) { key := []byte("12345678abcdefgh87654321") iv := []byte("12345678") plain := []byte("3des-cbc-default-padding") enc, err := Encrypt3DESCBC(plain, key, iv, "") if err != nil { t.Fatalf("Encrypt3DESCBC failed: %v", err) } dec, err := Decrypt3DESCBC(enc, key, iv, "") if err != nil { t.Fatalf("Decrypt3DESCBC failed: %v", err) } if !bytes.Equal(dec, plain) { t.Fatalf("3des cbc mismatch, got %q want %q", dec, plain) } } func TestDESStreamRoundTrip(t *testing.T) { desKey := []byte("12345678") desIV := []byte("abcdefgh") desPlain := []byte("des-stream-roundtrip") desEnc := &bytes.Buffer{} if err := EncryptDESCBCStream(desEnc, bytes.NewReader(desPlain), desKey, desIV, ""); err != nil { t.Fatalf("EncryptDESCBCStream failed: %v", err) } desDec := &bytes.Buffer{} if err := DecryptDESCBCStream(desDec, bytes.NewReader(desEnc.Bytes()), desKey, desIV, ""); err != nil { t.Fatalf("DecryptDESCBCStream failed: %v", err) } if !bytes.Equal(desDec.Bytes(), desPlain) { t.Fatalf("des cbc stream mismatch") } key3des := []byte("12345678abcdefgh87654321") iv3des := []byte("12345678") plain3des := []byte("3des-stream-roundtrip") enc3des := &bytes.Buffer{} if err := Encrypt3DESCBCStream(enc3des, bytes.NewReader(plain3des), key3des, iv3des, ""); err != nil { t.Fatalf("Encrypt3DESCBCStream failed: %v", err) } dec3des := &bytes.Buffer{} if err := Decrypt3DESCBCStream(dec3des, bytes.NewReader(enc3des.Bytes()), key3des, iv3des, ""); err != nil { t.Fatalf("Decrypt3DESCBCStream failed: %v", err) } if !bytes.Equal(dec3des.Bytes(), plain3des) { t.Fatalf("3des cbc stream mismatch") } } func TestCBCInvalidIVLength(t *testing.T) { _, err := EncryptAesCBC([]byte("a"), []byte("0123456789abcdef"), []byte("short"), PKCS7PADDING) if err == nil { t.Fatalf("expected invalid IV length error") } } func TestCBCInvalidCiphertextLength(t *testing.T) { _, err := DecryptSM4CBC([]byte("short"), []byte("0123456789abcdef"), []byte("abcdef9876543210"), PKCS7PADDING) if err == nil { t.Fatalf("expected invalid ciphertext length error") } } func TestCBCStreamInvalidCiphertextLength(t *testing.T) { err := DecryptAesCBCStream(&bytes.Buffer{}, bytes.NewReader([]byte("short")), []byte("0123456789abcdef"), []byte("abcdef9876543210"), PKCS7PADDING) if err == nil { t.Fatalf("expected invalid ciphertext length error") } } func TestSM4DerivedModesRoundTrip(t *testing.T) { key := []byte("0123456789abcdef") iv := []byte("abcdef9876543210") plain := []byte("sm4-derived-mode-roundtrip") ecbEnc, err := EncryptSM4ECB(plain, key, "") if err != nil { t.Fatalf("EncryptSM4ECB failed: %v", err) } ecbDec, err := DecryptSM4ECB(ecbEnc, key, "") if err != nil { t.Fatalf("DecryptSM4ECB failed: %v", err) } if !bytes.Equal(ecbDec, plain) { t.Fatalf("sm4 ecb mismatch") } ofbEnc, err := EncryptSM4OFB(plain, key, iv) if err != nil { t.Fatalf("EncryptSM4OFB failed: %v", err) } ofbDec, err := DecryptSM4OFB(ofbEnc, key, iv) if err != nil { t.Fatalf("DecryptSM4OFB failed: %v", err) } if !bytes.Equal(ofbDec, plain) { t.Fatalf("sm4 ofb mismatch") } ctrEnc, err := EncryptSM4CTR(plain, key, iv) if err != nil { t.Fatalf("EncryptSM4CTR failed: %v", err) } ctrDec, err := DecryptSM4CTR(ctrEnc, key, iv) if err != nil { t.Fatalf("DecryptSM4CTR failed: %v", err) } if !bytes.Equal(ctrDec, plain) { t.Fatalf("sm4 ctr mismatch") } } func TestSM4DerivedStreamRoundTrip(t *testing.T) { key := []byte("0123456789abcdef") iv := []byte("abcdef9876543210") plain := []byte("sm4-derived-stream-roundtrip") ecbEnc := &bytes.Buffer{} if err := EncryptSM4ECBStream(ecbEnc, bytes.NewReader(plain), key, ""); err != nil { t.Fatalf("EncryptSM4ECBStream failed: %v", err) } ecbDec := &bytes.Buffer{} if err := DecryptSM4ECBStream(ecbDec, bytes.NewReader(ecbEnc.Bytes()), key, ""); err != nil { t.Fatalf("DecryptSM4ECBStream failed: %v", err) } if !bytes.Equal(ecbDec.Bytes(), plain) { t.Fatalf("sm4 ecb stream mismatch") } ofbEnc := &bytes.Buffer{} if err := EncryptSM4OFBStream(ofbEnc, bytes.NewReader(plain), key, iv); err != nil { t.Fatalf("EncryptSM4OFBStream failed: %v", err) } ofbDec := &bytes.Buffer{} if err := DecryptSM4OFBStream(ofbDec, bytes.NewReader(ofbEnc.Bytes()), key, iv); err != nil { t.Fatalf("DecryptSM4OFBStream failed: %v", err) } if !bytes.Equal(ofbDec.Bytes(), plain) { t.Fatalf("sm4 ofb stream mismatch") } ctrEnc := &bytes.Buffer{} if err := EncryptSM4CTRStream(ctrEnc, bytes.NewReader(plain), key, iv); err != nil { t.Fatalf("EncryptSM4CTRStream failed: %v", err) } ctrDec := &bytes.Buffer{} if err := DecryptSM4CTRStream(ctrDec, bytes.NewReader(ctrEnc.Bytes()), key, iv); err != nil { t.Fatalf("DecryptSM4CTRStream failed: %v", err) } if !bytes.Equal(ctrDec.Bytes(), plain) { t.Fatalf("sm4 ctr stream mismatch") } } func TestChaCha20RoundTrip(t *testing.T) { key := []byte("0123456789abcdef0123456789abcdef") nonce := []byte("123456789012") plain := []byte("chacha20-roundtrip") enc, err := EncryptChaCha20(plain, key, nonce) if err != nil { t.Fatalf("EncryptChaCha20 failed: %v", err) } dec, err := DecryptChaCha20(enc, key, nonce) if err != nil { t.Fatalf("DecryptChaCha20 failed: %v", err) } if !bytes.Equal(dec, plain) { t.Fatalf("chacha20 mismatch") } } func TestChaCha20StreamRoundTrip(t *testing.T) { key := []byte("0123456789abcdef0123456789abcdef") nonce := []byte("123456789012") plain := []byte("chacha20-stream-roundtrip") enc := &bytes.Buffer{} if err := EncryptChaCha20Stream(enc, bytes.NewReader(plain), key, nonce); err != nil { t.Fatalf("EncryptChaCha20Stream failed: %v", err) } dec := &bytes.Buffer{} if err := DecryptChaCha20Stream(dec, bytes.NewReader(enc.Bytes()), key, nonce); err != nil { t.Fatalf("DecryptChaCha20Stream failed: %v", err) } if !bytes.Equal(dec.Bytes(), plain) { t.Fatalf("chacha20 stream mismatch") } } func TestChaCha20Poly1305RoundTrip(t *testing.T) { key := []byte("0123456789abcdef0123456789abcdef") nonce := []byte("123456789012") aad := []byte("aad") plain := []byte("chacha20-poly1305-roundtrip") enc, err := EncryptChaCha20Poly1305(plain, key, nonce, aad) if err != nil { t.Fatalf("EncryptChaCha20Poly1305 failed: %v", err) } dec, err := DecryptChaCha20Poly1305(enc, key, nonce, aad) if err != nil { t.Fatalf("DecryptChaCha20Poly1305 failed: %v", err) } if !bytes.Equal(dec, plain) { t.Fatalf("chacha20-poly1305 mismatch") } } func TestChaCha20Poly1305InvalidNonce(t *testing.T) { key := []byte("0123456789abcdef0123456789abcdef") _, err := EncryptChaCha20Poly1305([]byte("x"), key, []byte("short"), nil) if err == nil { t.Fatalf("expected invalid nonce error") } } func TestAESGCMNISTVectorEmpty(t *testing.T) { key := mustHex(t, "00000000000000000000000000000000") nonce := mustHex(t, "000000000000000000000000") enc, err := EncryptAesGCM(nil, key, nonce, nil) if err != nil { t.Fatalf("EncryptAesGCM failed: %v", err) } want := mustHex(t, "58e2fccefa7e3061367f1d57a4e7455a") if !bytes.Equal(enc, want) { t.Fatalf("AES-GCM empty vector mismatch: got %x want %x", enc, want) } } func TestAESGCMNISTVectorOneBlock(t *testing.T) { key := mustHex(t, "00000000000000000000000000000000") nonce := mustHex(t, "000000000000000000000000") plain := mustHex(t, "00000000000000000000000000000000") enc, err := EncryptAesGCM(plain, key, nonce, nil) if err != nil { t.Fatalf("EncryptAesGCM failed: %v", err) } want := mustHex(t, "0388dace60b6a392f328c2b971b2fe78ab6e47d42cec13bdf53a67b21257bddf") if !bytes.Equal(enc, want) { t.Fatalf("AES-GCM one-block vector mismatch: got %x want %x", enc, want) } } func TestSM4ECBStandardVector(t *testing.T) { key := mustHex(t, "0123456789abcdeffedcba9876543210") plain := mustHex(t, "0123456789abcdeffedcba9876543210") enc, err := EncryptSM4ECB(plain, key, ZEROPADDING) if err != nil { t.Fatalf("EncryptSM4ECB failed: %v", err) } want := mustHex(t, "681edf34d206965e86b3e94f536e4246") if !bytes.Equal(enc, want) { t.Fatalf("SM4 ECB vector mismatch: got %x want %x", enc, want) } } func TestChaCha20Poly1305RFCVector(t *testing.T) { key := mustHex(t, "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f") nonce := mustHex(t, "070000004041424344454647") enc, err := EncryptChaCha20Poly1305(nil, key, nonce, nil) if err != nil { t.Fatalf("EncryptChaCha20Poly1305 failed: %v", err) } want := mustHex(t, "a0784d7a4716f3feb4f64e7f4b39bf04") if !bytes.Equal(enc, want) { t.Fatalf("ChaCha20-Poly1305 vector mismatch: got %x want %x", enc, want) } } func TestAesOptionsDefaultToGCM(t *testing.T) { key := []byte("0123456789abcdef") nonce := []byte("123456789012") plain := []byte("aes-options-default-gcm") enc, err := EncryptAesWithOptions(plain, key, &CipherOptions{Nonce: nonce}) if err != nil { t.Fatalf("EncryptAesWithOptions failed: %v", err) } dec, err := DecryptAesWithOptions(enc, key, &CipherOptions{Nonce: nonce}) if err != nil { t.Fatalf("DecryptAesWithOptions failed: %v", err) } if !bytes.Equal(dec, plain) { t.Fatalf("aes options default gcm mismatch") } } func TestSM4OptionsDefaultToGCM(t *testing.T) { key := []byte("0123456789abcdef") nonce := []byte("123456789012") plain := []byte("sm4-options-default-gcm") enc, err := EncryptSM4WithOptions(plain, key, &CipherOptions{Nonce: nonce}) if err != nil { t.Fatalf("EncryptSM4WithOptions failed: %v", err) } dec, err := DecryptSM4WithOptions(enc, key, &CipherOptions{Nonce: nonce}) if err != nil { t.Fatalf("DecryptSM4WithOptions failed: %v", err) } if !bytes.Equal(dec, plain) { t.Fatalf("sm4 options default gcm mismatch") } } func TestLargeStreamRoundTrip(t *testing.T) { large := bytes.Repeat([]byte("starcrypto-large-stream-data-0123456789"), 180000) aesKey := []byte("0123456789abcdef") aesIV := []byte("abcdef9876543210") aesEnc := &bytes.Buffer{} if err := EncryptAesCBCStream(aesEnc, bytes.NewReader(large), aesKey, aesIV, ""); err != nil { t.Fatalf("EncryptAesCBCStream large failed: %v", err) } aesDec := &bytes.Buffer{} if err := DecryptAesCBCStream(aesDec, bytes.NewReader(aesEnc.Bytes()), aesKey, aesIV, ""); err != nil { t.Fatalf("DecryptAesCBCStream large failed: %v", err) } if !bytes.Equal(aesDec.Bytes(), large) { t.Fatalf("aes large stream mismatch") } chachaKey := []byte("0123456789abcdef0123456789abcdef") chachaNonce := []byte("123456789012") chachaEnc := &bytes.Buffer{} if err := EncryptChaCha20Stream(chachaEnc, bytes.NewReader(large), chachaKey, chachaNonce); err != nil { t.Fatalf("EncryptChaCha20Stream large failed: %v", err) } chachaDec := &bytes.Buffer{} if err := DecryptChaCha20Stream(chachaDec, bytes.NewReader(chachaEnc.Bytes()), chachaKey, chachaNonce); err != nil { t.Fatalf("DecryptChaCha20Stream large failed: %v", err) } if !bytes.Equal(chachaDec.Bytes(), large) { t.Fatalf("chacha20 large stream mismatch") } } func mustHex(t *testing.T, s string) []byte { t.Helper() b, err := hex.DecodeString(s) if err != nil { t.Fatalf("DecodeString failed: %v", err) } return b }