用Java的公钥进行RSA解密操作
在IT行业这个发展更新速度很快的行业,只有不停止的学习,才不会被行业所淘汰。如果你是Golang学习者,那么本文《用Java的公钥进行RSA解密操作》就很适合你!本篇内容主要包括##content_title##,希望对大家的知识积累有所帮助,助力实战开发!
提供商拥有此示例 java 代码,可使用公钥解密 rsa。
public static byte[] decryptbypublickey(byte[] encrypteddata, string publickey) throws exception { byte[] keybytes = base64.decodebase64(publickey); x509encodedkeyspec x509keyspec = new x509encodedkeyspec(keybytes); keyfactory keyfactory = keyfactory.getinstance("rsa"); key publick = keyfactory.generatepublic(x509keyspec); cipher cipher = cipher.getinstance(keyfactory.getalgorithm()); cipher.init(cipher.decrypt_mode, publick); int inputlen = encrypteddata.length; bytearrayoutputstream out = new bytearrayoutputstream(); int offset = 0; byte[] cache; int i = 0; while (inputlen - offset > 0) { if (inputlen - offset >(2048/8)) { cache = cipher.dofinal(encrypteddata, offset,(2048/8)); } else { cache = cipher.dofinal(encrypteddata, offset, inputlen - offset); } out.write(cache, 0, cache.length); i++; offset = i *(2048/8); } byte[] decrypteddata = out.tobytearray(); out.close(); return decrypteddata; }
我尝试用 go 编写等效的代码,但没有成功。
base64decodebyteskey, err := base64.stdencoding.decodestring(os.getenv("pubkey")) if err != nil { log(logref, " error reading pubkey", err) } pubkey, err := x509.parsepkcs1privatekey(base64decodebyteskey) c := new(big.int) m := new(big.int) m.setbytes(data) e := big.newint(int64(pubkey.e)) c.exp(m, e, pubkey.n) out := c.bytes() skip := 0 log(" payload size:--> ", len(data)) for i := 2; i < len(out); i++ { if i+1 >= len(out) { break } if out[i] == 0xff && out[i+1] == 0 { skip = i + 2 break } } return out[skip:]
以上是第一次尝试,但失败了。
rsa.decryptpkcs1v15
确实需要私钥,但提供商坚称没有必要。
encryptedBlockBytes, err := rsa.DecryptPKCS1v15( rand.Reader, NO_PRIVATE_KEY_PROVIDED, payloadBytes[start:finish])
有没有办法使用 go crypt 库从 rsa 验证 pss 获取解密的有效负载?
正确答案
从java代码来看,填充并不清楚,因为只指定了算法,但没有指定填充。在这种情况下,填充取决于提供者,例如sunjce 提供程序的 pkcs#1 v1.5。
假设 pkcs#1 v1.5,cipher.encrypt_mode
/私钥和 cipher.decrypt_mode
/公钥的组合应用 RSASSA-PKCS1-v1_5 作为填充。这在功能上与使用 nonewithrsa
进行签名/验证相同(除了使用 nonewithrsa
进行验证与使用公钥解密相比还额外检查数据的相等性)。
NonewithRSA
表示数据未经过哈希处理,并且没有在前面添加摘要 id。该算法实际上旨在对已经散列的数据进行签名(在预先添加摘要 id 之后)。它绝不意味着对未散列的数据进行签名,即 java 代码滥用了该算法。
由于 rsa 限制消息大小(密钥大小减去填充所需的空间),因此只能对适当的短消息进行签名。因此,大小超过允许大小的未散列数据会强制进行多重签名。这就是java代码中多次解密的原因。
使用散列数据不仅出于实际原因(签署长消息)有用,而且出于安全原因也是必要的。例如here和here。
为了在 go 中实现 java 代码的功能,需要像在 java 代码中一样在 go 中进行签名/验证的低级实现。
另一种可能性是实现解密 (m = c^e) 并自行删除填充,对于 rsassa-pkcs1-v1_5,填充仅由一系列 0xff 值组成,左侧为 0x0001,右侧为 0x00。 p>
下面我考虑第二种方法。下面的 go 代码执行以下操作:
- 导入公钥
- base64 解码密文
- 将密文分割成单独的签名块(这里 3 个块包含相同的数据:敏捷的棕色狐狸跳过懒狗)
- 解密每个签名块(m = c ^ e)
- 连接解密的签名块
package main import ( "fmt" "math/big" "encoding/pem" "crypto/x509" "crypto/rsa" "encoding/base64" "bytes" "io" ) func main() { pubkeypem := `-----begin public key----- miibijanbgkqhkig9w0baqefaaocaq8amiibcgkcaqeaoz67dtutlxoxnnezrbfb mwukejgc+y69cggpnbtelqj3m4aft/7cu9qybtngutsncdt7uovznb21u1vpzwkh yvgfego4sa8rnnjhjt2d7z8rdmwx3saody7jo9tklrpablzgo2o8vadw8dly/v+i d0ydheckvcoceeujq8koxzhtwhykgpu+vkdiqx5cuaivtu1uzt591ao5vw/hv4di hfknotnyxnpxiwrwtpyyogta64ywfi2t0bv99qz0bgdjqjd0civce8lrxgghyb1u 1ahjddgenultyjyeqczngwbpzehujqioxelfjt55afgpchauyuoxop3gqvosj6rc sqidaqab -----end public key-----` // import public key pubkey := importspkipublickeypem(pubkeypem); // base64 decode ciphertext ciphertextbytes, _ := base64.stdencoding.decodestring("ajqbkszbz97yzapsrbab9vj0ddlm9ttrqwsz+ucpj+cysmw06klctrh3spn3b2dqsd1revlxqxmtszfmjrvz5f8y3nzdp8njarploigbpfhkztv7xbvk5atemlukgti7f+d3kdmgug+cytkfxirmbvb3bis5otimnmc9pqlawcdvf9qpuxnwemqjbeo9ntklpdv+f8brchhmeukkrrmjbopbbcfq9hi4bhifyxpwhwb66d/arycksfrhax6hsktl+0nvuhvhv98wdo3juv2il50xkocbfc8kug628tcsk6n31pilf9cntsvtb/l/pvfcaxewx4hcuhluqmk6ezijvgo0g5lm22fe2gwj0kqwm/b49awy5vbu60memfrnd4/ngepsnoiiwrur90j5929g6knda3ry16stlusxzo0b2erfmt583t/dswkaztoogzxysmu7+8qvsuqexji7pilso3/ndynzhlbvnmk5h8skzabwdwseuae4jdzgvaai2lna1rfaqbsz8bdecw3jvz05jaxb/hfaa3ir5nljckazcqad223h6vr4ugx4hcst1ocaeunfwk8girbuywl+oupey/tdb7ovyb/fmhan47r9ijedfyjgm33pjfbutve3eiup99ayixfxj7uluwfy/6vx3amrmmeixfis7qppohgscbxqnbuszntn3thlo9jefpv2+pqmmub21otdbjn65w+p5xhkbdtoosk1efdi+fdvyopj3wt68terey1lmwang9nkxzlefn0/w0lpgmu6kbs8weplo/vefurkbmsyu6sc0jt/53cp2yzqb5zjor/eiswg8hcehlmhoiw2yl2motpzwnux2qm7gfaqxalt472doswl2/4xwgtyeez5sqpgswkgg9ttx+r0elhseixle9ahahrp38cviiqwvgfpfqfkrmv7q2+6fwg/3zb2jeo6/yixnrco4jt9zyrqbrbxnxirqffwmisx1ye1jvmh8v+lv9wdetdhifxseu6qatorkgm8") // split ciphertext into signature chunks a 2048/8 bytes and decrypt each chunk reader := bytes.newreader(ciphertextbytes) var writer bytes.buffer ciphertextbyteschunk := make([]byte, 2048/8) for { n, _ := io.readfull(reader, ciphertextbyteschunk) if (n == 0) { break } decryptchunk(ciphertextbyteschunk, &writer, pubkey) } // concatenate decrypted signature chunks decrypteddata := writer.string() fmt.println(decrypteddata) } func importspkipublickeypem(spkipem string) (*rsa.publickey) { body, _ := pem.decode([]byte(spkipem )) publickey, _ := x509.parsepkixpublickey(body.bytes) if publickey, ok := publickey.(*rsa.publickey); ok { return publickey } else { return nil } } func decryptchunk(ciphertextbyteschunk []byte , writer *bytes.buffer, pubkey *rsa.publickey ){ // decrypt each signature chunk ciphertextint := new(big.int) ciphertextint.setbytes(ciphertextbyteschunk) decryptedpaddedint := decrypt(new(big.int), pubkey, ciphertextint) // remove padding decryptedpaddedbytes := make([]byte, pubkey.size()) decryptedpaddedint.fillbytes(decryptedpaddedbytes) start := bytes.index(decryptedpaddedbytes[1:], []byte{0}) + 1 // // 0001ff...ff00: find index after 2nd 0x00 decryptedbytes := decryptedpaddedbytes[start:] // write decrypted signature chunk writer.write(decryptedbytes) } func decrypt(c *big.int, pub *rsa.publickey, m *big.int) *big.int { // textbook rsa e := big.newint(int64(pub.e)) c.exp(m, e, pub.n) return c }
输出:
the quick brown fox jumps over the lazy dogthe quick brown fox jumps over the lazy dogthe quick brown fox jumps over the lazy dog
请注意,代码只是示例实现,特别是不包括异常处理。
测试:
java代码如下
String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoZ67dtUTLxoXnNEzRBFBmwukEJGC+y69cGgpNbtElQj3m4Aft/7cu9qYbTNguTSnCDt7uovZNb21u1vpZwKHyVgFEGO4SA8RNnjhJt2D7z8RDMWX3saody7jo9TKlrPABLZGo2o8vadW8Dly/v+Id0YDheCkVCoCEeUjQ8koXZhTwhYkGPu+vkdiqX5cUaiVTu1uzt591aO5Vw/hV4DIhFKnOTnYXnpXiwRwtPyYoGTa64yWfi2t0bv99qz0BgDjQjD0civCe8LRXGGhyB1U1aHjDDGEnulTYJyEqCzNGwBpzEHUjqIOXElFjt55AFGpCHAuyuoXoP3gQvoSj6RCsQIDAQAB"; byte[] ciphertext = Base64.getDecoder().decode("ajQbkszbZ97YZaPSRBab9vj0DDLm9tTrQwSZ+ucPj+cYSmw06KLCtRH3SPn3b2DqSd1revLXqxMtSzFmjRvZ5F8y3nzdP8NJaRplOigbPFhKZTv7xBVK5ATEmLukgtI7f+d3KdmGUG+cyTkfxIrMBvB3BIS5oTiMNmC9pqLaWcDVF9qpuxnwEMQJbeO9nTklpdv+F8BrchHmeUkKRrMJBoPbbcfq9Hi4bHiFyxPWhwB66d/AryCKsFRhaX6hSkTL+0NvuhVhv98wdo3juv2Il50XKOCbfc8kUG628TcSK6n31piLF9cntSVTB/L/pVfcAxEwx4hcUhLuqmk6EZIJvGo0G5LM22fe2GWj0kQWm/b49Awy5vbU60MEmfrnD4/nGEpsNOiiwrUR90j5929g6knda3ry16sTLUsxZo0b2eRfMt583T/DSWkaZTooGzxYSmU7+8QVSuQExJi7pILSO3/ndynZhlBvnMk5H8SKzAbwdwSEuaE4jDZgvaai2lnA1RfaqbsZ8BDECW3jvZ05JaXb/hfAa3IR5nlJCkazCQaD223H6vR4uGx4hcsT1ocAeunfwK8girBUYWl+oUpEy/tDb7oVYb/fMHaN47r9iJedFyjgm33PJFButvE3Eiup99aYixfXJ7UlUwfy/6VX3AMRMMeIXFIS7qppOhGSCbxqNBuSzNtn3thlo9JEFpv2+PQMMub21OtDBJn65w+P5xhKbDToosK1EfdI+fdvYOpJ3Wt68terEy1LMWaNG9nkXzLefN0/w0lpGmU6KBs8WEplO/vEFUrkBMSYu6SC0jt/53cp2YZQb5zJOR/EiswG8HcEhLmhOIw2YL2motpZwNUX2qm7GfAQxAlt472dOSWl2/4XwGtyEeZ5SQpGswkGg9ttx+r0eLhseIXLE9aHAHrp38CvIIqwVGFpfqFKRMv7Q2+6FWG/3zB2jeO6/YiXnRco4Jt9zyRQbrbxNxIrqffWmIsX1ye1JVMH8v+lV9wDETDHiFxSEu6qaToRkgm8"); byte[] decrypted = decryptByPublicKey(ciphertext, publicKey); System.out.println(new String(decrypted, StandardCharsets.UTF_8));
使用您发布的方法会得到相同的结果。
本篇关于《用Java的公钥进行RSA解密操作》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于Golang的相关知识,请关注golang学习网公众号!

- 上一篇
- 终止 golang 中执行 exec.command 的子进程

- 下一篇
- 将大括号{}转换为键值对{}
-
- Golang · Go问答 | 1年前 |
- 在读取缓冲通道中的内容之前退出
- 139浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 戈兰岛的全球 GOPRIVATE 设置
- 204浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何将结构作为参数传递给 xml-rpc
- 325浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何用golang获得小数点以下两位长度?
- 477浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何通过 client-go 和 golang 检索 Kubernetes 指标
- 486浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 将多个“参数”映射到单个可变参数的习惯用法
- 439浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 将 HTTP 响应正文写入文件后出现 EOF 错误
- 357浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 结构中映射的匿名列表的“复合文字中缺少类型”
- 352浏览 收藏
-
- Golang · Go问答 | 1年前 |
- NATS Jetstream 的性能
- 101浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何将复杂的字符串输入转换为mapstring?
- 440浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 相当于GoLang中Java将Object作为方法参数传递
- 212浏览 收藏
-
- Golang · Go问答 | 1年前 |
- 如何确保所有 goroutine 在没有 time.Sleep 的情况下终止?
- 143浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 毕业宝AIGC检测
- 毕业宝AIGC检测是“毕业宝”平台的AI生成内容检测工具,专为学术场景设计,帮助用户初步判断文本的原创性和AI参与度。通过与知网、维普数据库联动,提供全面检测结果,适用于学生、研究者、教育工作者及内容创作者。
- 12次使用
-
- AI Make Song
- AI Make Song是一款革命性的AI音乐生成平台,提供文本和歌词转音乐的双模式输入,支持多语言及商业友好版权体系。无论你是音乐爱好者、内容创作者还是广告从业者,都能在这里实现“用文字创造音乐”的梦想。平台已生成超百万首原创音乐,覆盖全球20个国家,用户满意度高达95%。
- 26次使用
-
- SongGenerator
- 探索SongGenerator.io,零门槛、全免费的AI音乐生成器。无需注册,通过简单文本输入即可生成多风格音乐,适用于内容创作者、音乐爱好者和教育工作者。日均生成量超10万次,全球50国家用户信赖。
- 23次使用
-
- BeArt AI换脸
- 探索BeArt AI换脸工具,免费在线使用,无需下载软件,即可对照片、视频和GIF进行高质量换脸。体验快速、流畅、无水印的换脸效果,适用于娱乐创作、影视制作、广告营销等多种场景。
- 26次使用
-
- 协启动
- SEO摘要协启动(XieQiDong Chatbot)是由深圳协启动传媒有限公司运营的AI智能服务平台,提供多模型支持的对话服务、文档处理和图像生成工具,旨在提升用户内容创作与信息处理效率。平台支持订阅制付费,适合个人及企业用户,满足日常聊天、文案生成、学习辅助等需求。
- 27次使用
-
- GoLand调式动态执行代码
- 2023-01-13 502浏览
-
- 用Nginx反向代理部署go写的网站。
- 2023-01-17 502浏览
-
- Golang取得代码运行时间的问题
- 2023-02-24 501浏览
-
- 请问 go 代码如何实现在代码改动后不需要Ctrl+c,然后重新 go run *.go 文件?
- 2023-01-08 501浏览
-
- 如何从同一个 io.Reader 读取多次
- 2023-04-11 501浏览