写在前面
这是我封装的一个加密库,secret包,上层抽离接口,让我们的更容易对敏感数据进行脱敏处理
。
github地址:https://github.com/CocaineCong/secret
这里就不再过多赘述 AES/DES/3DES/RSA 等的加密算法
。
这一次重点介绍一下新增的一些新特性,主要是在 AES 加密这一块。
AES
1. 密钥长度
我们新增了对密钥程度的加密的选择。可以选择 128、192、256 三种长度的密钥进行加密,更加灵活方便。
type AesKeyType uint64
const (
AesEncrypt128 AesKeyType = 128
AesEncrypt192 AesKeyType = 192
AesEncrypt256 AesKeyType = 256
)
2. 加密模式
之前版本仅支持 CBC模式 的加密,这次我们扩展了 CFB / CTR / OFB
三种模式。
让我们加密模式的选择更多样化。
// AES 加密模式
const (
AesModeTypeCBC AesModeType = "CBC" // Cipher Block Chaining
AesModeTypeCFB AesModeType = "CFB" // Cipher FeedBack
AesModeTypeCTR AesModeType = "CTR" // Counter
AesModeTypeOFB AesModeType = "OFB" // Output FeedBack
)
同样的,为了兼容更多的模式,我们扩展了AES对象。
type AesEncrypt struct {
SpecialSign string // 加解密都会基于这一串字符,如果没有会基于 AesBaseSpecialSign.
Key string // 密钥,建议是 5-8位的密钥
IV string // 初始向量 16 字节
AesModeType AesModeType // 加密类型
AesKeyType AesKeyType // 加密类型
AesKey []byte // AES 密钥
AesKeyLength int // 加密长度
PlainTextLength int // 加密对象的长度
}
虽然字段增加多了,但是很多都是封装实现的,不需要用户将全部的参数都输入来进行构建
用户只需要选择传入必要的参数即可,非常方便简洁,甚至不需要输入iv
举个例子:
specialSign := "a1231243124124314vczxfda124sd"
key := "458796" // key 密钥
aesEncrypt, _ := NewAesEncrypt(specialSign, key, "", AesEncrypt128, AesModeTypeCTR)
我们只是在原先的基础上,增加了iv初始向量以及选择加密的长度。
并且与之前一样的加解密操作。
str := aesEncrypt.SecretEncrypt("this is a secret")
fmt.Println(str)
ans := aesEncrypt.SecretDecrypt(str)
fmt.Println(ans)
以上的新加的功能都是基于AES的,目前DES是不太考虑加了,可能后续会新增3DES的加密mode。
这里提一下关于两个新加入的加密 mode CTR AND OFB
- 加密
这里我们的CTR和OFB加密和解密都是可以
直接一个New就完事
了,非常的简洁和方便,与 CBC/CFB 不同,CBC/CFB 则需要区分 Encrypt 和 Decrypt。
// aesEncrypter CTR OR OFB 模式的加密
func (a *AesEncrypt) aesEncrypter(encodeStr string, block cipher.Block, mode AesModeType) (string, error) {
cipherText := make([]byte, a.PlainTextLength)
m := cipher.NewCTR(block, []byte(a.IV))
if mode == AesModeTypeCFB {
m = cipher.NewOFB(block, []byte(a.IV))
}
copy(cipherText, encodeStr)
m.XORKeyStream(cipherText, cipherText)
return hex.EncodeToString(cipherText), nil
}
// aesDecrypter CTR OR OFB 模式的加密
func (a *AesEncrypt) aesDecrypter(decodeBytes []byte, block cipher.Block, mode AesModeType) (string, error) {
m := cipher.NewCTR(block, []byte(a.IV))
if mode == AesModeTypeCFB {
m = cipher.NewOFB(block, []byte(a.IV))
}
plainTextCopy := make([]byte, a.PlainTextLength)
copy(plainTextCopy, decodeBytes)
m.XORKeyStream(plainTextCopy, plainTextCopy)
return string(plainTextCopy), nil
}
3. 拼接选择
这一次我们抽离对 specialSign
的填充操作。目前还是裁剪,后面打算换成hash,并且将string 由 编码的形式呈现
如果这个 specialSign 加上 key
- 不足对应的加密密钥的长度,那么我们会用 BaseSpecialSign 对specialSign 进行 填充。
- 如果大于对应的加密密钥的长度,我们会根据奇偶来判断,是取前缀还是后缀。
func formatSpecialSign(specialSign, key string, keyLength int) string {
specialSignLength := len(specialSign)
if specialSignLength+len(key) < keyLength {
log.Printf("【WARN】 the length of specialSign and key less %v ", keyLength)
if specialSignLength%2 == 0 {
specialSign += BaseSpecialSign[:keyLength-len(specialSign)]
} else {
specialSign += BaseSpecialSign[BaseSpecialSignLength-keyLength:]
}
}
if specialSignLength > keyLength {
if specialSignLength%2 == 0 {
specialSign = specialSign[:keyLength+1]
} else {
specialSign = specialSign[len(specialSign)-keyLength:]
}
}
return specialSign
}
多位密钥支持 & 多种模式选择
以上就是这次的新改型。
下一个版本会解决的问题: