首页 > 其他分享 >go语言RSA分段加密V2501

go语言RSA分段加密V2501

时间:2025-01-09 13:55:38浏览次数:1  
标签:私钥 err nil V2501 RSA ----- go return

go语言RSA分段加密V2501,GOLANG,RSA/ECB/PKCS1Padding。

 

加密解析:

//假设私钥长度为1024, 1024/8-11=117。
//如果明文的长度小于117,直接全加密,然后转base64。(data.Length <= maxBlockSize)
//如果明文长度大于117,则每117分一段加密,

publicKey.Size()刚好是(私钥长度/8)。privateKey.Size() 也一样。

 

解密解析:

//假设私钥长度为1024, 1024/8 =128。
//如果明文的长度小于 128,直接全解密。(data.Length <= maxBlockSize)
//如果明文长度大于 128,则每 128 分一段解密,

 

用“支付宝开放平台开发助手”生成一组公私钥:

PKCS8私钥:

MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAMz0Czg6QUtTISa2pUkloeQB/TEpHdqrfyroWpKLW9B/LWFSOGH9nyTk1pPZaeadyEZQ6gay/C0pUAetLraq9bMA/Luxq68b87uG7WX7dKytEO2/87qGpGMRs97H+GlkzWil2QO2KK4cHnAcVicPsmi5aZ72U0BWJFyPhtd+qdmrAgMBAAECgYEAvW67iAbgHt0BASVD9C3iSjpEaVHVlC165o/IVzaTcEx8Bz3Ve0zN8W3JnvIO3ebsG4HiLLr2Nk++9rltOc0eNeGMv7F1e/OFot1wN0ON6s1g4bYh1z5Uz8FcYiMWcqHHICrx+oSFeK9x+I2Zge7enQXcsVnqEhm77ZE5YczSryECQQD9nB58e5efYchF+cYbmURioX18cUMuhQbB9Aq2N55cd689Lg35KZqT8JQTp/8tQSdCJG8d2nU8VKspUKTEAuaDAkEAzuKIIoc9PVJvy90LhIPA9c1S8BPCI7EMCaTZqJ5o3VaR2dqvUZDGX7kL3kYkQ+n7mq3KIECvkEFzA+FOP96XuQJBAJQTKHW0T/YeSKoayUHp/lS8R6F2HCy4PRbXn71+wfbpZqcJEd2OHhQM3tiPOV258esbjMlYeSUNppZL4LgVnXMCQQC7Lvs9Ql+GPDAqo7ToEM1lmICR906QPIBHuX+1sJ3wpYMROWumwPa7ZRH36j6ls+6R5OwcgmpWeuE1gYTrBNsBAkEAn2pEtAljX1foQff6CLozYg/J6J9RmVFcJ6qz0LX3052qNFBQYw8CMHB7VkVNzsDIDC8LX5uP2pzTrdPLew+pPA==

与之匹配的 PKCS1 私钥,用助手转换的:

MIICXwIBAAKBgQDM9As4OkFLUyEmtqVJJaHkAf0xKR3aq38q6FqSi1vQfy1hUjhh/Z8k5NaT2WnmnchGUOoGsvwtKVAHrS62qvWzAPy7sauvG/O7hu1l+3SsrRDtv/O6hqRjEbPex/hpZM1opdkDtiiuHB5wHFYnD7JouWme9lNAViRcj4bXfqnZqwIDAQABAoGBAL1uu4gG4B7dAQElQ/Qt4ko6RGlR1ZQteuaPyFc2k3BMfAc91XtMzfFtyZ7yDt3m7BuB4iy69jZPvva5bTnNHjXhjL+xdXvzhaLdcDdDjerNYOG2Idc+VM/BXGIjFnKhxyAq8fqEhXivcfiNmYHu3p0F3LFZ6hIZu+2ROWHM0q8hAkEA/ZwefHuXn2HIRfnGG5lEYqF9fHFDLoUGwfQKtjeeXHevPS4N+Smak/CUE6f/LUEnQiRvHdp1PFSrKVCkxALmgwJBAM7iiCKHPT1Sb8vdC4SDwPXNUvATwiOxDAmk2aieaN1Wkdnar1GQxl+5C95GJEPp+5qtyiBAr5BBcwPhTj/el7kCQQCUEyh1tE/2HkiqGslB6f5UvEehdhwsuD0W15+9fsH26WanCRHdjh4UDN7YjzldufHrG4zJWHklDaaWS+C4FZ1zAkEAuy77PUJfhjwwKqO06BDNZZiAkfdOkDyAR7l/tbCd8KWDETlrpsD2u2UR9+o+pbPukeTsHIJqVnrhNYGE6wTbAQJBAJ9qRLQJY19X6EH3+gi6M2IPyeifUZlRXCeqs9C199OdqjRQUGMPAjBwe1ZFTc7AyAwvC1+bj9qc063Ty3sPqTw=

