文章首发于:clawhub.club


重要:

在Java中不带模式和填充来获取AES算法的时候,其默认使用AES/ECB/PKCS5Padding!!!

1 Java的AES加解密

如果把Cipher.getInstance(“AES”);中的”AES”换成”AES/ECB/PKCS5Padding”,效果是一样的。

1.1 加密操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* Description: 加密操作 <br>
*
* @param data 待加密数据
* @param key 密钥
* @return 加解密后的信息
* @throws Exception <br>
*/
public static byte[] encrypt(byte[] data, byte[] key)
throws Exception {
Key secretKey = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return cipher.doFinal(data);
}

1.2 解密操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* Description: 解密操作 <br>
*
* @param data 待解密数据
* @param key 密钥
* @return 解密后的信息
* @throws Exception <br>
*/
public static byte[] decrypt(byte[] data, byte[] key)
throws Exception {
Key secretKey = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return cipher.doFinal(data);
}

2 Golang的AES加解密

Golang中是没有现成的ECB/PKCS5Padding填充算法的,需要自己写或找份。

2.1 加密操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//ECB PKCS5 加密
func AESEncrypt(src, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
log.Logger.Error("txn put fail: %v", err)
return nil
}
ecb := NewECBEncrypter(block)
content := []byte(src)
content = PKCS5Padding(content, block.BlockSize())
des := make([]byte, len(content))
ecb.CryptBlocks(des, content)
return des
}
2.2 解密操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//ECB PKCS5 解密
func AesDecrypt(crypted, key []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
log.Logger.Error("txn get fail: %v", err)
return nil
}
blockMode := NewECBDecrypter(block)
origData := make([]byte, len(crypted))
blockMode.CryptBlocks(origData, crypted)
origData = PKCS5UnPadding(origData)
return origData
}

2.3 PKCS5Padding
1
2
3
4
5
6
//PKCS5Padding
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
2.4 PKCS5UnPadding
1
2
3
4
5
6
7
8
//PKCS5UnPadding
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
// 去掉最后一个字节 unpadding 次
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}

2.5 ECB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package ecb

import "crypto/cipher"

type ecb struct {
b cipher.Block
blockSize int
}

func newECB(b cipher.Block) *ecb {
return &ecb{
b: b,
blockSize: b.BlockSize(),
}
}

type ecbEncrypter ecb

// NewECBEncrypter returns a BlockMode which encrypts in electronic code book
// mode, using the given Block.
func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
return (*ecbEncrypter)(newECB(b))
}
func (x *ecbEncrypter) BlockSize() int { return x.blockSize }
func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
if len(src)%x.blockSize != 0 {
panic("crypto/cipher: input not full blocks")
}
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
for len(src) > 0 {
x.b.Encrypt(dst, src[:x.blockSize])
src = src[x.blockSize:]
dst = dst[x.blockSize:]
}
}

type ecbDecrypter ecb

// NewECBDecrypter returns a BlockMode which decrypts in electronic code book
// mode, using the given Block.
func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
return (*ecbDecrypter)(newECB(b))
}
func (x *ecbDecrypter) BlockSize() int { return x.blockSize }
func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
if len(src)%x.blockSize != 0 {
panic("crypto/cipher: input not full blocks")
}
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
for len(src) > 0 {
x.b.Decrypt(dst, src[:x.blockSize])
src = src[x.blockSize:]
dst = dst[x.blockSize:]
}
}

参考资料

golang AES/ECB/PKCS5 加密解密 url-safe-base64
aes加密解密,含 128、192、256位,cbc、cfb、ecb、ofb、pcbc模式

感谢网络上的大神!