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,一经查实,立即删除!

相关文章

鸿蒙ZRouter动态路由框架—NavDestnation页面模板化

前言 源码:https://gitee.com/common-apps/ZRouterOH:https://ohpm.openharmony.cn/#/cn/detail/hzw%2Fzrouter 基本使用 在介绍基本使用的流程中,我们知道每个子页面都需要通过NavDestination来包裹,这样会造成代码的冗余&…

【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…

每日速记10道java面试题23-Spring篇+Springboot篇

其他资料 每日速记10道java面试题01-CSDN博客 每日速记10道java面试题02-CSDN博客 每日速记10道java面试题03-CSDN博客 每日速记10道java面试题04-CSDN博客 每日速记10道java面试题05-CSDN博客 每日速记10道java面试题06-CSDN博客 每日速记10道java面试题07-CSDN博客 每…

4K高清壁纸网站推荐

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

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

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

双向链表容器

C中的list是一个双向链表容器&#xff0c;用于存储一系列的元素。它提供了在任意位置插入和删除元素的能力&#xff0c;同时还支持随机访问。 在C中&#xff0c;list是由标准模板库&#xff08;STL&#xff09;提供的容器之一。它位于<list>头文件中&#xff0c;并且通过…

正则表达式去除文本中括号()<>[]里的内容

一行文本中包含有各种括号&#xff0c;如()、<>、[]&#xff0c;我们希望把括号及括号内的内容0去除&#xff0c;可以通过正则表达式来实现。 匹配() pattern r\([^)]*\) # 匹配()匹配一个左括号(&#xff0c;然后匹配0个或多个不是右括号的任意字符[^)]*&#xff0c…

单击后移动至标记

单击后移动至标记 点击生成的表单之后&#xff0c;会在地图上自动的移动到改运动锻炼的位置 如何实现 实现这个我们肯定需要点击事件&#xff0c;但是我们需要去选取一个监听的类&#xff0c;我们使用事件委托的方式来创建这个点击事件&#xff1b; 实际代码 创建点击事件 …

C# 中的异常处理:构建健壮和可靠的程序

C#中的异常处理&#xff08;Exception Handling&#xff09;。异常处理是编程中非常重要的一部分&#xff0c;它允许开发者优雅地处理程序运行时可能出现的错误或意外情况。通过有效的异常处理&#xff0c;可以使应用程序更加健壮、可靠&#xff0c;并提供更好的用户体验。以下…

C# 中?. 和 ??

在 C# 中&#xff0c;?. 和 ?? 是两个不同的操作符&#xff0c;它们用于处理可能为 null 的对象。让我们分别解释这两个操作符以及它们的组合使用&#xff1a; 1. 可空类型 (?) 在 C# 中&#xff0c;? 用于定义可空值类型&#xff08;Nullable Value Types&#xff09…

[C++]继承

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

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

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

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

开启域名&#xff0c;单点登录后&#xff0c;就使用最上面的接口了

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

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

QILSTE H6-C210LB/5M高亮蓝光LED灯珠 发光二极管LED

在电子照明领域&#xff0c;H6-C210LB/5M&#xff0c;这款高亮蓝光LED&#xff0c;以其精确的参数和卓越的性能&#xff0c;脱颖而出。本文将通过增加文本的复杂性和长短句的交替使用&#xff0c;深入探讨这款LED的技术参数&#xff0c;以增强文章的困惑性和突发性。 **H6-C21…

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

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

回调机制详解

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

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

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