版权声明:本文为作者原创,如需转载,请注明出处
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加密解密流程一览
生成私钥流程
使用rsa中的GenerateKey方法生成私钥
func GenerateKey(random io.Reader, bits int) (priv *PrivateKey, err error)
- rand.Reader ->随机数生成器
- bits ->建议1024的整数倍
通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串
func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte
将私钥字符串设置到pem格式块中
初始化一个pem.Block块
type Block struct { Type string // 得自前言的类型(如"RSA PRIVATE KEY") Headers map[string]string // 可选的头项 Bytes []byte // 内容解码后的数据,一般是DER编码的ASN.1结构 }
通过pem将设置好的数据进行编码, 并写入磁盘文件中
func Encode(out io.Writer, b *Block) error
- out - 准备一个文件指针
- block- 将准备好的pem.block放入其中
生成公钥流程
从得到的私钥对象中将公钥信息取出
type PrivateKey struct { PublicKey // 公钥 D *big.Int // 私有的指数 Primes []*big.Int // N的素因子,至少有两个 // 包含预先计算好的值,可在某些情况下加速私钥的操作 Precomputed PrecomputedValues }
通过x509标准将得到 的rsa公钥序列化为字符串
func MarshalPKIXPublicKey(pub interface{}) ([]byte, error)
将公钥字符串设置到pem格式块中
type Block struct { Type string // 得自前言的类型(如"RSA PRIVATE KEY") Headers map[string]string // 可选的头项 Bytes []byte // 内容解码后的数据,一般是DER编码的ASN.1结 构 }
通过pem将设置好的数据进行编码, 并写入磁盘文件
func Encode(out io.Writer, b *Block) error
RSA加密流程
将公钥文件中的公钥读出, 得到使用pem编码的字符串
– 读文件
将得到的字符串pem解码
– pem.Decode
使用x509将编码之后的公钥解析出来
– func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error)
使用得到的公钥通过rsa进行数据加密
RSA解密流程
- 将私钥文件中的私钥读出, 得到使用pem编码的字符串
- 将得到的字符串pem解码
- 使用x509将编码之后的私钥解析出来
- 使用得到的私钥通过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语言实现了。
我博客中还有很多关于对称加密,椭圆形曲线加密解密,单向散列函数、数字签名等详细分析,欢迎一起交流: )