需要
加密存储用户数据,实现即便数据库泄露,也能保障用户数据的平安。
思路
- 应用
AES
解决一般数据。 -
应用
Argon2
解决非凡数据。以加密后是否须要解密为规范辨别:
加密后须要解密的,为一般数据(手机号、邮箱)。
反之,为非凡数据(登录明码)。
实现
AES解决一般数据
AES,Advanced Encryption Standard,高级加密规范。
// AES key,16、24或者32位,顺次对应AES-128、AES-192和AES-256。
const key = "1234567887654321"
// AES加密
func AESEncrypt(plainText []byte) ([]byte, error) {
block, err := aes.NewCipher([]byte(key)) // 应用AES key生成cipher.Block接口
if err != nil {
return nil, err
}
plainText = pkcs5Append(plainText, block.BlockSize()) // 填充最初一个分组的数据
blockMode := cipher.NewCBCEncrypter(block, ([]byte(key))[:block.BlockSize()]) // 生成BlockMode接口
cipherText := plainText
blockMode.CryptBlocks(cipherText, plainText) // 加密
return cipherText, nil
}
// AES解密
func AESDecrypt(cipherText []byte) ([]byte, error) {
block, err := aes.NewCipher([]byte(key)) // 应用AES key生成cipher.Block接口
if err != nil {
return nil, err
}
blockMode := cipher.NewCBCEncrypter(block, ([]byte(key))[:block.BlockSize()]) // 生成BlockMode接口
plainText := cipherText
blockMode.CryptBlocks(plainText, cipherText) // 解密
plainText = pkcs5Trim(plainText)
return plainText, nil
}
// 应用PKCS#5算法填充最初一个分组的数据
func pkcs5Append(ciphertext []byte, blockSize int) []byte {
padding := blockSize - (len(ciphertext) % blockSize) // 计算最初一个分组缺多少个字节
padText := bytes.Repeat([]byte{byte(padding)}, padding) // 创立一个大小为padding的切片, 每个字节的值为padding
newText := append(ciphertext, padText...) // 将padText增加到原始数据的后边, 将最初一个分组短少的字节数补齐
return newText
}
// 删除填充的数据
func pkcs5Trim(origData []byte) []byte {
length := len(origData) // 计算数据的总长度
number := int(origData[length-1]) // 依据填充的字节值得到填充的次数
return origData[:(length - number)] // 将尾部填充的number个字节去掉
}
Argon2解决非凡数据
Argon2,明码散列比赛冠军算法,是比bcrypt
、scrypt
更牢靠的明码散列算法。
go get -u golang.org/x/crypto/argon2
// 定义盐
salt := "some salt"
// 基于Argon2id生成明码的散列值
key := argon2.IDKey([]byte("some password"), salt, 1, 64*1024, 4, 32)
// 将key编码为base64字符串
data := base64.StdEncoding.EncodeToString(key)
Password Hashing Competition
phc-winner-argon2
golang/crypto
罕用明码技术 | 爱编程的大丙
发表回复