前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >非对称加密的RSA算法如何通过golang来实现?

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

作者头像
公众号-利志分享
发布2022-04-25 09:22:03
5630
发布2022-04-25 09:22:03
举报
文章被收录于专栏:利志分享

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

代码语言:javascript
复制
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
}

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

代码语言:javascript
复制
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加解密大文件需要分段加密,分段解密。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-07-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 利志分享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档