重要:
在Java中不带模式和填充来获取AES算法的时候,其默认使用AES/ECB/PKCS5Padding!!!
1 Java的AES加解密
如果把Cipher.getInstance("AES");中的"AES"换成"AES/ECB/PKCS5Padding",效果是一样的。
1.1 加密操作
/**
* 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 解密操作
/**
* 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 加密操作
//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 解密操作
//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
//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
//PKCS5UnPadding
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
// 去掉最后一个字节 unpadding 次
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
2.5 ECB
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模式
感谢网络上的大神!
有疑问加站长微信联系(非本文作者)