mysql 非对称密钥_golang加密算法(二)非对称加密

本文详细介绍了RSA非对称加密算法,包括其原理、加密与解密过程,并给出了使用Go语言实现RSA密钥对生成、加密和解密的代码示例。
摘要由CSDN通过智能技术生成

1. RSA

私钥:使用随机数按照一定的规则生成。

公钥:由私钥推导。

私钥只有自己持有,公钥任何人都可以持有。

利用数学难题,大素数(乘积)因式分解。

1. RSA加密

下面我们终于可以讲一讲非对称加密的代表—RSA的加密过程了。在RSA中,明文、密钥和密文都是数字。RSA的加密过程可以用下列公式来表达,如下。

$$

密文=明文 ^ E mod N(RSA加密)

$$

也就是说,RSA的密文是对代表明文的数字的E次方求modN的结果。换句话说,就是将明文自己做E次乘法,然后将其结果除以N求余数,这个余数就是密文。

咦,就这么简单?

对,就这么简单。仅仅对明文进行乘方运算并求mod即可,这就是整个加密的过程。在对称密码中,出现了很多复杂的函数和操作,就像做炒鸡蛋一样将比特序列挪来挪去,还要进行XOR(按位异或)等运算才能完成,但RSA却不同,它非常简洁。

对了,加密公式中出现的两个数一一一E和N,到底都是什么数呢?RSA的加密是求明文的E次方modN,因此只要知道E和N这两个数,任何人都可以完成加密的运算。

所以说,E和N是RSA加密的密钥,也就是说,==E和N的组合就是公钥==。

不过,E和N并不是随便什么数都可以的,它们是经过严密计算得出的。顺便说一句,E是加密(Encryption)的首字母,N是数字(Number)的首字母。

有一个很容易引起误解的地方需要大家注意一一E和N这两个数并不是密钥对(公钥和私钥的密钥对)。E和N两个数才组成了一个公钥,因此我们一般会写成 “公钥是(E,N)” 或者 “公钥是{E, N}" 这样的形式,将E和N用括号括起来。

现在大家应该已经知道,==RSA的加密就是 “求E次方的modN"==,接下来我们来看看RSA的解密。

2. RSA解密

RSA的解密和加密一样简单,可以用下面的公式来表达:

$$

明文=密文^DmodN(RSA解密)

$$

也就是说,对表示密文的数字的D次方求modN就可以得到明文。换句话说,将密文自己做D次乘法,再对其结果除以N求余数,就可以得到明文。

这里所使用的数字N和加密时使用的数字N是相同的。==数D和数N组合起来就是RSA的解密密钥==,因此D和N的组合就是私钥。只有知道D和N两个数的人才能够完成解密的运算。

大家应该已经注意到,在RSA中,加密和解密的形式是相同的。加密是求 "E次方的mod N”,而解密则是求 "D次方的modN”,这真是太美妙了。

当然,D也并不是随便什么数都可以的,作为解密密钥的D,和数字E有着相当紧密的联系。否则,用E加密的结果可以用D来解密这样的机制是无法实现的。

顺便说一句,D是解密〈Decryption)的首字母,N是数字(Number)的首字母。

3. RSA算法原理

Go语言实现

1. 生成密钥对

package rsa

import (

"crypto/rand"

"crypto/rsa"

"crypto/x509"

"encoding/base64"

"encoding/pem"

"log"

"os"

)

// 私钥的地址

const privateKeyFile = "./privateRSAKey.pem"

// 公钥的地址

const publicKeyFile = "./publicRSAKey.pem"

// 生成密钥对

// priv.E = 65537 ,使用pkcs1推荐的65537

func GenerateKeyPair(bits int) (err error) {

var (

privateKey *rsa.PrivateKey

privDerText []byte

privPemBlock pem.Block

privFileHandle *os.File

pubDerText []byte

pubPemBLock pem.Block

pubFileHandle *os.File

)

log.Println("生成私钥...")

// 1. 使用随机数生成密钥对

if privateKey, err = rsa.GenerateKey(rand.Reader, bits); err != nil {

return

}

// 2. 编码处理

// MarshalPKCS1PrivateKey 将公钥转化为 ASN.1 DER 编码格式

privDerText = x509.MarshalPKCS1PrivateKey(privateKey)

log.Printf("私钥为:%s\n", base64.StdEncoding.EncodeToString(privDerText))

// 3. 生成pem格式的block

privPemBlock = pem.Block{

Type: "RSA PRIVATE KEY",

Headers: nil,

Bytes: privDerText,

}

// 4. 写入到指定文件

if privFileHandle, err = os.OpenFile(privateKeyFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755); err != nil {

return

}

defer privFileHandle.Close()

if err = pem.Encode(privFileHandle, &privPemBlock); err != nil {

return

}

log.Println("生成公钥...")

// 5. 编码处理

pubDerText = x509.MarshalPKCS1PublicKey(&privateKey.PublicKey)

log.Printf("公钥为:%s\n", base64.StdEncoding.EncodeToString(pubDerText))

// 6. 生成pem格式的block

pubPemBLock = pem.Block{

Type: "RSA PUBLIC KEY",

Headers: nil,

Bytes: pubDerText,

}

// 7. 写入到指定文件

if pubFileHandle, err = os.OpenFile(publicKeyFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755); err != nil {

return

}

defer pubFileHandle.Close()

err = pem.Encode(pubFileHandle, &pubPemBLock)

return

}

2. 加密

// 公钥加密

func RSAEncript(src []byte) (dst []byte, err error) {

var (

fileContent []byte

block *pem.Block

derText []byte

publicKey *rsa.PublicKey

)

// 1. 读取公钥

if fileContent, err = ioutil.ReadFile(publicKeyFile); err != nil {

return

}

block, _ = pem.Decode(fileContent)

if block.Type != "RSA PUBLIC KEY" {

return nil, errors.New("公钥类型错误")

}

// 2. 获取x509编码的格式der

derText = block.Bytes

// 3. 解码公钥

if publicKey, err = x509.ParsePKCS1PublicKey(derText); err != nil {

return

}

// 4. 加密

dst = make([]byte, 0)

dst, err = rsa.EncryptPKCS1v15(rand.Reader, publicKey, src)

return

}

3. 解密

// 私钥解密

func RSADecript(src []byte) (dst []byte, err error) {

var (

fileContent []byte

block *pem.Block

derText []byte

privateKey *rsa.PrivateKey

)

// 1. 读取私钥文件信息

if fileContent, err = ioutil.ReadFile(privateKeyFile); err != nil {

return

}

// 2. 获取pem格式结构体block

block, _ = pem.Decode(fileContent)

// 3. 获取x509编码格式derText

derText = block.Bytes

// 4. 获取私钥

if privateKey, err = x509.ParsePKCS1PrivateKey(derText); err != nil {

return

}

// 5. 解密

dst, err = rsa.DecryptPKCS1v15(rand.Reader, privateKey, src)

return

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值