常用加解密
目录
1.加密种类
1.对称加密算法 :常⽤的算法包括DES、3DES、AES、DESX、Blowfish、RC4、RC5、RC6。推荐⽤AES。
⼆、⾮对称加密算法:常见的⾮对称加密算法:RSA、DSA(数字签名⽤)、ECC(移动设备⽤)、Diffie-Hellman、El Gamal。推荐⽤ECC(椭圆曲线密码编码学)。
三、散列算法(Hash算法---单向加密算法):常见的Hash算法:MD2、MD4、MD5、HAVAL、SHA、SHA-1、HMAC、HMAC-
MD5、HMAC-SHA1。推荐MD5、SHA-1。
对称和非对称区别:
对称加密:加解密密码相同
非对称加密:加解密密码不相同
2.常用对称加密算法
2.1base64
base64特征:结尾可能有"=="号
go
import b64 "encoding/base64"
import "fmt"
func main() {
data := "123456"
//加密1
sEnc := b64.StdEncoding.EncodeToString([]byte(data))
fmt.Println(sEnc) //MTIzNDU2
//解密1
sDec, err := b64.StdEncoding.DecodeString(sEnc)
if err !=nil{
fmt.Println(err)
}
fmt.Println(string(sDec)) //123456
// 使用兼容URL的base64编码和解码
//加密2
uEnc := b64.URLEncoding.EncodeToString([]byte(data))
fmt.Println(uEnc) //MTIzNDU2
//解密2
uDec, _ := b64.URLEncoding.DecodeString(uEnc)
fmt.Println(string(uDec))//123456
}
python
编码
# 想将字符串转编码成base64,要先将字符串转换成二进制数据
url = "https://www.cnblogs.com/songzhixue/"
bytes_url = url.encode("utf-8")
str_url = base64.b64encode(bytes_url) # 被编码的参数必须是二进制数据
print(str_url)
b'aHR0cHM6Ly93d3cuY25ibG9ncy5jb20vc29uZ3poaXh1ZS8='
解码
# 将base64解码成字符串
import base64
url = "aHR0cHM6Ly93d3cuY25ibG9ncy5jb20vc29uZ3poaXh1ZS8="
str_url = base64.b64decode(url).decode("utf-8")
print(str_url)
2.2AES
特征:对称加密,加密解密用的是同样的密钥。对称加密是最快速、最简单的一种加密方式
对称加密:适合经常发送数据的场合
非对称加密:加密和解密用的密钥是不同的,通常加密解密的速度比较慢,适合偶尔发送数据的场合。优点是密钥传输方便。
2.2.1AES的三要素
密钥:128、192、256
填充:
NoPadding
PKCS7Padding
ZeroPadding
AnsiX923
lso10126
lso97971
工作模式:
CBC、ECB、CTR、CFB、OFB
2.2.2AES工作模式区别
工作模式:
CBC、ECB、CTR、CFB、OFB
ECB模式:
1、简单
2、有利于计算
3、相同的明文块经过加密会变成相同的密文块,因此安全性较差
CBC模式:
1、无法并行计算,性能上不如ECB
2、引入初始化向量IV,增加复杂度。
3、安全性高
2.2.3AES的加密流程
1、把明文按照128bit拆分成若干个明文块
2、按照选择的填充模式来填充最后一个明文块
3、每个明文块利用AES加密器和密钥,加密成密文块
2.2.4AES的特点、特征
1、有iv的是特征的是CBC工作模式
2、mode和padding标示的加密模式、填充方式
iv:初始向量
mode:工作模式
padding:填充方式
2.2.5python的AES
2.2.6go的AES
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
)
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
func PKCS7UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
//AES加密,CBC
func AesEncrypt(origData, key []byte) (string, error) {
block, err := aes.NewCipher(key)
if err != nil {
return "", err
}
blockSize := block.BlockSize()
origData = PKCS7Padding(origData, blockSize)
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) // CBC加密
//blockMode := cipher.NewCFBEncrypter(block,key[:blockSize]) //CFB加密
crypted := make([]byte, len(origData))
blockMode.CryptBlocks(crypted, origData) //CBC加密
//blockMode.XORKeyStream(crypted,origData) //CFB加密
crypteBase64:=base64.StdEncoding.EncodeToString(crypted) //返回base64编码
return crypteBase64, nil
}
//AES解密
func AesDecrypt(crypteBase64 string, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) //CBC加密
//blockMode := cipher.NewCFBDecrypter(block, key[:blockSize]) //CFB加密
origData := make([]byte, len(crypteBase64))
crypted,_:= base64.StdEncoding.DecodeString(crypteBase64)
blockMode.CryptBlocks(origData, crypted) //CBC加密
//blockMode.XORKeyStream(origData, crypted) //CFB加密
origData = PKCS7UnPadding(origData)
return origData, nil
}
func main() {
text := "123456" // 你要加密的数据
AesKey := []byte("0123456789123456") // 秘钥,对称秘钥长度必须是16的倍数
crypteBase64, err := AesEncrypt([]byte(text), AesKey)
if err != nil {
panic(err)
}
fmt.Println("加密后:",crypteBase64) // KaknGVd4nFWtpiXyZ540SA==
origin, err := AesDecrypt(crypteBase64, AesKey)
if err != nil {
panic(err)
}
fmt.Printf("解密后明文: %s\n", string(origin)) //123456
}
3.常用非对称加密算法
3.1RSA加解密
3.1.1生成公钥私钥密钥对
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"os"
)
//生成RSA私钥和公钥,保存到文件中
// bits 证书大小
func GenerateRSAKey(bits int) {
//GenerateKey函数使用随机数据生成器random生成一对具有指定字位数的RSA密钥
//Reader是一个全局、共享的密码用强随机数生成器
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
panic(err)
}
//保存私钥
//通过x509标准将得到的ras私钥序列化为ASN.1的DER编码字符串
X509PrivateKey := x509.MarshalPKCS1PrivateKey(privateKey)
//使用pem格式对x509输出的内容进行编码
//创建文件保存私钥
privateFile, err := os.Create("./go_test/private.pem")
if err != nil {
panic(err)
}
defer privateFile.Close()
//构建一个pem.Block结构体对象
privateBlock := pem.Block{Type: "RSA Private Key", Bytes: X509PrivateKey}
//将数据保存到文件
pem.Encode(privateFile, &privateBlock)
//保存公钥
//获取公钥的数据
publicKey := privateKey.PublicKey
//X509对公钥编码
X509PublicKey, err := x509.MarshalPKIXPublicKey(&publicKey)
if err != nil {
panic(err)
}
//pem格式编码
//创建用于保存公钥的文件
publicFile, err := os.Create("./go_test/public.pem")
if err != nil {
panic(err)
}
defer publicFile.Close()
//创建一个pem.Block结构体对象
publicBlock := pem.Block{Type: "RSA Public Key", Bytes: X509PublicKey}
//保存到文件
pem.Encode(publicFile, &publicBlock)
}
func main() {
//生成密钥对,保存到文件
GenerateRSAKey(2048)
}
3.1.2RSA
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"os"
)
//RSA加密
// plainText 要加密的数据
// path 公钥匙文件地址
func RSA_Encrypt(plainText []byte, path string) string {
//打开文件
file, err := os.Open(path)
if err != nil {
panic(err)
}
defer file.Close()
//读取文件的内容
info, _ := file.Stat()
buf := make([]byte, info.Size())
file.Read(buf)
//pem解码
block, _ := pem.Decode(buf)
//x509解码
publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
panic(err)
}
//类型断言
publicKey := publicKeyInterface.(*rsa.PublicKey)
//对明文进行加密
cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plainText)
if err != nil {
panic(err)
}
//返回base编码密文,否则看不懂
crypteBase64:=base64.StdEncoding.EncodeToString(cipherText) //返回base64编码
return crypteBase64
}
//RSA解密
// cipherText 需要解密的byte数据
// path 私钥文件路径
func RSA_Decrypt(encryptBase64 string,path string) []byte{
//打开文件
file,err:=os.Open(path)
if err!=nil{
panic(err)
}
defer file.Close()
//获取文件内容
info, _ := file.Stat()
buf:=make([]byte,info.Size())
file.Read(buf)
//pem解码
block, _ := pem.Decode(buf)
//X509解码
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err!=nil{
panic(err)
}
//base64解码
cipherText,_:=base64.StdEncoding.DecodeString(encryptBase64)
//对密文进行解密
plainText,_:=rsa.DecryptPKCS1v15(rand.Reader,privateKey,cipherText)
//返回明文
return plainText
}
func main() {
//加密
data := []byte("123456") // 原数据
encryptBase64 := RSA_Encrypt(data, "./go_test/public.pem")
fmt.Println(encryptBase64)
//gHudPWYOAPsq7C3RVG/ilykMgKbvqsxQLFhaT9TbdjsM0FDy1odF3AuJkoakLaWMdueigC8UCdQEJhFADh0skPwAonuecqpk3UqljBeDPPgCSPhy2S5nrQMqZuK+EB+fdGnu8ieMmkIQACFQShhnFlqfXbvY5pGi+rjdXTaaXFtxRygtaA+OGHBh7rNWprEainoOC4WeLiHg/v1T6Pk6NiAR3eYjq0L4vadRvkV8MhyjUVifBziW5EXJk00omraoQjAu+1P+PV/wVlFj8BA/4p3ZfMrhzAkTpI/Bewsz5KHJ2xeQg4wEWMrbK8MyHTcH0GRLG+Pk0D/tGawpgW52TA==
// 解密
decrypt := RSA_Decrypt(encryptBase64, "./go_test/private.pem")
fmt.Println(string(decrypt)) //123456
}
3.2ECC加解密
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"fmt"
//以太坊加密库,要求go版本升级到1.15
"github.com/ethereum/go-ethereum/crypto/ecies"
)
func genPrivateKey() (*ecies.PrivateKey, error) {
pubkeyCurve := elliptic.P256() //初始化椭圆曲线
//随机挑选基点,生成私钥
p, err := ecdsa.GenerateKey(pubkeyCurve, rand.Reader) //用golang标准库生成公私钥
if err != nil {
return nil, err
} else {
return ecies.ImportECDSA(p), nil //转换成以太坊的公私钥对
}
}
//ECCEncrypt 椭圆曲线加密
func ECCEncrypt(plain string, pubKey *ecies.PublicKey) ([]byte, error) {
src := []byte(plain)
return ecies.Encrypt(rand.Reader, pubKey, src, nil, nil)
}
//ECCDecrypt 椭圆曲线解密
func ECCDecrypt(cipher []byte, prvKey *ecies.PrivateKey) (string, error) {
if src, err := prvKey.Decrypt(cipher, nil, nil); err != nil {
return "", err
} else {
return string(src), nil
}
}
func main() {
prvKey, err := genPrivateKey()
if err != nil {
fmt.Println(err)
}
pubKey := prvKey.PublicKey
plain := "123456"
fmt.Println("原数据:",plain)
cipher, err := ECCEncrypt(plain, &pubKey)
if err != nil {
fmt.Println(err)
}
fmt.Println("密文:",string(cipher))
plain, err = ECCDecrypt(cipher, prvKey)
if err != nil {
fmt.Println(err)
}
fmt.Printf("明文:%s\n", plain)
}
4.散列算法
4.1Md5
package main
import (
"crypto/md5"
"encoding/hex"
"fmt"
)
var md5Pool = sync.Pool{
New: func() interface{} {
return md5.New()
},
}
func MD5(str string) string {
h := md5.New()
//使用对象池
//h := md5Pool.Get().(hash.Hash)
str = str + "加盐"
h.Write([]byte(str)) // 需要加密的字符串为 123456
cipherStr := h.Sum(nil)
return hex.EncodeToString(cipherStr) // 输出加密结
}
func main() {
//1.md5.New()
data := "123456" //原数据
md5Data:=MD5(data)
fmt.Println(md5Data)
//2.md5.sum
//区别:md5.New() 创建一个可以重复使用的 MD5 哈希对象,可以通过调用 Write() 方法来增量计算 MD5 值,最后调用 Sum() 方法获得最终结果。
// md5.Sum(data) 一次性计算给定数据 data 的 MD5 值,不需要手动维护中间状态。
md5Str := fmt.Sprintf("%x", md5.Sum(data))
fmt.Println(md5Str)
}
4.2SHA1
package main
import (
"crypto/sha1"
"encoding/hex"
"fmt"
)
func SHA1(s string) string {
o := sha1.New()
k := s + "盐"
o.Write([]byte(k))
return hex.EncodeToString(o.Sum(nil))
}
func main() {
data := "123456" //原数据
hexData := SHA1(data)
fmt.Println(hexData) //c2adab52abc737ffdb59c31c57b83f88df28e76c
}
5其他
5.1base64
//编码
func Base64Encode(s string) string {
encodedMessage := base64.StdEncoding.EncodeToString([]byte(s))
return encodedMessage
}
//解码
func Base64Decode(s string) (string, error) {
decodedMessage, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return "", err
}
return string(decodedMessage), nil
}
5.2pageToken
type PageToken struct {
Page int `json:"page"`
PageSize int `json:"pageSize"`
Timestamp int64
}
func PageTokenEncode(page, pageSize int) string {
p := PageToken{
Page: page,
PageSize: pageSize,
Timestamp: time.Now().Unix(),
}
jsonStr, _ := json.Marshal(p)
s := Base64Encode(string(jsonStr))
return s
}
func PageTokenDecode(pageToken string) (int, int, int) {
if pageToken == "" {
return 0, 0, 20
}
s, err := Base64Decode(pageToken)
if err != nil {
return 0, 0, 20
}
var p PageToken
_ = json.Unmarshal([]byte(s), &p)
offset := (p.Page - 1) * p.PageSize
return offset, p.Page, p.PageSize
}
选择了IT,必定终身学习