goLang之路(RSA加密算法)

RSA加密算法

  • RSA加密算法
    • RSA之go与Java
      • 加解密算法对应关系
      • 签名算法对应关系
      • 密钥系列化与反序列化
    • 生成密钥对
      • 密钥序列化为字符串(pkcs1标准不推荐再使用,而且Java标准库也不提供支持)
      • 密钥反序列化为密钥对象
  • 留一个示例(Go与Java交互)
    • Go(加密、签名)
    • Java(解密、验签)
      • 解密
      • 验签

RSA加密算法

RSA之go与Java

加解密算法对应关系

GoJava
EncryptPKCS1v15RSA/ECB/PKCS1Padding(加密模式)
DecryptPKCS1v15RSA/ECB/PKCS1Padding(解密模式)
EncryptOAEP(可以指定具体的hash算法)RSA/ECB/OAEPWithSHA-1AndMGF1Paddinggo的sha1算法)(加密模式)RSA/ECB/OAEPWithSHA-256AndMGF1Paddinggo的sha256算法)(加密模式)
DecryptOAEP(可以指定具体的hash算法)RSA/ECB/OAEPWithSHA-1AndMGF1Paddinggo的sha1算法)(解密模式)RSA/ECB/OAEPWithSHA-256AndMGF1Paddinggo的sha256算法)(解密模式)

签名算法对应关系

