前言
在尝试RSA加/解密的时候,发现go标准库中仅有"公钥加密,私钥解密",而没有“私钥加密、公钥解密”。经过考虑,我认为GO的开发者是故意这样设计的,原因如下:
- 非对称加密相比对称加密的好处就是:私钥自己保留,公钥公布出去,公钥加密后只有私钥能解开,私钥加密后只有公钥能解开。
- 如果仅有一对密钥,与对称加密区别就不大了。
假如你是服务提供方,使用私钥进行加密后,接入方使用你提供的公钥进行解密,一旦这个公钥泄漏,带来的后果和对称加密密钥泄漏是一样的。只有双方互换公钥(均使用对方公钥加密,己方私钥解密),才能充分发挥非对称加密的优势。
当然,有第三方库支持“私钥加密、公钥解密”的,有兴趣的伙伴可自行百度。
RSA加密时,明文长度>(密钥长度-padding长度)时需要进行分段。PKCS1填充长度为11
main_test.go
package main
import (
"demos/kris/security"
"encoding/base64"
"encoding/hex"
"log"
)
func main() {
var mingwen = "我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅"
md5 := security.MD5([]byte(mingwen))
//MD5打印为16进制字符串
log.Println(hex.EncodeToString(md5))
//RSA的内容使用base64打印
privateKey, publicKey, _ := security.GenRSAKey(1024)
log.Println("rsa私钥:\t", base64.StdEncoding.EncodeToString(privateKey))
log.Println("rsa公钥:\t", base64.StdEncoding.EncodeToString(publicKey))
miwen, err := security.RsaEncryptBlock([]byte(mingwen), publicKey)
if err != nil {
log.Fatal(err)
}
log.Println("加密后:\t", base64.StdEncoding.EncodeToString(miwen))
jiemi, err := security.RsaDecryptBlock(miwen, privateKey)
if err != nil {
log.Fatal(err)
}
log.Println("解密后:\t", string(jiemi))
}
md5.go
package security
import (
"crypto/md5"
)
func MD5(src []byte) []byte {
hash := md5.New()
hash.Write(src)
return hash.Sum(nil)
}
rsa.go
代码中使用[]byte传递明文、密文、密钥。提供普通加解密、分段加解密,生成密钥对的功能。
package security
import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"log"
)
/**
生成RSA密钥对
*/
func GenRSAKey(size int) (privateKeyBytes, publicKeyBytes []byte, err error) {
//生成密钥
privateKey, err := rsa.GenerateKey(rand.Reader, size)
if err != nil {
return
}
privateKeyBytes = x509.MarshalPKCS1PrivateKey(privateKey)
publicKeyBytes = x509.MarshalPKCS1PublicKey(&privateKey.PublicKey)
return
}
/**
公钥加密
*/
func RsaEncrypt(src, publicKeyByte []byte) (bytes []byte, err error) {
publicKey, err := x509.ParsePKCS1PublicKey(publicKeyByte)
if err != nil {
return
}
return rsa.EncryptPKCS1v15(rand.Reader, publicKey, src)
}
/**
公钥加密-分段
*/
func RsaEncryptBlock(src, publicKeyByte []byte) (bytesEncrypt []byte, err error) {
publicKey, err := x509.ParsePKCS1PublicKey(publicKeyByte)
if err != nil {
return
}
keySize, srcSize := publicKey.Size(), len(src)
log.Println("密钥长度:", keySize, "\t明文长度:\t", srcSize)
//单次加密的长度需要减掉padding的长度,PKCS1为11
offSet, once := 0, keySize-11
buffer := bytes.Buffer{}
for offSet < srcSize {
endIndex := offSet + once
if endIndex > srcSize {
endIndex = srcSize
}
// 加密一部分
bytesOnce, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, src[offSet:endIndex])
if err != nil {
return nil, err
}
buffer.Write(bytesOnce)
offSet = endIndex
}
bytesEncrypt = buffer.Bytes()
return
}
/**
私钥解密
*/
func RsaDecrypt(src, privateKeyBytes []byte) (bytesDecrypt []byte, err error) {
privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBytes)
if err != nil {
return
}
return rsa.DecryptPKCS1v15(rand.Reader, privateKey, src)
}
/**
私钥解密-分段
*/
func RsaDecryptBlock(src, privateKeyBytes []byte) (bytesDecrypt []byte, err error) {
privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBytes)
if err != nil {
return
}
keySize := privateKey.Size()
srcSize := len(src)
log.Println("密钥长度:", keySize, "\t密文长度:\t", srcSize)
var offSet = 0
var buffer = bytes.Buffer{}
for offSet < srcSize {
endIndex := offSet + keySize
if endIndex > srcSize {
endIndex = srcSize
}
bytesOnce, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, src[offSet:endIndex])
if err != nil {
return nil, err
}
buffer.Write(bytesOnce)
offSet = endIndex
}
bytesDecrypt = buffer.Bytes()
return
}
运行结果:
2018/12/29 15:30:52 d97dda9fb100759916be5c32f9daaa3a
2018/12/29 15:30:52 rsa私钥: MIICXAIBAAKBgQCzTAvxAijkbdAM63NM+UmWv7Yx11/fK2FkX1svklK8BBk9XGBCkg4iePEUqhR9YUljRfEQI/EAlc5wG84w+FTnNqdHa95KK+fALQvKqxAU3976RqH2j4r28WUUQxPZjWfEeIjb5XfG5DjNFwQbJXmrymaHeDNsKg5a0LggGHmmlwIDAQABAoGAAddZFAuCof3isg9E6thwggTL+S0OBfurD13PUOi+wsGEBNZLAsP/MylsyFqKxVLXbxaLyC+mTOw853fRoT0bmhPVbma5z5BLFE8yExPOhEOJJU87WA4AXLMdCCZ6+XXs9JhTfT0UPgTIk7l5OLYxmclyTjoxlZCe9gF75n31HxECQQDOtwv5fiOzM8mNoFa82YmnGyHVqDFoXw2kFLTIZd+cqSiS6kN0WsNO4DbslqD5Xr+ENaDmWDWTeRmHY0cwZlI5AkEA3guH2D0LbKqa2FTn/lf9sraXQGsEKm+72ut4Y88XpgfTU4TlEE/y1ipd2W0GwdvJQrt8QIZ6mW0TeIj4Jvx/TwJBAK6EaS6kaL1lDldsM25Sdd1HkcQQsE2+WgTZmlrJbwSS53dJIdO8wMD5mEUbUiHV9PhIUmPFus2bYosjrLlW2TkCQBTcRnXlPkaGPKfoSidWAuqgRtNxemG2P5LQnm3aDeG2SH9HM/H1YN4H+usrWAAsctsHHCQ/vhLd8X9Ydt/KxvcCQHDFGYvFnjnhNW7fGicjYkM3wLrzx+Fy38PDZX+yYNfUxlQcGqru6h3PtabRAu3/pqKX9/HWhgCiIj4jRNFSn3Q=
2018/12/29 15:30:52 rsa公钥: MIGJAoGBALNMC/ECKORt0Azrc0z5SZa/tjHXX98rYWRfWy+SUrwEGT1cYEKSDiJ48RSqFH1hSWNF8RAj8QCVznAbzjD4VOc2p0dr3kor58AtC8qrEBTf3vpGofaPivbxZRRDE9mNZ8R4iNvld8bkOM0XBBsleavKZod4M2wqDlrQuCAYeaaXAgMBAAE=
2018/12/29 15:30:52 密钥长度: 128 明文长度: 288
2018/12/29 15:30:52 加密后: MTDi/0SZ3iy7RpWDX4yotnldqZMlyjoCfXpu1W/LjmNwV8TB9cm0upy8TLp9N2aULq2jw2OgTzwihCjsd3qQVpjCS5BkYWBi9dBQoRMdV5pqq/RS9Ydb0rvx9dL9yWxLRjfAabGq3eJPI9NyGrd+aMSmQfN7Mcnd7Vzrch94DGoeIIW+qzHk8tKmiV01xvx1m+jMxUZAfave7AT35HzNiJBr7OhXugFyYfOay2A+BCi8mBSH+kcbzsnyFc7XPiaOeZZY6Jsh8PPznZpbS8A2IK50CYI8FmmadP13yk0X5KF3PZK2rEVAQh9zbDJmme8oW4TCJvg7E3y+pzTVNKCeQ50Fv9GGLNrQRemd8rEkKH2sTn6lvAEnJlD3bTOxbGQfsDLELEtcl8ua6pjxU9dwdU7Y/Ednm7x/3FcvtCzG42rMrZcZhYm0FoKwLnW5I9TSrQGuJDOH5hSvA6ZZxSTeBgKjRqInAyf9Vx48wdVv04WS/LHGB8nnO3XLHvO0C4sf
2018/12/29 15:30:52 密钥长度: 128 密文长度: 384
2018/12/29 15:30:52 解密后: 我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