与之匹配的公钥:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDM9As4OkFLUyEmtqVJJaHkAf0xKR3aq38q6FqSi1vQfy1hUjhh/Z8k5NaT2WnmnchGUOoGsvwtKVAHrS62qvWzAPy7sauvG/O7hu1l+3SsrRDtv/O6hqRjEbPex/hpZM1opdkDtiiuHB5wHFYnD7JouWme9lNAViRcj4bXfqnZqwIDAQAB

 

核心重点是拿到 GO 的 *rsa.PublicKey 、*rsa.PrivateKey 2个对象。

注意:和C#一样,公钥要还原为完整格式。

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDM9As4OkFLUyEmtqVJJaHkAf0x
KR3aq38q6FqSi1vQfy1hUjhh/Z8k5NaT2WnmnchGUOoGsvwtKVAHrS62qvWzAPy7
sauvG/O7hu1l+3SsrRDtv/O6hqRjEbPex/hpZM1opdkDtiiuHB5wHFYnD7JouWme
9lNAViRcj4bXfqnZqwIDAQAB
-----END PUBLIC KEY-----

否则转成  *rsa.PublicKey  时会报错。

 

代码:

package main

import (
    "bytes"
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "encoding/base64"
    "encoding/pem"
    "fmt"
    "log"
    "strings"
)

