使用golang实现AES算法很简单,系统库中已自带了CBC、CFB等等许多加密模式,而且可以很方便的设置IVPara,但是前几日在做AES加密时,发现传入的key必须是128bit、192bit或256bit,记得当时用Java实现的时候并没有这个问题。AES中的key的确是必须满足以上要求才行。这里就涉及到PKCS5Padding的
/**
* AES 加密
*
* @param data 明文
* @param password 生成秘钥的关键字
* @return
*/
public static byte[] encrypt(byte[] data, String password) {
try {
IvParameterSpec zeroIv = new IvParameterSpec(VIPARA.getBytes());
SecretKeySpec key = new SecretKeySpec(password.getBytes(CharsetMap.charset_utf8), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);
byte[] encryptedData = cipher.doFinal(data);
return encryptedData;
// return byte2HexStr(encryptedData);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
return null;
}
可见Ciper初始化的时候,加入了PKCS5Padding特性,所以会对输入的key进行一次包装,避免了开发者的手动处理。
所以在golang中,需要自行实现该功能:
//加密数据
func (a *AesCryptor) Encrypt(data []byte) ([]byte, error) {
aesBlockEncrypter, err := aes.NewCipher(a.key)
content := PKCS5Padding(data, aesBlockEncrypter.BlockSize())
encrypted := make([]byte, len(content))
if err != nil {
println(err.Error())
return nil, err
}
aesEncrypter := cipher.NewCBCEncrypter(aesBlockEncrypter, a.iv)
aesEncrypter.CryptBlocks(encrypted, content)
return encrypted, nil
}
//解密数据
func (a *AesCryptor) Decrypt(src []byte) (data []byte, err error) {
decrypted := make([]byte, len(src))
var aesBlockDecrypter cipher.Block
aesBlockDecrypter, err = aes.NewCipher(a.key)
if err != nil {
println(err.Error())
return nil, err
}
aesDecrypter := cipher.NewCBCDecrypter(aesBlockDecrypter, a.iv)
aesDecrypter.CryptBlocks(decrypted, src)
return PKCS5Trimming(decrypted), nil
}
/**
PKCS5包装
*/
func PKCS5Padding(cipherText []byte, blockSize int) []byte {
padding := blockSize - len(cipherText)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(cipherText, padText...)
}
/*
解包装
*/
func PKCS5Trimming(encrypt []byte) []byte {
padding := encrypt[len(encrypt)-1]
return encrypt[:len(encrypt)-int(padding)]
}
注:以上代码部分来源于互联网。