vlambda博客
学习文章列表

非对称加密的RSA算法如何通过golang来实现?

上一篇文章我们讲了golang实现AES的方式,这里我们来讲一下RSA算法如何通过golang实现。需要注意的是rsa本身不支持大文件的加密,我们需要分段切割进行加解密。下面我们来看下代码。

package main
import ( "bytes" "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/base64" "encoding/hex" "encoding/pem" "fmt" "log")
func main() { data3, err := PublicEncrypt("sdfsdf") fmt.Println(data3, err) data4, err := PrivateDecrypt(data3) fmt.Println(data4, err)
data, err := RsaEncrypt("zxxx") fmt.Println(data, err) data2, err := RsaDecrypt(data) fmt.Println(data2, err)}
var privateKeyData = "-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQC11jirOpqCVTH0hNQJMwFZ9v6winoar8gUsZIHYyKhe3lmD/Mq\n+nfXIPhrQqd+uzEWKu4td3kqzhAKB+h+L8bpq2y6o5p6+Fvn7pGgiu8P4qB8tZM8\nnMN5SqK3vht0qcgjZ4XqiwdDEisG+owTHyguIzHTDvJa7ryQ0Cbibb3GUQIDAQAB\nAoGAUEKI6tNIJaTzEsmaSaEwxIPn8QZ+VM8n0jJ6kTYpr/svH2SE4YCCavtLixR1\nl9OKHA3A6WKlocYogDTzYtc1xWkJMXsfQq9VK0EunBxTpOgSsUW1eVjgW26+xgCf\nPSqaE/M9JTwRXHLIT3SEonS9GE5sOTpZcrK6L/obCRA74BECQQDnr4qaG+dSElEc\nuWm4pHFpEZcmCC1fcSB+nR4sL7ZzuetwBNWOluvtkQwvoFuVb4JG9KoRw40l+bKu\n7uWFr3SNAkEAyOtw+X8FXXRR5xgkmaMG8O2/GsD4703LmLMfE1bRwwyltg8DC6fD\nNRdGH8yMRss4YfkttbJNtRtOl1r81VJB1QJAFHcYGibO1xwRGCV0pj+4WNyZ6l0c\njOq0QRrl2GdaiXxpxJpYtuCz9Gc0mVxj2p5f9p6UCz+nzyvwUa1+jsGB3QJATn4E\nZcQk0Wy27oQ1EDxrYsZOqWIIHl0TE/WuRzzct8mCF4zn0K7aiSwtfhDIIIQV49iX\n7erZhs5DNsgaDDCVfQJBAIavhMTuGVsq5ZISPYLgiqWbL2PI0kpQqWAdjgCA02XI\nHy1PtTmKCR3YHytmsDDZOlNMcaVFd/epzPxGriOpHIU=\n-----END RSA PRIVATE KEY-----"var publicKeyData = "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC11jirOpqCVTH0hNQJMwFZ9v6w\ninoar8gUsZIHYyKhe3lmD/Mq+nfXIPhrQqd+uzEWKu4td3kqzhAKB+h+L8bpq2y6\no5p6+Fvn7pGgiu8P4qB8tZM8nMN5SqK3vht0qcgjZ4XqiwdDEisG+owTHyguIzHT\nDvJa7ryQ0Cbibb3GUQIDAQAB\n-----END PUBLIC KEY-----"
//大文件切割函数func split(buf []byte, lim int) [][]byte { var chunk []byte chunks := make([][]byte, 0, len(buf)/lim+1) for len(buf) >= lim { chunk, buf = buf[:lim], buf[lim:] chunks = append(chunks, chunk) } if len(buf) > 0 { chunks = append(chunks, buf[:len(buf)]) } return chunks}
// 公钥加密,支持大文件方法func PublicEncrypt(data string) (string, error) { // 解码部分 block, rest := pem.Decode([]byte(publicKeyData)) fmt.Println("------", block, string(rest)) publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { log.Fatal("RsaEncrypt ParsePKIXPublicKey fail", err) return "", err } //断言格式 publicKey := publicKeyInterface.(*rsa.PublicKey) partLen := publicKey.N.BitLen()/8 - 11 //按照固定切割 chunks := split([]byte(data), partLen) buffer := bytes.NewBufferString("") for _, chunk := range chunks { //加密方法 bytes, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, chunk) if err != nil { return "", err } buffer.Write(bytes) } return base64.RawURLEncoding.EncodeToString(buffer.Bytes()), nil}
// 私钥解密,支持大文件方法func PrivateDecrypt(encrypted string) (string, error) { block, _ := pem.Decode([]byte(privateKeyData)) privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { log.Fatal("RsaDecrypt parse private key fail", err) return "", err } partLen := privateKey.N.BitLen() / 8 raw, err := base64.RawURLEncoding.DecodeString(encrypted) if err != nil { log.Fatal("DecodeString", err) return "", err } chunks := split([]byte(raw), partLen) buffer := bytes.NewBufferString("") for _, chunk := range chunks { //解密方法 decrypted, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, chunk) if err != nil { log.Fatal("err", err) return "", err } buffer.Write(decrypted) }
return buffer.String(), err}
// rsa加密,不支持大文件func RsaEncrypt(content string) (string, error) { plainText := []byte(content) // 解码部分 block, _ := pem.Decode([]byte(publicKeyData)) publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { log.Fatal("RsaEncrypt ParsePKIXPublicKey fail", err) return "", err } publicKey := publicKeyInterface.(*rsa.PublicKey) cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plainText) if err != nil { log.Fatal("RsaEncrypt EncryptPKCS1v15 fail", err) return "", err } return hex.EncodeToString(cipherText), nil}
// rsa解密,不支持大文件func RsaDecrypt(cryptContent string) (string, error) { // 私匙解密 block, _ := pem.Decode([]byte(privateKeyData)) privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { log.Fatal("RsaDecrypt parse private key fail", err) return "", err } cryptText, err := hex.DecodeString(cryptContent) if err != nil { log.Fatal("RsaDecrypt cryptContent decode string fail", err) return "", err } plainText, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, cryptText) if err != nil { log.Fatal("RsaDecrypt DecryptPKCS1v15 fail", err) return "", err } return string(plainText), nil}

上面的代码是可以直接执行生成结果的,如果对公钥和私钥的生成,我们看这段代码:

package main
import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/pem" "fmt")
func main() { privateKey, publickKey := GenRsaKey() fmt.Println(string(privateKey), string(publickKey))}
//RSA公钥私钥产生func GenRsaKey() (prvkey, pubkey []byte) { // 生成私钥文件 privateKey, err := rsa.GenerateKey(rand.Reader, 1024) if err != nil { panic(err) } derStream := x509.MarshalPKCS1PrivateKey(privateKey) block := &pem.Block{ Type: "RSA PRIVATE KEY", Bytes: derStream, } prvkey = pem.EncodeToMemory(block) publicKey := &privateKey.PublicKey derPkix, err := x509.MarshalPKIXPublicKey(publicKey) if err != nil { panic(err) } block = &pem.Block{ Type: "PUBLIC KEY", Bytes: derPkix, } pubkey = pem.EncodeToMemory(block) return}


总结:

RSA加密算法是我们常用的加密方式之一,学习掌握是很重要的。

关于RSA加解密大文件需要分段加密,分段解密。