背景

安全是软件开始中很重要的一个环节,在加密算法中使用较多加密方式和加密概念有:

  • 对称密钥加密:一个密钥
  • 公钥加密:两个密钥
  • 单向散列算法
  • 数字签名:结合使用公钥与散列
  • 密钥交换:结合使用对称密钥与公钥

主要使用的加密方式就是对称加密和非对称加密了,对称加密的代表是 AES、DES、3DES 等,非对称加密代表是 RSA、ECC等,最近火热的比特币中就是使用 ECC 椭圆曲线算法,本篇主要是我在使用 Golang RSA 私钥加密公钥解密遇到的问题,以及寻找的解决方案进行阐述。

附上:
gorsa Github地址:https://github.com/farmerx/gorsa
优化过的 gorsa Github地址:https://github.com/Lyafei/go-rsa

RSA

RSA 公开密钥密码体制。所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种 “由已知加密密钥推导出解密密钥在计算上是不可行的” 密码体制。

在公开密钥密码体制中,加密密钥(即公开密钥)PK 是公开信息,而解密密钥(即秘密密钥)SK 是需要保密的。加密算法 E 和解密算法 D 也都是公开的。虽然解密密钥 SK 是由公开密钥 PK 决定的,由于无法计算出大数 n 的欧拉函数 phi(N),所以不能根据 PK 计算出 SK。

正是基于这种理论,1978年出现了著名的 RSA 算法,它通常是先生成一对 RSA 密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。为提高保密强度,RSA 密钥至少为 500 位长,一般推荐使用 1024位。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的 DES 或 IDEA 密钥加密,然后使用 RSA 密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。

关于 RSA 加密的具体算法实现可以参考以下两篇文章:
RSA算法原理(一)
RSA算法原理(二)

GoRSA

在 Golang 使用 RSA 加密算法时,遇到了一个坑,官方提供的库 crypto/rsa 中只有公钥加密私钥解密的实现,意味着无法实现公钥加密私钥解密,而要实现双向认证必须要使用公钥加密私钥解密,找啊找,终于找到了可以使用的库,通过查看源码使用的是软实现,在这里推荐给大家
基于 https://github.com/farmerx/gorsa 进行封装优化了以下几点:

  • 优化公私钥需要提前注册初始化
  • 加密机进行 base64 处理
  • 支持 RSAWithSHA1/RSAWithSHA256 签名验证算法

获取扩展包:

go get github.com/Lyafei/go-rsa

具体使用:

package main

import (
    "log"
    "errors"
    "github.com/Lyafei/go-rsa"
)

var Pubkey = `-----BEGIN Public key-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk+89V7vpOj1rG6bTAKYM
56qmFLwNCBVDJ3MltVVtxVUUByqc5b6u909MmmrLBqS//PWC6zc3wZzU1+ayh8xb
UAEZuA3EjlPHIaFIVIz04RaW10+1xnby/RQE23tDqsv9a2jv/axjE/27b62nzvCW
eItu1kNQ3MGdcuqKjke+LKhQ7nWPRCOd/ffVqSuRvG0YfUEkOz/6UpsPr6vrI331
hWRB4DlYy8qFUmDsyvvExe4NjZWblXCqkEXRRAhi2SQRCl3teGuIHtDUxCskRIDi
aMD+Qt2Yp+Vvbz6hUiqIWSIH1BoHJer/JOq2/O6X3cmuppU4AdVNgy8Bq236iXvr
MQIDAQAB
-----END Public key-----
`

