密码学介绍,不完整

对称加密

DES

明文64bit
密钥56bit+8bit
XOR是三轮加密
在这里插入图片描述

ECB电子密码本

简单分组,不安全,需要填充
在这里插入图片描述

package main

import (
	"bytes"
	"crypto/des"
	"encoding/hex"
	"fmt"
)

func main() {
	src := []byte("微信公众号【福大大架构师每日一题】")
	fmt.Println("明文:", string(src))
	key := []byte("moonfdd1") //64bit
	ret := EncryptDES(src, key)
	fmt.Println("密文:", hex.EncodeToString(ret))
	ret = DecryptDes(ret, key)
	fmt.Println("明文:", string(ret))
}

// 加密
func EncryptDES(src, key []byte) []byte {
	block, err := des.NewCipher(key)
	if err != nil {
		panic(err)
	}
	length := block.BlockSize()
	src = PaddingText(src, length)
	dst := make([]byte, len(src))
	out := dst
	for len(src) > 0 {
		block.Encrypt(out, src[:length])
		src = src[length:]
		out = out[length:]
	}
	return dst
}

// 解密
func DecryptDes(src, key []byte) []byte {
	block, err := des.NewCipher(key)
	if err != nil {
		panic(err)
	}
	length := block.BlockSize()
	dst := make([]byte, len(src))
	out := dst
	for len(src) > 0 {
		block.Decrypt(out, src[:length])
		src = src[length:]
		out = out[length:]
	}
	dst = UnPaddingText(dst)
	return dst
}

// 填充数据
func PaddingText(src []byte, blockSize int) []byte {
	padding := blockSize - len(src)%blockSize
	padText := bytes.Repeat([]byte{byte(padding)}, padding)
	nextText := append(src, padText...)
	return nextText
}

// 删除尾部填充数据
func UnPaddingText(src []byte) []byte {
	len := len(src)
	number := int(src[len-1])
	newText := src[:len-number]
	return newText
}

在这里插入图片描述

CBC密码分组链接

需要填充
在这里插入图片描述
在这里插入图片描述
初始化向量:当加密第一个明文分组时,由于不存在前一个密文分组,因此需要事先准备一个长度为一个分组的比特序列来代替前一个密文分组,这个比特序列就称之为初始化向量,通常缩写称IV。
分析:
1.假设CBC模式加密的密文分组中有一个分组损坏了(由于硬盘故障导致密文分组的值发生了变化),只要密文分组的长度没有发生变化,则解密是最多只会有2个分组受到数据损坏的影响。
2.假设CBC模式的密文分组中长度发生了变化,会导致每一个分组会向后一个分组借位,这样就导致了后面的分组全部发生变化,最终导致后面的数据全部解密失败。

package main

import (
	"bytes"
	"crypto/cipher"
	"crypto/des"
	"encoding/hex"
	"fmt"
)

func main() {
	src := []byte("微信公众号【福大大架构师每日一题】")
	fmt.Println("明文:", string(src))
	key := []byte("moonfdd1") //64bit
	ret := EncryptDES(src, key)
	fmt.Println("密文:", hex.EncodeToString(ret))
	ret = DecryptDes(ret, key)
	fmt.Println("明文:", string(ret))
}

// 加密
func EncryptDES(src, key []byte) []byte {
	block, err := des.NewCipher(key)
	if err != nil {
		panic(err)
	}
	length := block.BlockSize()
	src = PaddingText(src, length)
	iv := []byte("12345678")
	blockMode := cipher.NewCBCEncrypter(block, iv)
	dst := make([]byte, len(src))
	blockMode.CryptBlocks(dst, src)
	return dst
}

// 解密
func DecryptDes(src, key []byte) []byte {
	block, err := des.NewCipher(key)
	if err != nil {
		panic(err)
	}
	iv := []byte("12345678")
	blockMode := cipher.NewCBCDecrypter(block, iv)
	dst := make([]byte, len(src))
	blockMode.CryptBlocks(dst, src)
	dst = UnPaddingText(dst)
	return dst
}

