前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RSA 加密算法与 golang 代码实现

RSA 加密算法与 golang 代码实现

原创
作者头像
_春华秋实
发布2023-11-27 22:25:20
2400
发布2023-11-27 22:25:20
举报
文章被收录于专栏:_春华秋实_春华秋实

最近参与借贷业务的开发,接口传输过程中需要使用 RSA 加密算法对请求和返回进行加密,所以写了这篇博客。主要介绍 RSA 的基础知识和 golang 使用例子

概念介绍

RSA 是一个非对称加密算法,是目前使用最广的数据安全加密算法之一。

RSA 通过生成公钥和与之对应的私钥来进行加解密的,公钥与私钥一一对应。

虽然私钥可以用于加密数据,但因为公钥是对外的,所以加密数据的意义不大,因为知道公钥的都能解密,所以 RSA 常见用法有下面两种

  • 公钥加密数据,私钥解密数据
  • 私钥则用户签名,公钥用于验签

密钥格式

  • PKCS#8 密钥格式,多用于JAVA、PHP程序加解密中,为目前用的比较多的密钥、证书格式;
  • PKCS#1 密钥格式,多用于JS等其它程序加解密,属于比较老的格式标准。

PKCS#1 和 PKCS#8 的主要区别,从本质上说,PKCS#8 格式增加验证数据段,保证密钥正确性。

RSA 加解密(PKCS#8 格式)

RSA非对称加密算法,被加密的数据长度,需要短于公私钥的长度,否则会加密失败。所以针对比较长的数据一般采用分段加解密

代码语言:javascript
复制
// RsaPubEncrypt 使用公钥分段加密数据
func RsaPubEncrypt(data []byte, publicKeyPEM string) (bytesEncrypt string, err error) {
    // 解码公钥
    publicKeyPEM, err = ReadFile(publicKeyPEM)
    block, _ := pem.Decode([]byte(publicKeyPEM))
    if block == nil {
       return "", fmt.Errorf("failed to parse public key")
    }

    publicKey, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
       return
    }
    keySize, srcSize := publicKey.(*rsa.PublicKey).Size(), len(data)
    //单次加密的长度需要减掉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.(*rsa.PublicKey), data[offSet:endIndex])
       if err != nil {
          return "", err
       }
       buffer.Write(bytesOnce)
       offSet = endIndex
    }
    bytesEncrypt = base64.StdEncoding.EncodeToString(buffer.Bytes())

    return
}


// RsaPriDecrypt 使用私钥分段解密数据
func RsaPriDecrypt(encryptedData, privateKeyPEM string) (bytesDecrypt string, err error) {
    privateKeyPEM, err = ReadFile(privateKeyPEM)
    block, _ := pem.Decode([]byte(privateKeyPEM))
    if block == nil {
       return "", fmt.Errorf("failed to parse private key")
    }

    privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
    if err != nil {
       return
    }

    // 解码加密的数据
    encrypted, err := base64.StdEncoding.DecodeString(encryptedData)
    if err != nil {
       return "", fmt.Errorf("failed to decode base64: %v", err)
    }

    keySize := privateKey.(*rsa.PrivateKey).Size()
    srcSize := len(encrypted)
    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.(*rsa.PrivateKey), encrypted[offSet:endIndex])
       if err != nil {
          return "", err
       }
       buffer.Write(bytesOnce)
       offSet = endIndex
    }
    bytesDecrypt = buffer.String()
    return
}

RSA 验签(PKCS#8 格式)

代码语言:javascript
复制
// GetSign RSA生成签名
func GetSign(signString string, priKey string) (string, error) {
    priKey, err := ReadFile(priKey)
    block, _ := pem.Decode([]byte(priKey))
    if block == nil {
       return "", fmt.Errorf("Failed to decode PEM block")
    }

    privKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
    if err != nil {
       return "", err
    }

    h := sha1.New()
    h.Write([]byte(signString))
    hashed := h.Sum(nil)

    signature, err := rsa.SignPKCS1v15(rand.Reader, privKey.(*rsa.PrivateKey), crypto.SHA1, hashed)
    if err != nil {
       return "", err
    }

    return base64.StdEncoding.EncodeToString(signature), nil
}

// CheckSign RSA校验
func CheckSign(pubKey string, sign string, toSign string) (bool, error) {
    pubKey, err := ReadFile(pubKey)
    if err != nil {
       return false, err
    }
    block, _ := pem.Decode([]byte(pubKey))
    pub, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
       return false, err
    }

    signature, _ := base64.StdEncoding.DecodeString(sign)

    h := sha1.New()
    h.Write([]byte(toSign))
    hashed := h.Sum(nil)

    err = rsa.VerifyPKCS1v15(pub.(*rsa.PublicKey), crypto.SHA1, hashed, signature)
    if err != nil {
       return false, err
    }

    return true, nil
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

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