var Pirvatekey = `-----BEGIN Private key-----
MIIEpAIBAAKCAQEAk+89V7vpOj1rG6bTAKYM56qmFLwNCBVDJ3MltVVtxVUUByqc
5b6u909MmmrLBqS//PWC6zc3wZzU1+ayh8xbUAEZuA3EjlPHIaFIVIz04RaW10+1
xnby/RQE23tDqsv9a2jv/axjE/27b62nzvCWeItu1kNQ3MGdcuqKjke+LKhQ7nWP
RCOd/ffVqSuRvG0YfUEkOz/6UpsPr6vrI331hWRB4DlYy8qFUmDsyvvExe4NjZWb
lXCqkEXRRAhi2SQRCl3teGuIHtDUxCskRIDiaMD+Qt2Yp+Vvbz6hUiqIWSIH1BoH
Jer/JOq2/O6X3cmuppU4AdVNgy8Bq236iXvrMQIDAQABAoIBAQCCbxZvHMfvCeg+
YUD5+W63dMcq0QPMdLLZPbWpxMEclH8sMm5UQ2SRueGY5UBNg0WkC/R64BzRIS6p
jkcrZQu95rp+heUgeM3C4SmdIwtmyzwEa8uiSY7Fhbkiq/Rly6aN5eB0kmJpZfa1
6S9kTszdTFNVp9TMUAo7IIE6IheT1x0WcX7aOWVqp9MDXBHV5T0Tvt8vFrPTldFg
IuK45t3tr83tDcx53uC8cL5Ui8leWQjPh4BgdhJ3/MGTDWg+LW2vlAb4x+aLcDJM
CH6Rcb1b8hs9iLTDkdVw9KirYQH5mbACXZyDEaqj1I2KamJIU2qDuTnKxNoc96HY
2XMuSndhAoGBAMPwJuPuZqioJfNyS99x++ZTcVVwGRAbEvTvh6jPSGA0k3cYKgWR
NnssMkHBzZa0p3/NmSwWc7LiL8whEFUDAp2ntvfPVJ19Xvm71gNUyCQ/hojqIAXy
tsNT1gBUTCMtFZmAkUsjqdM/hUnJMM9zH+w4lt5QM2y/YkCThoI65BVbAoGBAMFI
GsIbnJDNhVap7HfWcYmGOlWgEEEchG6Uq6Lbai9T8c7xMSFc6DQiNMmQUAlgDaMV
b6izPK4KGQaXMFt5h7hekZgkbxCKBd9xsLM72bWhM/nd/HkZdHQqrNAPFhY6/S8C
IjRnRfdhsjBIA8K73yiUCsQlHAauGfPzdHET8ktjAoGAQdxeZi1DapuirhMUN9Zr
kr8nkE1uz0AafiRpmC+cp2Hk05pWvapTAtIXTo0jWu38g3QLcYtWdqGa6WWPxNOP
NIkkcmXJjmqO2yjtRg9gevazdSAlhXpRPpTWkSPEt+o2oXNa40PomK54UhYDhyeu
akuXQsD4mCw4jXZJN0suUZMCgYAgzpBcKjulCH19fFI69RdIdJQqPIUFyEViT7Hi
bsPTTLham+3u78oqLzQukmRDcx5ddCIDzIicMfKVf8whertivAqSfHytnf/pMW8A
vUPy5G3iF5/nHj76CNRUbHsfQtv+wqnzoyPpHZgVQeQBhcoXJSm+qV3cdGjLU6OM
HgqeaQKBgQCnmL5SX7GSAeB0rSNugPp2GezAQj0H4OCc8kNrHK8RUvXIU9B2zKA2
z/QUKFb1gIGcKxYr+LqQ25/+TGvINjuf6P3fVkHL0U8jOG0IqpPJXO3Vl9B8ewWL
cFQVB/nQfmaMa4ChK0QEUe+Mqi++MwgYbRHx1lIOXEfUJO+PXrMekw==
-----END Private key-----
`


func main() {
    // Public key encryption private key decryption
    if err := applyPubEPriD(); err != nil {
        log.Println(err)
    }
    // Public key decryption private key encryption
    if err := applyPriEPubD(); err != nil {
        log.Println(err)
    }
}

// Public key encryption private key decryption
func applyPubEPriD() error {
       pubenctypt, err := gorsa.PublicEncrypt(`hello world`,Pubkey)
    if err != nil {
        return err
    }

    pridecrypt, err := gorsa.PriKeyDecrypt(pubenctypt,Pirvatekey)
    if err != nil {
        return err
    }
    if string(pridecrypt) != `hello world` {
        return errors.New(`Decryption failed`)
    }
    return nil
}

// Public key decryption private key encryption
func applyPriEPubD() error {
prienctypt, err := gorsa.PriKeyEncrypt(`hello world`,Pirvatekey)
if err != nil {
    return err
}

pubdecrypt, err := gorsa.PublicDecrypt(prienctypt,Pubkey)
if err != nil {
    return err
}
if string(pubdecrypt) != `hello world` {
    return errors.New(`Decryption failed`)
}
return nil
}

总结

RSA 在软件开发中运用广泛,如果大家也遇到 Golang公钥加密私钥解密问题,欢迎使用 gorsa 扩展解决问题。

最后修改:2020 年 05 月 19 日 03 : 52 PM
如果觉得我的文章对你有用,请随意赞赏