go语言实现非对称加密——RSA加密解密的实现

版权声明:本文为作者原创,如需转载,请注明出处
https://blog.csdn.net/weixin_42940826


非对称加密简介

什么是非对称加密
非对称加密,顾名思义,是相对于对称加密的一种加密方法,对称加密是指加密与解密使用的是同一把秘钥,而非对称加密有两把不同的秘钥,一个称之为公钥,另一个称之为私钥,使用公钥加密,私钥可以解密。或者使用私钥加密,公钥可以解密。大多数情况下,公钥可以公开,但是私钥只能自行持有,不可泄露。
常用的非对称密码算法有RSA、ECC椭圆形加密这两种。
本文亦将用go语言具体实现RSA的加密解密,关于椭圆形曲线加密,将在我的另一篇博文中作详细介绍。

为什么需要非对称加密
非对称加密可以说是密码学史上最伟大的发明之一,因为它解决了对称加密的秘钥配送问题,举个例子,A和B进行通信,A使用秘钥为123456,那么B如何知道秘钥为123456进行解密呢,如果直接发送,很容易被黑客抓取到,除了私底下交换秘钥,似乎没有更好的方法了。
但是非对称加密的出现解决了这一弊端,举个例子,还是A和B进行通信,A要给B发送信息,B把自己的公钥发送给A,然后A使用B的公钥对信息进行加密 发送给B,由于此信息使用的B的公钥进行加密,所以只有使用B的私钥才能解密,因此即使黑客知道B的公钥,也是没有任何办法的。

应用场景
信息加密,登陆认证,数字签名,数字证书等等,如今红极一时的区块链技术也是使用了非对称加密,还有包括网银U盾、二代居民身份证本质上也是使用了非对称加密。
关于数字签名将在我的另一篇博文中作详细介绍。


RSA加密解密流程一览

生成私钥流程

  1. 使用rsa中的GenerateKey方法生成私钥

    func GenerateKey(random io.Reader, bits int) (priv *PrivateKey, err error)

    • rand.Reader ->随机数生成器
    • bits ->建议1024的整数倍
  2. 通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串

    func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte

  3. 将私钥字符串设置到pem格式块中

    初始化一个pem.Block块

    type Block struct {
       Type    string            // 得自前言的类型(如"RSA PRIVATE KEY")
       Headers map[string]string // 可选的头项
       Bytes   []byte            // 内容解码后的数据,一般是DER编码的ASN.1结构
    }
    
  4. 通过pem将设置好的数据进行编码, 并写入磁盘文件中

    func Encode(out io.Writer, b *Block) error

    • out - 准备一个文件指针
    • block- 将准备好的pem.block放入其中

生成公钥流程

  1. 从得到的私钥对象中将公钥信息取出

    type PrivateKey struct {
        PublicKey            // 公钥
        D         *big.Int   // 私有的指数
        Primes    []*big.Int // N的素因子,至少有两个
        // 包含预先计算好的值,可在某些情况下加速私钥的操作
        Precomputed PrecomputedValues
    }
    
  2. 通过x509标准将得到 的rsa公钥序列化为字符串

    func MarshalPKIXPublicKey(pub interface{}) ([]byte, error)
    
  3. 将公钥字符串设置到pem格式块中

    type Block struct {
        Type    string            // 得自前言的类型(如"RSA PRIVATE KEY")
        Headers map[string]string // 可选的头项
        Bytes   []byte            // 内容解码后的数据,一般是DER编码的ASN.1结	}
    
  4. 通过pem将设置好的数据进行编码, 并写入磁盘文件

    func Encode(out io.Writer, b *Block) error

RSA加密流程

  1. 将公钥文件中的公钥读出, 得到使用pem编码的字符串

    – 读文件

  2. 将得到的字符串pem解码

    – pem.Decode

  3. 使用x509将编码之后的公钥解析出来

    – func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error)

  4. 使用得到的公钥通过rsa进行数据加密

RSA解密流程

  1. 将私钥文件中的私钥读出, 得到使用pem编码的字符串
  2. 将得到的字符串pem解码
  3. 使用x509将编码之后的私钥解析出来
  4. 使用得到的私钥通过rsa进行数据解密

代码实现

package main

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

func Getkeys(){
	//得到私钥
	privateKey,_:=rsa.GenerateKey(rand.Reader,2048)
	//通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串
	x509_Privatekey:=x509.MarshalPKCS1PrivateKey(privateKey)
	//创建一个用来保存私钥的以.pem结尾的文件
	fp,_:=os.Create("csdn_private.pem")
	defer fp.Close()
	//将私钥字符串设置到pem格式块中
	pem_block:=pem.Block{
		Type:"csdn_privateKey",
		Bytes:x509_Privatekey,
	}
	//转码为pem并输出到文件中
	pem.Encode(fp,&pem_block)

	//处理公钥,公钥包含在私钥中
	publickKey:=privateKey.PublicKey
	//接下来的处理方法同私钥
	//通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串
	x509_PublicKey,_:=x509.MarshalPKIXPublicKey(&publickKey)
	pem_PublickKey:=pem.Block{
		Type:"csdn_PublicKey",
		Bytes:x509_PublicKey,
	}
	file,_:=os.Create("csdn_PublicKey.pem")
	defer file.Close()
	//转码为pem并输出到文件中
	pem.Encode(file,&pem_PublickKey)

}

//使用公钥进行加密
func RSA_encrypter(path string,msg []byte)[]byte  {
	//首先从文件中提取公钥
	fp,_:=os.Open(path)
	defer fp.Close()
	//测量文件长度以便于保存
	fileinfo,_:=fp.Stat()
	buf:=make([]byte,fileinfo.Size())
	fp.Read(buf)
	//下面的操作是与创建秘钥保存时相反的
	//pem解码
	block,_:=pem.Decode(buf)
	//x509解码,得到一个interface类型的pub
	pub,_:=x509.ParsePKIXPublicKey(block.Bytes)
	//加密操作,需要将接口类型的pub进行类型断言得到公钥类型
	cipherText,_:=rsa.EncryptPKCS1v15(rand.Reader,pub.(*rsa.PublicKey),msg)
	return cipherText
}

//使用私钥进行解密
func RSA_decrypter(path string,cipherText []byte)[]byte  {
	//同加密时,先将私钥从文件中取出,进行二次解码
	fp,_:=os.Open(path)
	defer fp.Close()
	fileinfo,_:=fp.Stat()
	buf:=make([]byte,fileinfo.Size())
	fp.Read(buf)
	block,_:=pem.Decode(buf)
	PrivateKey,_:=x509.ParsePKCS1PrivateKey(block.Bytes)
	//二次解码完毕,调用解密函数
	afterDecrypter,_:=rsa.DecryptPKCS1v15(rand.Reader,PrivateKey,cipherText)
	return afterDecrypter
}

func main() {
	//尝试调用
	msg:=[]byte("RSA非对称加密很棒")
	ciphertext:=RSA_encrypter("csdn_PublicKey.pem",msg)
	//转化为十六进制方便查看结果
	fmt.Println(hex.EncodeToString(ciphertext))
	result:=RSA_decrypter("csdn_private.pem",ciphertext)
	fmt.Println(string(result))
}


以上就是加密解密的go语言实现了。

我博客中还有很多关于对称加密,椭圆形曲线加密解密,单向散列函数、数字签名等详细分析,欢迎一起交流: )

你可能感兴趣的:(密码学)