常用加解密

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

pythonAES加解密

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
}
posted @ 2022-04-25 12:21  Jeff的技术栈  阅读(301)  评论(0编辑  收藏  举报
回顶部