GoJava
rsa.SignPKCS1v15(指定不同的hash算法,对应Java算法名称前面的SHA名称SHA1withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA(对应sign方法)
rsa.VerifyPKCS1v15(指定不同的hash算法,对应Java算法名称前面的SHA名称SHA1withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA(对应sign方法)
rsa.SignPSS()(同样指定不同的hash算法RSASSA-PSS(配合PSSParameterSpec(指定具体的hash算法) 使用)sign方法
rsa.VerifyPSS(同样指定不同的hash算法)RSASSA-PSS(配合PSSParameterSpec(指定具体的hash算法) 使用)verify方法

密钥系列化与反序列化

GoJava
x509.MarshalPKCS1PrivateKey标准库不支持 PKCS#1
x509.MarshalPKCS1PublicKey标准库不支持 PKCS#1
x509.ParsePKCS1PrivateKey标准库不支持 PKCS#1
x509.ParsePKCS1PublicKey标准库不支持 PKCS#1
x509.MarshalPKCS8PrivateKeyPrivateKey#getEncoded
x509.MarshalPKIXPublicKeyPublicKey.getEncoded()
x509.ParsePKCS8PrivateKeyPKCS8EncodedKeySpec
x509.ParsePKIXPublicKeyX509EncodedKeySpec

生成密钥对

go中生成密钥对非常简单

// 1024 密钥位数
key, err := rsa.GenerateKey(rand.Reader, 1024)
// key本身就是私钥,而公钥包含在私钥的一个字段内
publicKey := key.PublicKey

密钥序列化为字符串(pkcs1标准不推荐再使用,而且Java标准库也不提供支持)

java需借助 Bouncy Castle 等第三方库解析PKCS1的密钥。大致代码如下

RSAPrivateKeyStructure keyStructure = new RSAPrivateKeyStructure((ASN1Sequence) ASN1Sequence.fromByteArray(Base64.getDecoder().decode(base64PrivateKey)));
RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(keyStructure.getModulus(), keyStructure.getPrivateExponent());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
  • pkcs1方式编码密钥和公钥
key, _ := rsa.GenerateKey(rand.Reader, 1024)// pkcs1 方式相对比较老,新的系统普遍使用 pkcs8 处理私钥
privateByte := x509.MarshalPKCS1PrivateKey(key)
publicByte := x509.MarshalPKCS1PublicKey(&key.PublicKey)
privateByteBase64 := base64.StdEncoding.EncodeToString(privateByte)
publicByteBase64 := base64.StdEncoding.EncodeToString(publicByte)p("私钥:", privateByteBase64)
p("公钥:", publicByteBase64)
  • pkcs8方式

密钥反序列化为密钥对象

/*反序列化私钥*/
privateKeyDec, _ := base64.StdEncoding.DecodeString(privateByteBase64)
privateKey, _ := x509.ParsePKCS1PrivateKey(privateKeyDec)
/*反序列化公钥*/
publicKeyDec, _ := base64.StdEncoding.DecodeString(publicByteBase64)
publicKey, _ := x509.ParsePKCS1PublicKey(publicKeyDec)

留一个示例(Go与Java交互)

Go(加密、签名)

// 生成RSA私钥privateKey, err := rsa.GenerateKey(rand.Reader, 2048)if err != nil {fmt.Println("生成私钥失败:", err)return}// 获取对应的公钥publicKey := privateKey.PublicKey// 要加密的文本plaintext := []byte("这是一段要加密的文字")// 使用公钥加密文本encryptedData, err := rsa.EncryptPKCS1v15(rand.Reader, &publicKey, plaintext)if err != nil {fmt.Println("加密失败:", err)return}// 将加密后的数据进行Base64编码encryptedBase64 := base64.StdEncoding.EncodeToString(encryptedData)fmt.Println("Base64编码后的密文:", encryptedBase64)// 将私钥转换为Base64编码字符串privateKeyBase64 := privateKeyToBase64(privateKey)fmt.Println("Base64编码后的私钥:", privateKeyBase64)// 将公钥转换为Base64编码字符串publicKeyBase64 := publicKeyToBase64(&publicKey)fmt.Println("Base64编码后的公钥:", publicKeyBase64)// 开始私钥签名hashed := sha256.Sum256(plaintext)sha256, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed[:])if err != nil {panic(err)}p("签名:", base64.StdEncoding.EncodeToString(sha256))

Java(解密、验签)

解密

// Go生成的私钥
String base64PrivateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCmcxhZF3Q0TBMavmcUueq2BJ09QbXUM+rYrPbIXFN5wecrpGs1T+gaZ6HnKTkHLR55iBhVfJ6QTjRcdkREZ86EwkhlJItKp8P9HlR+cNdoDTXMLYKZmSrZ2o0gS5wjGd8f6bil+BauIac8uWOgXULIU8QnAAJECflvcAsJWIlhbTG3gaDSGlBODmViTMxe64WowEaLdo3MFUZhTF/i3Q+KhLan8l99pLrA5ufXx9pMrexMsbzuNW/9AKV4j++ANRuxIhMPY4UauFCOEgtbBx6BWKUXK9/eGO7LJSeOQoZBM2yDnsobVojCjSSQmuInue3PE0i7GcBlw0X+oOgpY/G/AgMBAAECggEBAIm09xPeP5l0xul9VTLkjbaBIsWnM5OYUFdq4dDp8XXuYh7NLJUywsf1rRDeHfw969SIL/mp3FVvHgrRHbGqYEWdpt9m2IavPYqQKT9ihBPlufhuPnptKfKKye9KHqc7pEl2x/knwzvVQ9MNXcsy3Sl3g/TwIO/BgMgdXkQhJ6edpY4+bag238UmVCqe2oRvpqiSN477afBsa1JNyfY1UEjku+wvj1wNJ56NPS3TAeq1B8XIBGB7IooVAXB4OU4k1zf1FvYeNguiMBOIUh/Gdl3Z+FXMt3hvI8yoNJre3KupmR8j3TzlgkhJgg53ZZTUfgjzy479DwUhYQYvqcICeMECgYEAxpGPldUHLP+1kxutnVHEDPCIF8bqndh3RMKLG0ggY62RDphCOfzzMnYLPjA9CgIdIPo9gPRKcMYsJ2rNJMaSX3LuA7po4BNlG7aMkQT5Ztaa1XtFg3GsS+UjYnbF6Aj1Gt+UUc7SdrJs/WrRzxMD2IGX34mkEjAdaQzudvsJ3JkCgYEA1pdf/2/OCLbj2qNM1dsnFEhfUFw+dmbnvRHl1H8+DDWKkiFZVGEwbdp2mtosvlw/dZXNdeW2VBULjCLBGkfgA5cxXUJomSjT5anfPD0LtJZJSvRlD7P9dAY59/5ySiCRi7/ko7ID6fWhJvpNj0sOMR1tafkoVTB9eX4OAHYeIBcCgYEAizLDSy+5BgyDxwpiHKSTINcFMFXbZqe2hFc0mP1o5zdnNqn50xjFi5xAqWm7gGaW8OU7dEjMXl4t2bv+70bcmVjCDY8BsgMmn9TKmWa5RyQuCnWN92UaeWG5+m50sgKFgD83hFnOJDNUQBo/1j/oNEA0rRmaEL32AAx2pqW49hECgYEAjm5c5mNkQn550AWxmwRh9OFwehsvzlDRIbo+bQOjwGDNP97otsvnZBKrxG5pYlRCPp6Wh9lXYomxZ2st9m6cbmWs+zR3zqi9tGNC622tVkimDx0V8w1JffggA82cOD1TvYk5jbk7Rc+mDgP29NQhcFIS7FLXBWww7DHRw1ai+jMCgYAglIzt0lUc6Yx5OUOtnm/3Tn1gH1NmktAXyC1JNQxxp9CBHDtD038LJHuArSyLp1hxRzoJ4E5cmUTWLLx4v5pMGunrcDPZrj/oJBfFDc5SItDZ6H2PKqrN0ZvyqxUxW6NIwhKpkjEif9SayrDZP5vHDbcVp8ScMJKwz7ynUkRCcg==";
// Go生成的密文
String base64EncryptedText = "U2PeiPR52FVkDuBWdTcg0Cu0SAiVIQ0GuPh8TYivP91rGwIf/nRQsZ5pznEVX3YPypV0caJWInk6p6HEW3D4C1mGnrnG5BttDTKIFneyN8Yv46LOg83Tykk+1vY47+OflLBPYX4zIFSLBUyQMPJUaFWAYmQ3Zy/32Bm2i3gl/H9foeM4Mf+BBdrv2jRKdm738e5V6xvOhQbcW7K4eav0MhX+0PXJPSlwgXch7Fh1dRj50Gb2srVYgvg/pshHIHEZgkfsry60xmn9qBkqFIHybqlow0l5632TMU3qDnLTXt1Z1goos0/QSzIRlWkwDr9IRMfo1H9AFcajrNRP1aJIpw==";
PrivateKey privateKey = getPrivateKeyFromBase64(base64PrivateKey);
// 将Base64编码的密文字符串转换为字节数组
byte[] encryptedBytes = Base64.getDecoder().decode(base64EncryptedText);
// 使用私钥解密
byte[] decryptedBytes = decrypt(privateKey, encryptedBytes);
System.out.println("解密后的文本: " + new String(decryptedBytes));
  • 解密用的辅助方法
    public static PrivateKey getPrivateKeyFromBase64(String base64PrivateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {byte[] privateKeyBytes = Base64.getDecoder().decode(base64PrivateKey);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);return keyFactory.generatePrivate(keySpec);}public static byte[] decrypt(PrivateKey privateKey, byte[] encryptedData) throws NoSuchPaddingException, java.security.InvalidKeyException, javax.crypto.IllegalBlockSizeException, javax.crypto.BadPaddingException, NoSuchAlgorithmException {Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");cipher.init(Cipher.DECRYPT_MODE, privateKey);return cipher.doFinal(encryptedData);}

验签

// Go 生成的公钥
String publicStr = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwsTqgcW8vD+Ac9mnE1T2DDP7Nu2voifcC4xS60gvtC8cDKhqMP3B/Vno2InJ06EP94VZFukXZlbQaIF5U2z5Dyp/iT+yPjQnG6ZBL9IjrPovL1rvcUkDZu+yqajvKM0FCz+NsPIzO8pjlRGjIlfGKC9Of1XutxUwlux5aR55NA0vXCN60giz4DK2HFIKQioITwOduEeYL1xinUpY7lGLkouPJRjrVvvcjzgb5QCeLS5vxQ6EsmrzcomnAKfnGar1dvSVUqJk0lu9nrWygJngRsotLG4VbwRVTklWH49rEr5fkPtaal4avtjCiXXNalHscv/nU/fwF1okKCIt5hmV+QIDAQAB";
// Go 生成的签名
String sign = "RjYdalZyJpqOTjQwK1VJd2kD+5gHnTliqbhhpLfda7lq7BWlQ84VzRy+rs3W2yBI1aJtNKj8ByXwD9jJh51fmMunCPZ/Uv6tpuuSGGE0mAeIE3gl1aPSipjvKO7PBpYMsbFxI4NiL9Zh0LKLStUj4Xtc92pmXJdcL80JlTEdxC+vx7dsO/GXzM0TGskFD1whpYETLFEFc4ASD9AXMBNVycdv4jWFO/SRN+LUtpTQsSWC/K7o8wlXCqFE4zsOnj/fgG2uKwt7aZMyZN/hdLP3T+MftXaFeVFOphh/9E6SvOCqo7mP9MXu5SUBL2/pfDpV5fxeNzVW6I8VnfxMLgnHFA==";
// 反序列化公钥
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicStr));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(publicKey);
// 签名的原文
String plain = "这是一段要加密的文字";
byte[] bytes = plain.getBytes(StandardCharsets.UTF_8);
signature.update(bytes);
boolean verify = signature.verify(Base64.getDecoder().decode(sign));
System.out.println("验签结果:" + verify);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/888971.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【AIGC】如何获取ChatGPT外部GPTs应用的提示词Prompt指令和知识库文件

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | GPTs应用实例 文章目录 💯前言💯获取GPTs的提示词Prompt指令💯获取GPTs的知识库文件💯小结 关于GPTs指令如何在ChatGPT上使用,请看这篇文章&#xff…

沐风老师3DMAX摄相机阵列插件使用方法

3DMAX摄相机阵列插件,从网格对象或样条线的顶点法线快速创建摄相机阵列。该插件从网格的顶点或样条线的节点获取每个摄影机的位置和方向。 3DMAX摄相机阵列插件支持目前3dMax主流的物理相机、标准相机、VRay物理相机。 【版本要求】 3dMax 2015及更高版本 【安装方…

BMC VPD格式定义

1.说明 目前遇到有2种格式的VPD定义方式,特记录并分享出来。 本节可参考链接下载文件: https://gitee.com/wit_yuan/fru 2.参考PCI_Express_Base_6.0a.pdf 应用范围: 例如常见的定制raid卡,Hba卡采用的储存serial number等。 3.参考platform-manag…

4K高清壁纸网站推荐

1. Awesome Wallpapers 官网: https://4kwallpapers.com/ 主题: 创意、摄影、人物、动漫、绘画、视觉 分辨率: 4K Awesome Wallpapers 提供了丰富的高质量图片,分为通用、动漫、人物三大类,可以按屏幕比例和分辨率检索,满足你对壁纸的各种…

小迪笔记 第四十五天 sql 注入进阶 :二次注入,堆叠注入,数据读取(load_file)加外带

二次注入 概念:就是我们注入的语句(刚注入时 不会产生影响)但是我们的恶意代码会进入数据库 他在被二次利用的时候就会进行执行 这个就是二次注入 这个的典型案例就是账号密码的修改 : 大家应该也知道 账号注册一般是禁止你使…

[C++]继承

继承 概念使用方法继承方式子类的构造与析构 继承的成员继承成员在子类对象里的存放顺序成员变量普通成员变量静态成员变量 成员函数普通成员函数重定义(隐藏) 静态成员函数友元函数 单继承与多继承概念赋值转换(切片)多继承带来的…

机器人构建详解:售前售后服务客服机器人与广告生成机器人的微调数据处理方法

引言 大模型(如BERT、GPT等)在自然语言处理任务中展现了强大的能力,但为了使其更贴合特定应用场景,通常需要进行微调。本文将详细讲解如何为售前售后服务的客服机器人和广告生成机器人准备高质量的微调数据,并通过具体…

8.解决跨域问题的三种方案

开启域名,单点登录后,就使用最上面的接口了

全解:Redis RDB持久化和AOF持久化

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…

使用 ASP.NET Core HttpLoggingMiddleware 记录 http 请求/响应

我们发布了一个应用程序,该应用程序运行在一个相当隐蔽的 WAF 后面。他们向我们保证,他们的产品不会以任何方式干扰我们的应用程序。这是错误的。他们删除了我们几乎所有的“自定义”标头。为了“证明”这一点,我构建了一个中间件&#xff0c…

回调机制详解

一、什么是回调: 回调是一种双向的调用模式,程序模块之间通过这样的接口调用完成通信联系,回调的核心就是回调方将本身即this传递给调用方,这样调用方就可以在调用完毕之后再告诉回调方它想要知道的信息。 回调函数用于层间协作&…

CUDA 计时功能,记录GPU程序/函数耗时,cudaEventCreate,cudaEventRecord,cudaEventElapsedTime

为了测试GPU函数的耗时,可以使用 CUDA 提供的计时功能:cudaEventCreate, cudaEventRecord, 和 cudaEventElapsedTime。这些函数可以帮助你测量某个 CUDA 操作(如设置设备)所花费的时间。 一、记录耗时案例 以下是一个示例程序&a…

异步操作,promise、axios

一、异步操作(异步编程)、同步操作 异步操作是指在编程中,某个任务的执行不会立即完成,同时不会阻塞后续代码的执行。在异步操作中,程序可以继续运行,并在异步任务完成时得到通知并处理结果。这与同步操作…

Ansible的yum和saltstack的哪个功能相似

Ansible的yum和saltstack的哪个功能相似 在 Ansible 和 SaltStack 中,Ansible 的 yum 模块 和 SaltStack 的 pkg 模块 功能相似。它们都用于管理软件包,支持安装、升级、删除和查询等操作。 Ansible 的 yum 模块 用途: 专门用于基于 Red Hat …

JVM 面试题相关总结

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…

基于BiLSTM-CRF的中文电子病历命名实体识别

声明:博客未经允许禁止抄袭转载。 前言 最近有粉丝在后台私信我能不能更一篇关于命名实体识别(NER,Named Entity Recognition)的经典模型BiLSTM-CRF的实战文章,前段时间有点忙所有一直没有更新,趁着最近有点空,满足一…

k8s 优雅监控jvm及dump heap的方案探讨

背景 k8s cluster 的健康检测失败会主动重启pod,而大部份情况下健康检测失败都是由full gc引起的。往往发生重启时已经没有条件dump heap排查full gc的原因。 如何监控 为了避免因健康检测失败而导致的pod重启,我们需要实施有效的监控策略,这…

TPM 2.0:安全固件的新标准

得益于可信计算组 ( TCG ) 推出的全新 TPM 2.0规范,联网设备可以更好地抵御网络攻击,并且不太可能受到错误的攻击。 制造商将可信平台模块 (TPM) 附加到设备上,以帮助用户和管理员验证其身份、生成和存储加密密钥以及确保平台完整性。 在 T…

ensp实验-vrrp多网关配置

一、交换机与路由的配置区别 1. 角色定义交换机: Master 或 Backup: 交换机通常作为 Master 或 Backup 设备参与 VRRP,负责在主设备故障时接替其工作。路由器: Master 或 Backup: 路由器同样可以作为 Master 或 Backup 设备…

黑盒测试方法

‌黑盒测试是一种软件测试方法,它通过向系统提供输入并检查输出结果来验证系统的功能是否符合需求。‌黑盒测试主要关注软件的功能性,而不是其内部结构或工作原理。以下是几种常见的黑盒测试顺序方法: 场景设计法‌: 通过模拟实际…