func main() {
    strOrg := "This is a very long message that needs to be encrypted using RSA in multiple parts.中华人民共和国2025-01-07.This is a very long message that needs to be encrypted using RSA in multiple parts.中华人民共和国2025-01-07This is a very long message that needs to be encrypted using RSA in multiple parts.中华人民共和国2025-01-07。测试123abc"
    log.Println("待加密的字符串:", strOrg)
    strPrivateKeyPKCS1 := "MIICXwIBAAKBgQDM9As4OkFLUyEmtqVJJaHkAf0xKR3aq38q6FqSi1vQfy1hUjhh/Z8k5NaT2WnmnchGUOoGsvwtKVAHrS62qvWzAPy7sauvG/O7hu1l+3SsrRDtv/O6hqRjEbPex/hpZM1opdkDtiiuHB5wHFYnD7JouWme9lNAViRcj4bXfqnZqwIDAQABAoGBAL1uu4gG4B7dAQElQ/Qt4ko6RGlR1ZQteuaPyFc2k3BMfAc91XtMzfFtyZ7yDt3m7BuB4iy69jZPvva5bTnNHjXhjL+xdXvzhaLdcDdDjerNYOG2Idc+VM/BXGIjFnKhxyAq8fqEhXivcfiNmYHu3p0F3LFZ6hIZu+2ROWHM0q8hAkEA/ZwefHuXn2HIRfnGG5lEYqF9fHFDLoUGwfQKtjeeXHevPS4N+Smak/CUE6f/LUEnQiRvHdp1PFSrKVCkxALmgwJBAM7iiCKHPT1Sb8vdC4SDwPXNUvATwiOxDAmk2aieaN1Wkdnar1GQxl+5C95GJEPp+5qtyiBAr5BBcwPhTj/el7kCQQCUEyh1tE/2HkiqGslB6f5UvEehdhwsuD0W15+9fsH26WanCRHdjh4UDN7YjzldufHrG4zJWHklDaaWS+C4FZ1zAkEAuy77PUJfhjwwKqO06BDNZZiAkfdOkDyAR7l/tbCd8KWDETlrpsD2u2UR9+o+pbPukeTsHIJqVnrhNYGE6wTbAQJBAJ9qRLQJY19X6EH3+gi6M2IPyeifUZlRXCeqs9C199OdqjRQUGMPAjBwe1ZFTc7AyAwvC1+bj9qc063Ty3sPqTw="
    strPublicKey := "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDM9As4OkFLUyEmtqVJJaHkAf0xKR3aq38q6FqSi1vQfy1hUjhh/Z8k5NaT2WnmnchGUOoGsvwtKVAHrS62qvWzAPy7sauvG/O7hu1l+3SsrRDtv/O6hqRjEbPex/hpZM1opdkDtiiuHB5wHFYnD7JouWme9lNAViRcj4bXfqnZqwIDAQAB"

    //和C#一样,公钥要还原为完整格式。
    strPublicKey2 := PubKeyFullToPure(strPublicKey)    //格式化为纯字符串
    strPublicKey2 = PubKeyPureStrToFull(strPublicKey2) //还原为完整格式
    fmt.Println("公钥完整格式:\n", strPublicKey2)
    rsaPub, err := convertPEMToRSAPublicKey(strPublicKey2) //从字符串转换为“公钥对象”
    if err != nil {
        log.Println("转换公钥时出错:", err)
        return
    }
    log.Println("私钥长度:", rsaPub.N.BitLen())

    privateKeyBytes, _ := base64.StdEncoding.DecodeString(strPrivateKeyPKCS1)
    privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBytes)
    if err != nil {
        log.Println("转换私钥时出错:", err)
        return
    }

    bData, err := RsaEncryptBlock([]byte(strOrg), rsaPub)
    if err != nil {
        log.Println("加密时出错:", err)
    }

    encryptedString := base64.StdEncoding.EncodeToString(bData)
    fmt.Println("密文:")
    fmt.Println(encryptedString)
    byteDecode, _ := base64.StdEncoding.DecodeString(encryptedString)
    dData, err2 := RsaDecryptBlock(byteDecode, privateKey)
    if err2 == nil {
        fmt.Println("解密出的内容:")
        fmt.Println(string(dData))
    } else {
        log.Println("解密时出错:", err2)
    }

}

// 格式化为纯字符串
func PubKeyFullToPure(pubKeyStr string) string {
    a := strings.ReplaceAll(pubKeyStr, "-----BEGIN PUBLIC KEY-----", "")
    a = strings.ReplaceAll(a, "-----END PUBLIC KEY-----", "")
    a = strings.ReplaceAll(a, "\n", "")
    return a
}

// 将 PEM 格式的公钥字符串转换为 rsa.PublicKey
func convertPEMToRSAPublicKey(pemStr string) (*rsa.PublicKey, error) {
    // 解码 PEM 格式的字符串
    block, _ := pem.Decode([]byte(pemStr))
    if block == nil || block.Type != "PUBLIC KEY" {
        return nil, fmt.Errorf("failed to decode PEM block containing the public key")
    }

    // 解析公钥
    pub, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
        return nil, err
    }

    // 类型断言为 rsa.PublicKey
    rsaPub, ok := pub.(*rsa.PublicKey)
    if !ok {
        return nil, fmt.Errorf("not a valid RSA public key")
    }

    return rsaPub, nil
}

// 还原为完整格式
func PubKeyPureStrToFull(pubKeyStr string) string {
    // 获取公钥字符串的长度
    nKeyLen := len(pubKeyStr)
    var finalBuffer bytes.Buffer
    finalBuffer.WriteString("-----BEGIN PUBLIC KEY-----\n")
    // 由于我们已经知道要在每 64 个字符后插入换行符,我们可以直接这样做:
    for i := 0; i < nKeyLen; i += 64 {
        end := i + 64
        if end > nKeyLen {
            end = nKeyLen
        }
        currLine := pubKeyStr[i:end]
        finalBuffer.WriteString(currLine)
        finalBuffer.WriteString("\n")
    }
    // 写入尾部
    finalBuffer.WriteString("-----END PUBLIC KEY-----\n")
    // 获取最终的字符串
    allKeyStr := finalBuffer.String()
    return allKeyStr
}