// 填充数据
func PaddingText(src []byte, blockSize int) []byte {
	padding := blockSize - len(src)%blockSize
	padText := bytes.Repeat([]byte{byte(padding)}, padding)
	nextText := append(src, padText...)
	return nextText
}

// 删除尾部填充数据
func UnPaddingText(src []byte) []byte {
	len := len(src)
	number := int(src[len-1])
	newText := src[:len-number]
	return newText
}

在这里插入图片描述

CFB密码反馈模式

需要填充
在这里插入图片描述
在这里插入图片描述

OFB输出反馈模式

不需要填充
在这里插入图片描述
在这里插入图片描述

CTR计数器

不需要填充

3DES

package main

import (
	"bytes"
	"crypto/cipher"
	"crypto/des"
	"encoding/hex"
	"fmt"
)

func main() {
	key := []byte("moonfdd1moonfdd1moonfdd1") //24个字符
	data := []byte("微信公众号【福大大架构师每日一题】")
	fmt.Println("原文:", string(data))
	encrypt_msg := Encrypt3DES(data, key)
	fmt.Println("encrypt_msg = ", hex.EncodeToString(encrypt_msg))
	decrypt_msg := Decrypt3DES(encrypt_msg, key)
	fmt.Println("decrypt_msg = ", string(decrypt_msg))
}

//使用3des加密
func Encrypt3DES(src, key []byte) []byte {
	block, err := des.NewTripleDESCipher(key)
	if err != nil {
		panic(err)
	}
	src = PaddingText(src, block.BlockSize())
	iv := []byte("12345678")
	blockMode := cipher.NewCBCEncrypter(block, iv)
	dst := make([]byte, len(src))
	blockMode.CryptBlocks(dst, src)
	return dst
}

//解密
func Decrypt3DES(src, key []byte) []byte {
	block, err := des.NewTripleDESCipher(key)
	if err != nil {
		panic(err)
	}
	iv := []byte("12345678")
	blockMode := cipher.NewCBCDecrypter(block, iv)
	dst := make([]byte, len(src))
	blockMode.CryptBlocks(dst, src)
	dst = UnPaddingText(dst)
	return dst
}

// 填充数据
func PaddingText(src []byte, blockSize int) []byte {
	padding := blockSize - len(src)%blockSize
	padText := bytes.Repeat([]byte{byte(padding)}, padding)
	nextText := append(src, padText...)
	return nextText
}

// 删除尾部填充数据
func UnPaddingText(src []byte) []byte {
	len := len(src)
	number := int(src[len-1])
	newText := src[:len-number]
	return newText
}

在这里插入图片描述

AES

明文分组的长度为128位即16字节
密钥长度可以为16、24、32字节(128、192、256位)

package main

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/hex"
	"fmt"
)

func main() {
	key := []byte("moonfdd1moonfdd1moonfdd1") //24个字符 16,24,32
	data := []byte("微信公众号【福大大架构师每日一题】")
	fmt.Println("原文:", string(data))
	encrypt_msg := EncryptAes(data, key)
	fmt.Println("encrypt_msg = ", hex.EncodeToString(encrypt_msg))
	decrypt_msg := DecryptAes(encrypt_msg, key)
	fmt.Println("decrypt_msg = ", string(decrypt_msg))
}

//aes加密
func EncryptAes(src, key []byte) []byte {
	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}
	src = PaddingText(src, block.BlockSize())
	blockMode := cipher.NewCBCEncrypter(block, key[:block.BlockSize()])
	dst := make([]byte, len(src))
	blockMode.CryptBlocks(dst, src)
	return dst
}

//aes解密
func DecryptAes(src, key []byte) []byte {
	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	blockMode := cipher.NewCBCDecrypter(block, key[:block.BlockSize()])
	dst := make([]byte, len(src))
	blockMode.CryptBlocks(dst, src)
	dst = UnPaddingText(dst)
	return dst
}

