摘要
在项目开发过程中,当操作一些用户的隐私信息,诸如密码,帐户密钥等数据时,往往需要加密后可以在网上传输.这时,需要一些高效地,简单易用的加密算法加密数据,然后把加密后的数据存入数据库或进行其他操作;当需要读取数据时,把加密后的数据取出来,再通过算法解密.
1. 关于加密解密
当前我们项目中常用的加解密的方式无非三种.
- 对称加密, 加解密都使用的是同一个密钥, 其中的代表就是AES,DES
- 非对加解密, 加解密使用不同的密钥, 其中的代表就是RSA
- 签名算法, 如MD5,SHA1,HMAC等, 主要用于验证,防止信息被修改, 如:文件校验,数字签名,鉴权协议
1.1. Base64不是加密算法
它是一种数据编码方式,虽然是可逆的,但是它的编码方式是公开的,无所谓加密.本文也对Base64编码方式做了简要介绍.
2. AES
AES,即高级加密标准(Advanced Encryption Standard),是一个对称分组密码算法,旨在取代DES成为广泛使用的标准.AES中常见的有三种解决方案,分别为AES-128,AES-192和AES-256. AES加密过程涉及到4种操作:字节替代(SubBytes),行移位(ShiftRows),列混淆(MixColumns)和轮密钥加(AddRoundKey).解密过程分别为对应的逆操作.由于每一步操作都是可逆的,按照相反的顺序进行解密即可恢复明文.加解密中每轮的密钥分别由初始密钥扩展得到.算法中16字节的明文,密文和轮密钥都以一个4×4的矩阵表示. AES 有五种加密模式:电码本模式(Electronic Codebook Book (ECB)),密码分组链接模式(Cipher Block Chaining (CBC)),计算器模式(Counter (CTR)),密码反馈模式(Cipher FeedBack (CFB))和输出反馈模式(Output FeedBack (OFB))
import (
"bytes"
"crypto/aes"
"fmt" "crypto/cipher" "encoding/base64" ) func main() { orig := "hello world" key := "123456781234567812345678" fmt.Println("原文:", orig) encryptCode := AesEncrypt(orig, key) fmt.Println("密文:" , encryptCode) decryptCode := AesDecrypt(encryptCode, key) fmt.Println("解密结果:", decryptCode) } func AesEncrypt(orig string, key string) string { // 转成字节数组 origData := []byte(orig) k := []byte(key) // 分组秘钥 block, err := aes.NewCipher(k) if err != nil { panic(fmt.Sprintf("key 长度必须 16/24/32长度: %s", err.Error())) } // 获取秘钥块的长度 blockSize := block.BlockSize() // 补全码 origData = PKCS7Padding(origData, blockSize) // 加密模式 blockMode := cipher.NewCBCEncrypter(block, k[:blockSize]) // 创建数组 cryted := make([]byte, len(origData)) // 加密 blockMode.CryptBlocks(cryted, origData) //使用RawURLEncoding 不要使用StdEncoding //不要使用StdEncoding 放在url参数中回导致错误 return base64.RawURLEncoding.EncodeToString(cryted) } func AesDecrypt(cryted string, key string) string { //使用RawURLEncoding 不要使用StdEncoding //不要使用StdEncoding 放在url参数中回导致错误 crytedByte, _ := base64.RawURLEncoding.DecodeString(cryted) k := []byte(key) // 分组秘钥 block, err := aes.NewCipher(k) if err != nil { panic(fmt.Sprintf("key 长度必须 16/24/32长度: %s", err.Error())) } // 获取秘钥块的长度 blockSize := block.BlockSize() // 加密模式