Golang数据安全与常用加解密算法-非对称加密算法
- 使用公钥加密,使用私钥解密
- 公钥和私钥不同
- 公钥可以公布给所有人
- 公钥只有自己保存
- 相比于对称加密,运算速度非常慢
对称加密和非对称加密结合使用
例:小明要给小红传输机密文件,两人先交换各自的RSA公钥
- 小明生成一个随机的AES口令,用小红的RSA公钥加密,并发给小红
- 小红用自己的RSA私钥解密得到AES口令
- 双方使用这个共享的AES口令用AES加密通信
RSA
RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼)(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院麻省理工学院)工作。RSA就是他们三人姓氏开头字母拼在一起组成的
密钥越长,越难破解。目前768位的密钥还无法破解(至少没人公开宣布)。因此可以认为1024位的RSA密钥基本安全,2048的秘钥及其安全。
RSA的算法原理主要用到了数论。
RSA加密过程
-
随机选择两个不相等的质数p和q。p=61,q=53
-
计算p和q的乘积n。n=3222
-
计算n的欧拉函数φ(n) = (p-1)(q-1)。 φ(n) =3120
-
随机选择一个整数e,使得1< e < φ(n),且e与φ(n) 互质。e=17
-
计算e对于φ(n)的模反元素d,即求解ed+ φ(n)y=1。d=2753, y=-15
-
将n和e封装成公钥,n和d封装成私钥。公钥=(3233,17),公钥=(3233,2753)
示例代码:
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/hex"
"encoding/pem"
"errors"
"fmt"
"os"
)
/**
生成1024位的RSA私钥:
openssl genrsa -out data/rsa_private_key.pem 1024
根据私钥生成公钥:
openssl rsa -in data/rsa_private_key.pem -pubout -out data/rsa_public_key.pem
pem是一种标准格式,它通常包含页眉和页脚
*/
var (
publicKey []byte
privateKey []byte
)
// ReadFile 读取文件
func ReadFile(keyFile string) ([]byte, error) {
if f, err := os.Open(keyFile); err != nil {
return nil, err
} else {
content := make([]byte, 4096)
if n, err := f.Read(content); err != nil {
return nil, err
} else {
return content[:n], err
}
}
}
//ReadRSAKey 读取公私钥文件
func ReadRSAKey(publicKeyFile, privateKeyFile string) {
publicKey, _ = ReadFile(publicKeyFile)
privateKey, _ = ReadFile(privateKeyFile)
}
// RsaEncrypt Rsa加密
func RsaEncrypt(origData []byte) ([]byte, error) {
//解密pem格式的公钥
block, _ := pem.Decode(publicKey)
if block == nil {
return nil, errors.New("public key error")
}
//解析公钥,目前数字证书一般都是基于ITU(国际电信联盟)指定的x.509标准
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
//类型断言
pub := pubInterface.(*rsa.PublicKey)
//加密明文
return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
}
// RsaDecrypt Rsa解密
func RsaDecrypt(cipherText []byte) ([]byte, error) {
//解密
block, _ := pem.Decode(privateKey)
if block == nil {
return nil, errors.New("private key error!")
}
//解析PKCS1格式的私钥
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
//解密密文
return rsa.DecryptPKCS1v15(rand.Reader, priv, cipherText)
}
func main() {
ReadRSAKey("encryption/rsa_public_key.pem", "encryption/rsa_private_key.pem")
plain := "我们有什么不同"
cipherText, _ := RsaEncrypt([]byte(plain))
fmt.Printf("密文:%s\n", hex.EncodeToString(cipherText))
bPlain, _ := RsaDecrypt(cipherText)
fmt.Printf("明文:%s\n", string(bPlain))
}
>>>>>>>>>>output
密文:6ba0f414733b881bcc8207e18099c3c0f013227661532c5fd9c8e32c4ea771789f09abe3344bae8081cfde3c905623906e18bd79a929a212f9d7d07152f57bcf92d883d90c7963d8efdc98c587b305763f3ab91e6efb3b04eb78a30973ba8aa6ce6dd671c8f5e7422150748d5caf9af51aaf3217307154a377d9e12b43220e43
明文:我们有什么不同