// 填充数据
func PaddingText(src []byte, blockSize int) []byte {
	padding := blockSize - len(src)%blockSize
	padText := bytes.Repeat([]byte{byte(padding)}, padding)
	nextText := append(src, padText...)
	return nextText
}

// 删除尾部填充数据
func UnPaddingText(src []byte) []byte {
	len := len(src)
	number := int(src[len-1])
	newText := src[:len-number]
	return newText
}

在这里插入图片描述

SM4

分组对称加密算法,秘钥长度和分组长度均为128位。

package main

import (
	"bytes"
	"crypto/cipher"
	"encoding/hex"
	"fmt"

	"github.com/tjfoc/gmsm/sm4"
)

//sm4加密
//src:明文
//key:秘钥
func EncryptSm4(src, key []byte) []byte {
	block, err := sm4.NewCipher(key)
	if err != nil {
		panic(err)
	}

	src = PaddingText(src, block.BlockSize())
	blockMode := cipher.NewCBCEncrypter(block, key[:block.BlockSize()])
	dst := make([]byte, len(src))
	blockMode.CryptBlocks(dst, src)
	return dst
}

//sm4解密
//src:密文
//key:秘钥
func DecryptSm4(src, key []byte) []byte {
	block, err := sm4.NewCipher(key)
	if err != nil {
		panic(err)
	}
	blockMode := cipher.NewCBCDecrypter(block, key[:block.BlockSize()])
	dst := make([]byte, len(src))
	blockMode.CryptBlocks(dst, src)
	newText := UnPaddingText(dst)
	return newText
}

// 填充数据
func PaddingText(src []byte, blockSize int) []byte {
	padding := blockSize - len(src)%blockSize
	padText := bytes.Repeat([]byte{byte(padding)}, padding)
	nextText := append(src, padText...)
	return nextText
}

// 删除尾部填充数据
func UnPaddingText(src []byte) []byte {
	len := len(src)
	number := int(src[len-1])
	newText := src[:len-number]
	return newText
}

func main() {
	key := []byte("12345678abcdefgh")
	msg := []byte("微信公众号【福大大架构师每日一题】")
	encrypt_msg := EncryptSm4(msg, key)
	fmt.Println("encrypt_msg = ", hex.EncodeToString(encrypt_msg))
	decrypt_msg := DecryptSm4(encrypt_msg, key)
	fmt.Println("decrypt_msg = ", string(decrypt_msg))
}

在这里插入图片描述

非对称加密

公钥加密,私钥解密

数字签名可以识别篡改和伪装和防止否认,在数字签名中有两种行为:
a. 生成消息签名
b. 验证消息签名
在这里插入图片描述

公钥通信流程:
在这里插入图片描述
公钥密码:
在这里插入图片描述
数字签名如下:
在这里插入图片描述

RSA

package main

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/hex"
	"encoding/pem"
	"fmt"
	"os"
)

func RsaGenKey(bits int) error {
	//GenerateKey函数使用随机数生成器生成一对指定长度的公钥和私钥
	//rand.Reader是一个全局,共享的密码随机生成器
	privKey, err := rsa.GenerateKey(rand.Reader, bits)
	if err != nil {
		panic(err)
	}
	//x509是通用的整数格式:序列号  签名算法  颁发者 有效时间  持有者  公钥
	//PKCS:RSA实验室与其他安全系统开发商为促进公钥密码的发展而指定的一系列标准
	priStream := x509.MarshalPKCS1PrivateKey(privKey)
	//将私钥字符串设置pem格式的块中
	/*
		pem是一种整数或私钥的格式:
		---------------BEGIN  RSA Private Key---------------


		--------------END RSA Private Key-------------------
	*/
	block := pem.Block{
		Type:  "RSA Private Key",
		Bytes: priStream,
	}
	privFile, err := os.Create("private.pem")
	if err != nil {
		panic(err)
	}
	defer privFile.Close()
	//将块编码到文件
	err = pem.Encode(privFile, &block)
	if err != nil {
		panic(err)
	}
	//从私钥中获取公钥
	pubKey := privKey.PublicKey
	//将公钥序列化
	pubStream := x509.MarshalPKCS1PublicKey(&pubKey)
	//将公钥设置到pem块中
	block = pem.Block{
		Type:  "RSA Public Key",
		Bytes: pubStream,
	}
	pubFile, err := os.Create("publiv.pem")
	defer pubFile.Close()
	if err != nil {
		panic(err)
	}
	err = pem.Encode(pubFile, &block)
	if err != nil {
		panic(err)
	}
	return nil
}

