Skip to content

Commit 8b4825f

Browse files
committed
feat: crypto/aesutil/aesecb: add DecryptBase64(), EncryptBase64()
1 parent 700499f commit 8b4825f

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed

crypto/aesutil/aesecb/aesecb.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package aesecb
2+
3+
import (
4+
"bytes"
5+
"crypto/aes"
6+
"crypto/cipher"
7+
"encoding/base64"
8+
"errors"
9+
)
10+
11+
func DecryptBase64(v, key string) (string, error) {
12+
if decoded, err := base64.StdEncoding.DecodeString(v); err != nil {
13+
return "", err
14+
} else if block, err := aes.NewCipher([]byte(key)); err != nil {
15+
return "", err
16+
} else if len(decoded)%aes.BlockSize != 0 {
17+
return "", errors.New("ciphertext is not a multiple of the block size")
18+
} else {
19+
decrypted := make([]byte, len(decoded))
20+
decryptECB(block, decrypted, decoded)
21+
22+
decrypted, err = removePKCS7Padding(decrypted, aes.BlockSize)
23+
if err != nil {
24+
return "", err
25+
} else {
26+
return string(decrypted), nil
27+
}
28+
}
29+
}
30+
31+
// decryptECB performs the ECB mode decryption
32+
func decryptECB(block cipher.Block, dst, src []byte) {
33+
bs := block.BlockSize()
34+
for len(src) > 0 {
35+
block.Decrypt(dst, src[:bs])
36+
src = src[bs:]
37+
dst = dst[bs:]
38+
}
39+
}
40+
41+
// removePKCS7Padding removes padding from the decrypted data.
42+
func removePKCS7Padding(data []byte, blockSize int) ([]byte, error) {
43+
if len(data) == 0 || len(data)%blockSize != 0 {
44+
return nil, errors.New("invalid padding size")
45+
}
46+
47+
paddingLen := int(data[len(data)-1])
48+
if paddingLen == 0 || paddingLen > blockSize {
49+
return nil, errors.New("invalid padding")
50+
}
51+
52+
for _, padByte := range data[len(data)-paddingLen:] {
53+
if int(padByte) != paddingLen {
54+
return nil, errors.New("invalid padding")
55+
}
56+
}
57+
58+
return data[:len(data)-paddingLen], nil
59+
}
60+
61+
func EncryptBase64(v, key string) (string, error) {
62+
paddedInput := addPKCS5Padding([]byte(v), aes.BlockSize)
63+
64+
if block, err := aes.NewCipher([]byte(key)); err != nil {
65+
return "", err
66+
} else {
67+
encrypted := make([]byte, len(paddedInput))
68+
encryptECB(block, encrypted, paddedInput)
69+
return base64.StdEncoding.EncodeToString(encrypted), nil
70+
}
71+
}
72+
73+
// encryptECB performs the ECB mode encryption.
74+
func encryptECB(block cipher.Block, dst, src []byte) {
75+
bs := block.BlockSize()
76+
for len(src) > 0 {
77+
block.Encrypt(dst, src[:bs])
78+
src = src[bs:]
79+
dst = dst[bs:]
80+
}
81+
}
82+
83+
func addPKCS5Padding(data []byte, blockSize int) []byte {
84+
padding := blockSize - len(data)%blockSize
85+
padText := bytes.Repeat([]byte{byte(padding)}, padding)
86+
return append(data, padText...)
87+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package aesecb
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
var aesecbTests = []struct {
9+
plaintext string
10+
key string
11+
}{
12+
{"My Secret Password", "0123456789abcdef"},
13+
{"My Secret Password", "1234567890123456"},
14+
}
15+
16+
func TestEncryptDecrypt(t *testing.T) {
17+
for _, tt := range aesecbTests {
18+
enc, err := EncryptBase64(tt.plaintext, tt.key)
19+
if err != nil {
20+
t.Errorf("aesecb.EncryptBase64 error(%s)", err.Error())
21+
}
22+
dec, err := DecryptBase64(enc, tt.key)
23+
if err != nil {
24+
t.Errorf("aesecb.DecryptBase64 error(%s)", err.Error())
25+
}
26+
if dec != tt.plaintext {
27+
fmt.Printf("[%v]\n", []byte(dec))
28+
fmt.Printf("[%v]\n", []byte(tt.plaintext))
29+
t.Errorf("encrypt/decrypt AES ECB error: want decrypted (%s), got (%s)", tt.plaintext, dec)
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)