GO实现MD5和RSA分段加解密

前言

在尝试RSA加/解密的时候,发现go标准库中仅有"公钥加密,私钥解密",而没有“私钥加密、公钥解密”。经过考虑,我认为GO的开发者是故意这样设计的,原因如下:

  1. 非对称加密相比对称加密的好处就是:私钥自己保留,公钥公布出去,公钥加密后只有私钥能解开,私钥加密后只有公钥能解开。
  2. 如果仅有一对密钥,与对称加密区别就不大了。
    假如你是服务提供方,使用私钥进行加密后,接入方使用你提供的公钥进行解密,一旦这个公钥泄漏,带来的后果和对称加密密钥泄漏是一样的。只有双方互换公钥(均使用对方公钥加密,己方私钥解密),才能充分发挥非对称加密的优势。

当然,有第三方库支持“私钥加密、公钥解密”的,有兴趣的伙伴可自行百度。
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 解密后:	 我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅我不管我就是最帅

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值