//公钥加密
func RsaPublicEncrypt(src, pathName []byte) ([]byte, error) {
	file, err := os.Open(string(pathName))
	msg := []byte("")
	if err != nil {
		return msg, err
	}
	defer file.Close()
	info, err := file.Stat()
	if err != nil {
		return msg, err
	}
	//创建切片,用于存储公钥
	recvBuf := make([]byte, info.Size())
	//读取公钥
	file.Read(recvBuf)
	//将得到的公钥反序列化
	//参数一:存储公钥的切片, 参数二:剩余未解密的数据
	block, _ := pem.Decode(recvBuf)
	//使用x509将编码之后的公钥解析出来
	pubKey, err := x509.ParsePKCS1PublicKey(block.Bytes)
	if err != nil {
		return msg, err
	}
	msg, err = rsa.EncryptPKCS1v15(rand.Reader, pubKey, src)
	if err != nil {
		return msg, err
	}
	return msg, nil
}

//使用私钥解密
func RsaPrivateDecrypt(src []byte, pathName string) ([]byte, error) {
	msg := []byte("")
	file, err := os.Open(pathName)
	if err != nil {
		return msg, err
	}
	info, err := file.Stat()
	if err != nil {
		return msg, err
	}
	//创建切片,用于存储公钥
	recvBuf := make([]byte, info.Size())
	//读取公钥
	file.Read(recvBuf)
	block, _ := pem.Decode(recvBuf)
	privKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		return msg, err
	}
	msg, err = rsa.DecryptPKCS1v15(rand.Reader, privKey, src)
	if err != nil {
		panic(err)
	}
	return msg, nil
}

func main() {
	err := RsaGenKey(1024)
	if err != nil {
		fmt.Println("秘钥对生成失败!")
	} else {
		fmt.Println("秘钥对生成成功!")
	}

	src := []byte("微信公众号【福大大架构师每日一题】")
	encrypt_msg, _ := RsaPublicEncrypt(src, []byte("publiv.pem"))
	fmt.Println("encrypt_msg = ", hex.EncodeToString(encrypt_msg))
	decrypt_msg, _ := RsaPrivateDecrypt(encrypt_msg, "private.pem")
	fmt.Println("decrypt_msg = ", string(decrypt_msg))
}

在这里插入图片描述

dsa

直接对消息进行签名(DSA)
在这里插入图片描述

package main

import (
	"crypto/dsa"
	"crypto/rand"
	"fmt"
)

/*
验证签名的作用:
1.保证数据的完整性
2.确保数据的来源
*/
func main() {
	//Parameters代表秘钥的域参数
	var param dsa.Parameters
	//GenerateParameters函数随机的设置合法的参数到params,
	//根据第三个参数就决定L和N的长度,长度越长,加密强度越高
	dsa.GenerateParameters(&param, rand.Reader, dsa.L1024N160)

	//生成私钥
	var priv dsa.PrivateKey
	priv.Parameters = param
	dsa.GenerateKey(&priv, rand.Reader)

	//利用私钥签名数据
	message := []byte("微信公众号【福大大架构师每日一题】")
	r, s, _ := dsa.Sign(rand.Reader, &priv, message)

	//通过私钥获取公钥
	pub := priv.PublicKey
	message1 := []byte("微信公众号【福大大架构师每日一题】")
	//使用公钥验证签名
	if dsa.Verify(&pub, message1, r, s) {
		fmt.Println("验证通过!")
	} else {
		fmt.Println("验证失败!")
	}
}

