非对称加密的RSA算法如何通过golang来实现?
上一篇文章我们讲了golang实现AES的方式,这里我们来讲一下RSA算法如何通过golang实现。需要注意的是rsa本身不支持大文件的加密,我们需要分段切割进行加解密。下面我们来看下代码。
package mainimport ("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 []bytechunks := 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() / 8raw, 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 mainimport ("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.PublicKeyderPkix, err := x509.MarshalPKIXPublicKey(publicKey)if err != nil {panic(err)}block = &pem.Block{Type: "PUBLIC KEY",Bytes: derPkix,}pubkey = pem.EncodeToMemory(block)return}
总结:
RSA加密算法是我们常用的加密方式之一,学习掌握是很重要的。
关于RSA加解密大文件需要分段加密,分段解密。
