163 lines
4.6 KiB
Go
163 lines
4.6 KiB
Go
package rsa
|
||
|
||
import (
|
||
"crypto/rand"
|
||
"crypto/rsa"
|
||
"crypto/sha256"
|
||
"crypto/x509"
|
||
"encoding/base64"
|
||
"encoding/pem"
|
||
"fmt"
|
||
"strings"
|
||
)
|
||
|
||
// parseRSAPublicKeyFromPEM 解析PEM编码的RSA公钥
|
||
func parseRSAPublicKeyFromPEM(pemData []byte) (*rsa.PublicKey, error) {
|
||
block, _ := pem.Decode(pemData)
|
||
if block == nil || block.Type != "PUBLIC KEY" {
|
||
return nil, fmt.Errorf("failed to parse PEM block containing the RSA public key")
|
||
}
|
||
|
||
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
switch pub := pub.(type) {
|
||
case *rsa.PublicKey:
|
||
return pub, nil
|
||
default:
|
||
return nil, fmt.Errorf("unknown public key type in PKIX wrapping")
|
||
}
|
||
}
|
||
|
||
// encrypt 使用RSA公钥加密数据
|
||
func Encrypt(publicKeyPEM string, plaintext string) ([]byte, error) {
|
||
var encryptedData []byte
|
||
// 将PEM编码的公钥转换为[]byte
|
||
pemData := []byte(publicKeyPEM)
|
||
|
||
// 解析PEM数据以获取公钥
|
||
pubKey, err := parseRSAPublicKeyFromPEM(pemData)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
hash := sha256.New()
|
||
maxBlockSize := pubKey.Size() - 2*hash.Size() - 2
|
||
// 创建用于加密的随机填充
|
||
label := []byte("") // OAEP标签,对于某些情况可能是非空的
|
||
for len(plaintext) > 0 {
|
||
blockSize := maxBlockSize
|
||
if len(plaintext) < maxBlockSize {
|
||
blockSize = len(plaintext)
|
||
}
|
||
block := plaintext[:blockSize]
|
||
encryptedBlock, err := rsa.EncryptOAEP(hash, rand.Reader, pubKey, []byte(block), label)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
encryptedData = append(encryptedData, encryptedBlock...)
|
||
plaintext = plaintext[blockSize:]
|
||
}
|
||
return encryptedData, nil
|
||
}
|
||
|
||
// parseRSAPrivateKeyFromPEM 解析PEM编码的RSA私钥
|
||
func parseRSAPrivateKeyFromPEM(pemData []byte) (*rsa.PrivateKey, error) {
|
||
block, _ := pem.Decode(pemData)
|
||
if block == nil || block.Type != "RSA PRIVATE KEY" {
|
||
return nil, fmt.Errorf("failed to parse PEM block containing the RSA private key")
|
||
}
|
||
|
||
// 尝试使用PKCS#1 v1.5
|
||
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||
if err != nil {
|
||
// 如果失败,尝试使用PKCS#8
|
||
privInterface, err := x509.ParsePKCS8PrivateKey(block.Bytes)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
switch k := privInterface.(type) {
|
||
case *rsa.PrivateKey:
|
||
priv = k
|
||
default:
|
||
return nil, fmt.Errorf("unknown private key type in PKCS#8 wrapping")
|
||
}
|
||
}
|
||
|
||
return priv, nil
|
||
}
|
||
|
||
// decrypt 使用RSA私钥解密数据
|
||
func Decrypt(privateKeyPEM string, encryptedDataBase64 string) ([]byte, error) {
|
||
var decryptedData []byte
|
||
// 将PEM编码的私钥转换为[]byte
|
||
pemData := []byte(privateKeyPEM)
|
||
// 解析PEM数据以获取私钥
|
||
privKey, err := parseRSAPrivateKeyFromPEM(pemData)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
keySize := privKey.PublicKey.Size()
|
||
label := []byte("") // OAEP标签,对于某些情况可能是非空的
|
||
hash := sha256.New()
|
||
// 将Base64编码的加密数据解码为字节切片
|
||
encryptedData, err := base64.StdEncoding.DecodeString(encryptedDataBase64)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
for len(encryptedData) > 0 {
|
||
block := encryptedData[:keySize]
|
||
// 这里假设使用的是OAEP填充和SHA-256哈希函数
|
||
decryptedBlock, err := rsa.DecryptOAEP(hash, rand.Reader, privKey, block, label)
|
||
if err != nil {
|
||
//// 如果失败,可以尝试使用PKCS#1 v1.5填充
|
||
decryptedBlock, err = rsa.DecryptPKCS1v15(rand.Reader, privKey, encryptedData)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
}
|
||
decryptedData = append(decryptedData, decryptedBlock...)
|
||
encryptedData = encryptedData[keySize:]
|
||
}
|
||
return decryptedData, nil
|
||
}
|
||
|
||
// 生成密钥对
|
||
func GenerateKey() (string, string, error) {
|
||
// 生成私钥
|
||
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||
if err != nil {
|
||
return "", "", err
|
||
}
|
||
// 导出私钥PKCS#1格式
|
||
privKey := x509.MarshalPKCS1PrivateKey(privateKey)
|
||
// 将私钥转换为PEM编码
|
||
var privBlock = &pem.Block{
|
||
Type: "RSA PRIVATE KEY",
|
||
Bytes: privKey,
|
||
}
|
||
privPem := pem.EncodeToMemory(privBlock)
|
||
// 导出公钥
|
||
pubKey := &privateKey.PublicKey
|
||
derPkix, err := x509.MarshalPKIXPublicKey(pubKey)
|
||
if err != nil {
|
||
return "", "", err
|
||
}
|
||
// 将公钥转换为PEM编码
|
||
var pubBlock = &pem.Block{
|
||
Type: "PUBLIC KEY",
|
||
Bytes: derPkix,
|
||
}
|
||
pubPem := pem.EncodeToMemory(pubBlock)
|
||
pri := strings.Replace(string(privPem), "-----BEGIN RSA PRIVATE KEY-----\n", "", -1)
|
||
pri = strings.Replace(pri, "\n-----END RSA PRIVATE KEY-----\n", "", -1)
|
||
pri = strings.Replace(pri, "\n", "", -1)
|
||
pub := strings.Replace(string(pubPem), "-----BEGIN PUBLIC KEY-----\n", "", -1)
|
||
pub = strings.Replace(pub, "\n-----END PUBLIC KEY-----\n", "", -1)
|
||
pub = strings.Replace(pub, "\n", "", -1)
|
||
return pub, pri, nil
|
||
}
|