/*
*
公钥加密-分段
*/
func RsaEncryptBlock(src []byte, publicKey *rsa.PublicKey) (bytesEncrypt []byte, err error) {

    keySize, srcSize := publicKey.Size(), len(src)
    //单次加密的长度 私钥长度/8 -11 。私钥长度,如:1024、2048。 publicKey.Size()刚好是(私钥长度/8)。
    offSet, blockSize := 0, keySize-11
    buffer := bytes.Buffer{}
    for offSet < srcSize {
        endIndex := offSet + blockSize
        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 RsaDecryptBlock(src []byte, privateKey *rsa.PrivateKey) (bytesDecrypt []byte, err error) {

    //分段解密,单块长度是(私钥长度/8),privateKey.Size()正好是(私钥长度/8)。
    blockSize := privateKey.Size()
    srcSize := len(src)
    // log.Println("密钥长度:", blockSize, "\t密文长度:\t", srcSize)
    var offSet = 0
    var buffer = bytes.Buffer{}
    for offSet < srcSize {
        endIndex := offSet + blockSize
        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
}

 

 运行结果:

2025/01/09 13:39:51 待加密的字符串: This is a very long message that needs to be encrypted using RSA in multiple parts.中华人民共和国2025-01-07.This is a very long message that needs to be encrypted using RSA in multiple parts.中华人民共和国2025-01-07This is a very long message that needs to be encrypted using RSA in multiple parts.中华人民共和国2025-01-07。测试123abc
2025/01/09 13:39:51 私钥长度: 1024
密文:
DMUH3zB2Eis9KT7GQ8jDFuJ2ZOZNLa/fpDzZl3oBsIVwH8uKDY8whwbYJzjXcL5EMhqpsHUNe+O8r7lN3JjYwsQlXAdRxALHvwptvW4Li8Qq5bn/RngqWiGt4AOgBK/Qm/pBhZIw1j0RTDQoZqmpNp2Rybtjw1aSoKJAvEbuGF+J7NYV8Nosl64+ZWDNDJNIhV08XAU8zw2qDd8ixGLpDd4mtrCArJ+NiHOfz7KZL2H9y23FOWnafwvdGJtWpx/R3aTjIv80INCW1xEG78qPUZx62+oHfjORwY5oTSibi49eiEW6kuDP2EQbW90130ZDkSLM6uak21cgvkDb58RzNYFonIi2Q7znzPpKF8eKWZ5fjyC7+v8kdBgqg0e6dhEi6uReO30ibT+/cl5kiQnywLbB5NALwLotmTmonPkYYGGkJF2vSZ7hy/HUgiZ506AVN/U5gDVQC3ffpd76LOD1quLnkYoRdJQ0MgB0tPj8Q+4yaTeUgdOC3TpKrdxf3pvPcyJxXBJFJ5gA+enV1iTzZBrxi12uTsF4g9f0npxRTV7Gr8GitvBeTekRnK+i8FCFa3MT9IFO9c4D/m7a8PCNWNMYcKl6SMX+F3bNYiiPR3nKHxi7o/3hZTHBggCqPpILR3P/VfnUc/y51KpCICaH0YrfOHrTiMzpVZGxitn1Uv8=
解密出的内容:
This is a very long message that needs to be encrypted using RSA in multiple parts.中华人民共和国2025-01-07.This is a very long message that needs to be encrypted using RSA in multiple parts.中华人民共和国2025-01-07This is a very long message that needs to be encrypted using RSA in multiple parts.中华人民共和国2025-01-07。测试123abc

 

--

标签:私钥,err,nil,V2501,RSA,-----,go,return
From: https://www.cnblogs.com/runliuv/p/18662005

相关文章

  • 2025-01-09:清除数字。用go语言,给定一个字符串 s ,你的任务是执行以下操作,直到字符串中
    2025-01-09:清除数字。用go语言,给定一个字符串s,你的任务是执行以下操作,直到字符串中不再有数字字符:删除第一个出现的数字字符,以及它左侧最近的非数字字符。最终,你需要返回经过操作后剩下的字符串。1<=s.length<=100。s只包含小写英文字母和数字字符。输入保证所......
  • Python+Django鹿幸公司员工在线餐饮管理系统的设计与实现(Pycharm Flask Django Vue m
    收藏关注不迷路,防止下次找不到!文章末尾有惊喜项目介绍Python+Django鹿幸公司员工在线餐饮管理系统的设计与实现(PycharmFlaskDjangoVuemysql)项目展示详细视频演示请联系我获取更详细的演示视频,相识就是缘分,欢迎合作!!!所用技术栈前端vue.js框......
  • Python+Django高校网上缴费综合务系统(Pycharm Flask Django Vue mysql)
    收藏关注不迷路,防止下次找不到!文章末尾有惊喜项目介绍Python+Django高校网上缴费综合务系统(PycharmFlaskDjangoVuemysql)项目展示详细视频演示请联系我获取更详细的演示视频,相识就是缘分,欢迎合作!!!所用技术栈前端vue.js框架支持:django数据库:mysql5.7数......
  • rsarsa-给定pqe求私钥对密文解密
    题目:Mathiscool!UsetheRSAalgorithmtodecodethesecretmessage,c,p,q,andeareparametersfortheRSAalgorithm.p=964842302901051567659055174001042653494573763923573980064398935203985250729849139956103500916342705037010757073363335091169128......
  • python+django/flask的社区汽车共享平台java+nodejs+php-计算机毕业设计
    目录技术栈和环境说明具体实现截图预期达到的目标系统设计详细视频演示技术路线解决的思路性能/安全/负载方面可行性分析论证python-flask核心代码部分展示python-django核心代码部分展示研究方法感恩大学老师和同学源码获取技术栈和环境说明本系统以Python开发语言......
  • python+django/flask的油田物料管理系统java+nodejs+php-计算机毕业设计
    目录技术栈和环境说明具体实现截图预期达到的目标系统设计详细视频演示技术路线解决的思路性能/安全/负载方面可行性分析论证python-flask核心代码部分展示python-django核心代码部分展示研究方法感恩大学老师和同学源码获取技术栈和环境说明本系统以Python开发语言......
  • python+django/flask的教学资料管理系统java+nodejs+php-计算机毕业设计
    目录技术栈和环境说明具体实现截图预期达到的目标系统设计详细视频演示技术路线解决的思路性能/安全/负载方面可行性分析论证python-flask核心代码部分展示python-django核心代码部分展示研究方法感恩大学老师和同学源码获取技术栈和环境说明本系统以Python开发语言......
  • mongodb windows zip安装并服务自启动
    1.下载并解压。2.新建文件/文件夹data/db目录logs/mongod.log文件conf/mongod.conf文件3.编辑conf/mongod.conf文件systemLog:destination:filelogAppend:truepath:F:/mongodb-win32-x86_64-windows-6.0.20-rc3/logs/mongod.logstorage:dbPath:F:/m......
  • Godot引擎开发:UI和用户交互_输入处理
    输入处理在Godot引擎开发中,输入处理是实现用户与游戏交互的关键步骤。通过处理用户输入,可以实现角色移动、攻击、跳跃等操作,从而增强游戏的可玩性和互动性。本节将详细介绍Godot引擎中的输入处理机制,包括键盘输入、鼠标输入、触摸输入和游戏手柄输入,并提供具体的代码示例。......
  • Godot引擎开发:UI和用户交互_鼠标和键盘输入处理
    鼠标和键盘输入处理在上一节中,我们介绍了如何在Godot引擎中创建和管理UI元素。接下来,我们将深入探讨如何处理鼠标和键盘输入,以实现用户与UI的交互。用户输入是任何游戏开发中不可或缺的一部分,特别是在动作游戏中,玩家需要通过键盘和鼠标进行快速、精确的操作。本节将详细介......