非对称加密

非对称加密

对称加密存在的问题
  • 当通信对象很多时会面临众多秘钥的有效管理问题。(秘钥管理困难)
  • 对于一个新的数据通信对象,密钥怎样进行传输的问题。(秘钥分发困难)
非对称加密

加密解密使用不相同同的钥匙

加密流程

在这里插入图片描述

对称加密与非对称加密对比
  • 对称加密
  1. 秘钥数量:1
  2. 效率:高,适合大文件加解密
  • 非对称加密
  1. 秘钥数量:2
    1. 公钥:public key,任何人都可以持有。公共的
    2. 私钥:private key,只有自己持有,任何人都不可以拥有
  2. 公钥与私钥一一对应,
    1. 公钥加密,只有自己的私钥可以解密
    2. 私钥签名,只有自己的公钥可以解密
  3. 生成过程:
    1. 选定一个随机数=> 生成私钥 =》 公钥 (不能反推)
  4. 效率:低,不适合大文件加解密
应用非对称加密的场景
  1. 通信加密

公钥加密,私钥解密

  1. https

验证服务器,数字证书,使用ca认证公钥

  1. 签名(防止篡改)

哈希+非对称加密

  1. 网银U盾

验证client,U盾相当于私钥,公钥在服务端

  1. github ssh(secure shell)登录
  • ssh是一种网络协议,主要用于计算机之间的加密登录与数据传输
  • ssh登录的时候没有ca认证,需要用户自己确认登录主机的指纹,点击yes后把远程主机的指纹存放到本地的know_hosts中,后续登录会跳过警告。
  • ssh-keygen -t rsa,演示
RSA非对称加密算法

密文=明文^ E mod N(RSA加密)====> {E, N } ==> 公钥

明文=密文^D modN(RSA解密)====》{D, N} ==> 私钥

核心思想:利用大素数的因式分解困难

素数:除了1和本身能整除,其他数字无法整除的数

go语言实现创建公钥私钥
基本概念

x509: 证书规范

der:公钥私钥的一种编码格式

pem: PEM编码主要用于TLS密钥和证书。

base64:数据编码格式,可逆的

pkcs: 公钥密码的发展而制订的一系列标准。(PKCS 全称是 Public-Key Cryptography Standards )

pkcs1、pkcs8:用的比较多,可以把pkcs1人工转为pkcs8,目前pkcs8比较流行

创建私钥
流程
  1. 创建私钥
  2. 对私钥进行编码,生成der格式的字符串
  3. 将der字符串拼装到pem格式的数据块中
  4. pem格式进行base64编码,得到最终的私钥
代码
func generateRsaKeyPair(bit int) error {

	//rsa
	// 1. 创建私钥, GenerateKey函数使用随机数据生成器random生成一对具有指定字位数的RSA密钥。
	// func GenerateKey(random io.Reader, bits int) (priv *PrivateKey, err error)
	priKey, err := rsa.GenerateKey(rand.Reader, bit)
	if err != nil {
		return err
	}

	// 2. 对私钥进行编码,生成der格式的字符串
	//x509包:公钥标准, func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte
	derText, err := x509.MarshalPKCS8PrivateKey(priKey)
	if err != nil {
		return err
	}

	// 3. 将der字符串拼装到pem格式的数据块中
	// type Block struct {
	// 	Type    string            // 得自前言的类型(如"RSA PRIVATE KEY")
	// 	Headers map[string]string // 可选的头项
	// 	Bytes   []byte            // 内容解码后的数据,一般是DER编码的ASN.1结构
	// }

	block := pem.Block{
		Type:    "RSA PRIVATE KEY",
		Headers: nil, //头信息,键值对
		Bytes:   derText,
	}

	f1, err := os.Create("rsaPriKey.pem")
	if err != nil {
		return err
	}

	defer f1.Close()

	// 4. pem格式进行base64编码,得到最终的私钥
	// err = pem.Encode(os.Stdout, &block)
	err = pem.Encode(f1, &block)
	if err != nil {
		return err
	}

	return nil
}
创建公钥
流程
  1. 创建私钥
  2. 通过私钥得到公钥
  3. 对公钥进行编码,生成der格式的字符串
  4. 将der字符串拼装到pem格式的数据块中
  5. pem格式进行base64编码,得到最终的公钥
