Golang数据安全与常用加解密算法-非对称加密算法


  • 使用公钥加密,使用私钥解密
  • 公钥和私钥不同
  • 公钥可以公布给所有人
  • 公钥只有自己保存
  • 相比于对称加密,运算速度非常慢

对称加密和非对称加密结合使用

例:小明要给小红传输机密文件,两人先交换各自的RSA公钥

  1. 小明生成一个随机的AES口令,用小红的RSA公钥加密,并发给小红
  2. 小红用自己的RSA私钥解密得到AES口令
  3. 双方使用这个共享的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
明文:我们有什么不同