在这里插入图片描述
对消息的散列值进行签名
在这里插入图片描述

package main

import (
	"crypto"
	"crypto/md5"
	"crypto/rand"
	"crypto/rsa"
	"fmt"
)

func main() {
	//生成秘钥对
	priv, _ := rsa.GenerateKey(rand.Reader, 1024)
	//消息
	msg := []byte("微信公众号【福大大架构师每日一题】")
	//给消息进行散列处理
	h := md5.New()
	h.Write(msg)
	hashed := h.Sum(nil)

	//签名
	opts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthAuto, Hash: crypto.MD5}
	sig, _ := rsa.SignPSS(rand.Reader, priv, crypto.MD5, hashed, opts)

	//获取公钥
	pub := &priv.PublicKey
	err := rsa.VerifyPSS(pub, crypto.MD5, hashed, sig, opts)
	if err == nil {
		fmt.Println("验证通过!")
	}
}

在这里插入图片描述

ECC

ecdsa

package main

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/sha256"
	"fmt"
)

func main() {
	message := []byte("微信公众号【福大大架构师每日一题】")
	//参数一:曲线类型
	privateKey, _ := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
	//获取公钥
	pub := privateKey.PublicKey

	//散列明文
	digest := sha256.Sum256(message)
	r, s, _ := ecdsa.Sign(rand.Reader, privateKey, digest[:])

	message1 := []byte("微信公众号【福大大架构师每日一题】")
	digest = sha256.Sum256(message1)
	flag := ecdsa.Verify(&pub, digest[:], r, s)
	if flag {
		fmt.Println("验证成功")
	} else {
		fmt.Println("验证失败")
	}

}

在这里插入图片描述

SM2

非对称加密,基于椭圆加密,签名速度与秘钥生成速度都快于RSA。

摘要

能辨认出篡改,不能辨认真伪。

md5

package main

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
)

func main() {
	hash := md5.New()
	hash.Write([]byte("微信公众号【福大大架构师每日一题】"))
	result := hash.Sum(nil)
	fmt.Println(hex.EncodeToString(result))
	hash.Reset()
	hash.Write([]byte("微信公众号【福大大架构师每日一题】"))
	result = hash.Sum(nil)
	fmt.Println(hex.EncodeToString(result))
}

在这里插入图片描述
在这里插入图片描述

sha256

package main

import (
	"crypto/sha256"
	"fmt"
)

/*
go语言sha256包中实现了两种哈希函数,分别是sha256hesha224
*/

func main() {
	hash := sha256.New()
	hash.Write([]byte("微信公众号【福大大架构师每日一题】"))
	result := hash.Sum(nil)
	fmt.Printf("%x\n", result)
}

在这里插入图片描述
在这里插入图片描述

SM3

消息摘要算法,散列值为256位

package main

import (
	"encoding/hex"
	"fmt"

	"github.com/tjfoc/gmsm/sm3"
)

func main2() {
	hash := sm3.New()
	hash.Write([]byte("微信公众号【福大大架构师每日一题】"))
	result := hash.Sum(nil)
	fmt.Println(hex.EncodeToString(result))
	fmt.Println("length = ", len(result)*8)
}

func main() {
	result := sm3.Sm3Sum([]byte("微信公众号【福大大架构师每日一题】"))
	fmt.Println("length = ", len(result)*8)
	fmt.Println(hex.EncodeToString(result))
}

在这里插入图片描述

国密算法

SM2:非对称加密,基于椭圆加密,签名速度与秘钥生成速度都快于RSA。
SM3:消息摘要算法,散列值为256位
SM4:分组对称加密算法,秘钥长度和分组长度均为128位。

SSL协议

工作原理:
SSL协议主要是有三个自协议组成,分别是握手协议,记录协议,警报协议。

CA证书颁发机构

openssl模拟CA

posted @ 2022-03-19 22:16  福大大架构师每日一题  阅读(23)  评论(0编辑  收藏  举报  来源