代码
func  GenerateRsaPubKey(priKey *PrivateKey) error {
	// 1. 创建私钥后
	// 2. 通过私钥得到公钥
	pubKey := priKey.PublicKey

	// 3. 对公钥进行编码,生成der格式的字符串
	//注意要使用地址,否则报错
	derText, err := x509.MarshalPKIXPublicKey(&pubKey)
	if err != nil {
		return err
	}

	// 4. 将der字符串拼装到pem格式的数据块中
	block := pem.Block{
		Type:    "RSA PUBLIC KEY",
		Headers: nil,
		Bytes:   derText,
	}
	
	f1, err := os.Create("rsaPublicKey.pem")
	if err != nil {
		return err
	}
	defer f1.Close()
	
	// 5. pem格式进行base64编码,得到最终的公钥
	// err = pem.Encode(os.Stdout, &block)
    err = pem.Encode(f1, &block)
	if err != nil {
		return err
	}
    
	return nil
}

注意在生成公钥的时候MarshalPKIXPublicKey后面的要要传地址&pubKey

go语言实现公钥加密,私钥解密
公钥加密
流程
  1. 读取公钥文件
  2. 解码,得到block
  3. 得到der
  4. 得到公钥
  5. 加密
代码
func getRsaPubKey(filename string)(*rsa.PublicKey,error){
//1. 读取公钥文件
	info, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
//2. 解码,得到block,
	// block, rest := pem.Decode(info)
	block, _ := pem.Decode(info)
//3. 得到der
	der := block.Bytes
//4. 得到公钥
	// func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error)
	// ParsePKIXPublicKey解析一个DER编码的公钥。这些公钥一般在以"BEGIN PUBLIC KEY"出现的PEM块中。
	// derText, err = x509.MarshalPKIXPublicKey(&pubKey) //这是编码过程
	pubInterface, err := x509.ParsePKIXPublicKey(der) //这是解码过程
	if err != nil {
		return nil, err
	}
	//断言
	pubKey, ok := pubInterface.(*rsa.PublicKey)
	//断言失败,返回错误信息
	if !ok {
		return nil, errors.New("pubKey no ok!")
	}
	return pubKey, nil
}
//5. 加密
func rsaEncryptData(filename string,src []byte)([]byte,error){
	pubKey,err:=getRsaPubKey(filename)
	if err!=nil{
		return nil,err
	}
	// EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error)
	encryptInfo, err := rsa.EncryptPKCS1v15(rand.Reader, pubKey, src)
	if err != nil {
		return nil, err
	}
	return encryptInfo, nil
}
私钥解密
流程
  1. 读取私钥文件
  2. 解码,得到block
  3. 得到der
  4. 得到私钥
  5. 解密
代码
func getRsaPriKey(filename string)(*rsa.PrivateKey,error){
//1. 读取私钥文件
	info, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
//2. 解码,得到block,
	block, _ := pem.Decode(info)
//3. 得到der
	der := block.Bytes
//4. 得到私钥
	priKeyInter, err := x509.ParsePKCS8PrivateKey(der)
	if err != nil {
		return nil, err
	}
	//断言
	priKey, ok := priKeyInter.(*rsa.PrivateKey)
	//断言失败,返回错误信息
	if !ok {
		return nil, errors.New("priKey no ok!")
	}
	return pubKey, nil
}
//5. 解密
func rsaDecryptData(filename string,src []byte)([]byte,error){
	pubKey,err:=getRsaPriKey(filename)
	if err!=nil{
		return nil,err
	}
	info, err := rsa.DecryptPKCS1v15(rand.Reader, priKey, src)
	if err != nil {
		return nil, err
	}
	return info, nil
}	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值