RSA公钥加密机制跨语言应用实战
在公钥密码学中(也称为非对称密码学),加密机制依赖于两个密钥:公钥和私钥。公钥用于加密消息,而只有私钥的所有者才能解密消息。实际应用中通常需要对公钥和私钥进行序列化,然后分发密钥实现在不同场景、不同语言环境中使用。本文主要介绍如何生成RSA密钥对并序列化为文件,最后使用密钥对进行跨语言应用。
概念介绍
RSA, 即 Rivest–Shamir–Adleman,是非对称加密算法。不同于对称加密算法(如AES、DES),它需要两个密钥,公钥可共享给任何人,用于加密信息;私钥仅我们自己保存,用于解密数据。
-
X.509 是定义公钥证书格式的标准,用于描述公钥及其他信息。
-
PKCS8 是存储私钥的标准。为了安全起见,可以使用对称加密算法对私钥再次进行加密。该标准不仅可以处理RSA私钥,还可以处理其他算法。PKCS8私钥通常通过PEM编码格式进行交换。
-
DER 是最流行的数据存储编码格式,如X.509证书文件、PKCS8私钥文件。它是二进制编码格式,内容不能通过文本文件直接查看。
-
PEM 是对DER证书内容进行base64编码的机制,PEM也能编码其他类型数据,如公钥、私钥以及请求证书。PEM文件还可能包括一些格式信息,示例如下:
-----BEGIN PUBLIC KEY-----
...Base64 encoding of the DER encoded certificate...
-----END PUBLIC KEY-----
生成RSA密钥对
正式开始加密之前,需要生成RSA密钥对。可以使用java.security
包中的KeyPairGenerator
类实现:
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048);
KeyPair pair = generator.generateKeyPair();
生成密钥为2048个字节,下面可以生成公钥和私钥:
PrivateKey privateKey = pair.getPrivate();
PublicKey publicKey = pair.getPublic();
现在可以使用公钥加密数据,私钥解密数据。在加密数据之前,我们可能需要传输密钥,下面先看看如何把密钥保存为文件。
保存密钥文件
把密钥对存储在内存中不是好的选项,大多数情况下密钥不会变化,因此可以存储为文件,还可能需要分发给别人。
DER编码文件
通过getEncoded()方法,返回密钥内容的字节数组:
try (FileOutputStream fos = new FileOutputStream("public.key")) {fos.write(publicKey.getEncoded());
}
从文件中读取key,返回字节数组:
File publicKeyFile = new File("public.key");
byte[] publicKeyBytes = Files.readAllBytes(publicKeyFile.toPath());
然后使用KeyFactory类重新创建密钥实例:
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
keyFactory.generatePublic(publicKeySpec);
密钥字节内容需要使用EncodedKeySpec进行包装。这里使用X509EncodedKeySpec标准,它是缺省标准。上面实例实现了公钥的保存和读取,也可以使用同样方式实现对私钥的保存和读取。这里需要提醒的是:尽可能保障私钥的安全,我们还可以对私钥进行对称加密,防止非法访问带来安全问题。
PEM编码文件
DER编码文件是二进制格式,不能使用文本文件直接查看。下面介绍存储密钥为PEM编码文件,即使用BASE64进行编码,保存为文本文件。
首先是文件写入:
Base64.Encoder encoder = Base64.getEncoder();// 密钥对的文件名String outFile = "pairFileName";FileOutputStream out = new FileOutputStream(outFile + ".key");out.write(encoder.encode(privateKey.getEncoded()));out.close();System.err.println("Private key format: " + privateKey.getFormat());out = new FileOutputStream(outFile + ".pub");out.write(encoder.encode(publicKey.getEncoded()));out.close();System.err.println("Public key format: " + publicKey.getFormat());
没有特别的部分,仅使用encoder.encode进行Base64编码。
下面是读取过程:
/* Read all the public key bytes */Path path = Paths.get(fileName + ".pub");byte[] bytes = Files.readAllBytes(path);Base64.Decoder deCoder = Base64.getDecoder();/* Generate public key. */X509EncodedKeySpec ks = new X509EncodedKeySpec(deCoder.decode(bytes));KeyFactory kf = KeyFactory.getInstance("RSA");PublicKey publicKey = kf.generatePublic(ks);System.err.println("Public key format: " + publicKey.getFormat());
没有太多要解释的,仅多了一步解码过程,私钥的读取过程类似。
如果PEM文件包括格式信息,则读取前需要先处理:
public RSAPrivateKey readPrivateKey(File file) throws Exception {String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset());Base64.Decoder deCoder = Base64.getDecoder();String privateKeyPEM = key.replace("-----BEGIN PRIVATE KEY-----", "").replaceAll(System.lineSeparator(), "").replace("-----END PRIVATE KEY-----", "");byte[] encoded = deCoder.decode(privateKeyPEM);KeyFactory keyFactory = KeyFactory.getInstance("RSA");PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
}
RSA加密解密数据
加密过程
现在如何对简单字符串进行加密解密。首先定义明文字符串:
String secretMessage = "These are secret messages";
需要使用Cipher对象并初始化为公钥加密模式:
Cipher encryptCipher = Cipher.getInstance("RSA");
encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
准备好cipher对象,使用doFinal方法加密消息,它的参数为字节数组,因此调用前需要对字符串进行转换:
byte[] secretMessageBytes = secretMessage.getBytes(StandardCharsets.UTF_8);)
byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessageBytes);
啊哈,终于成功加密了消息。如果需要在数据库中存储消息或通过REST API发送消息,仍然需要使用BASE64进行编码:
String encodedMessage = Base64.getEncoder().encodeToString(encryptedMessageBytes);
Base64.getEncoder()是apache commons提供的工具类。编码后消息更易使用、方便读取。
解密过程
现在解释解密密文为明文。仍然需要cipher实例,这次初始化为解密模式,同时需要传入私钥:
Cipher decryptCipher = Cipher.getInstance("RSA");
decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);
和前面一样执行DoFinal方法:
byte[] decryptedMessageBytes = decryptCipher.doFinal(encryptedMessageBytes);
String decryptedMessage = new String(decryptedMessageBytes, StandardCharsets.UTF_8);
需要说明的是,如果是Base64格式,需要先解码。
跨语言使用
我们使用Golang生成rsa密钥对,然后通过java解密或验证。
golang生成密钥对
func main() {// Create the keys pairpriv, pub := GenerateRsaKeyPair()// Export the keys to pem stringpriv_pem := ExportRsaPrivateKeyAsPemStr(priv)pub_pem, _ := ExportRsaPublicKeyAsPemStr(pub)writeFile(priv_pem, "pri.key")writeFile(pub_pem, "pub.key")// 使用公钥加密文本var reqCode string = "These are secret messages"reqCodes, _ := rsa.EncryptPKCS1v15(rand.Reader, pub, []byte(reqCode))reqString := base64.StdEncoding.EncodeToString(reqCodes)writeFile(reqString, "reqStr.txt")
} func writeFile(content string, fileName string) {file, _ := os.Create(fileName)defer file.Close()_, _ = file.WriteString(content)
}func GenerateRsaKeyPair() (*rsa.PrivateKey, *rsa.PublicKey) {privkey, _ := rsa.GenerateKey(rand.Reader, 2048)return privkey, &privkey.PublicKey
}func ExportRsaPublicKeyAsPemStr(pubkey *rsa.PublicKey) (string, error) {pubkey_bytes, err := x509.MarshalPKIXPublicKey(pubkey)if err != nil {return "", err}pubkey_pem := pem.EncodeToMemory(&pem.Block{Type: "RSA PUBLIC KEY",Bytes: pubkey_bytes,},)return string(pubkey_pem), nil
}func ExportRsaPrivateKeyAsPemStr(privkey *rsa.PrivateKey) string {privkey_bytes, _ := x509.MarshalPKCS8PrivateKey(privkey)privkey_pem := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY",Bytes: privkey_bytes,},)return string(privkey_pem)
}
java用私钥解密
这里使用java8 进行解密:
public static void main(String[] args) throws Exception {RsaTools tools = new RsaTools();// 读取待解密文件内容byte[] deString = Files.readAllBytes(Paths.get("reqStr.txt"));String result = tools.decrypt(new String(deString, StandardCharsets.UTF_8));System.out.println(result);
}// 从文件加载私钥
public PrivateKey readPrivateKey(File file) throws Exception {KeyFactory factory = KeyFactory.getInstance("RSA");try (FileReader keyReader = new FileReader(file);PemReader pemReader = new PemReader(keyReader)) {PemObject pemObject = pemReader.readPemObject();byte[] content = pemObject.getContent();PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(content);return factory.generatePrivate(privKeySpec);}
}// 利用私钥解密
public String decrypt(String deStr) throws Exception {Cipher decryptCipher = Cipher.getInstance("RSA");PrivateKey privateKey = readPrivateKey(new File("pri.key"));decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);// 密文需要使用Base64解码byte[] decryptedMessageBytes = decryptCipher.doFinal(Base64.getDecoder().decode(deStr));String decryptedMessage = new String(decryptedMessageBytes, StandardCharsets.UTF_8);return decryptedMessage;
}
总结
本文介绍了如何生成RSA密钥对,并利用相关标准生成密钥文件,最后通过实例展示如何实现跨语言应用。
相关文章:
RSA公钥加密机制跨语言应用实战
在公钥密码学中(也称为非对称密码学),加密机制依赖于两个密钥:公钥和私钥。公钥用于加密消息,而只有私钥的所有者才能解密消息。实际应用中通常需要对公钥和私钥进行序列化,然后分发密钥实现在不同场景、不同语言环境中使用。本文…...
P7面试送命题
面试总结,对标市场P7。什么叫送命题,一道题回答不上来面试直接挂的题目。JVM 运行时数据区域内存回收机制GC root有哪些volatile原理synchronize原理JDK 集合家族介绍HashMap原理ConcurrentHashMap原理Thread生命周期ThreadPoolExecutor生命周期、实例化…...
零信任-微软零信任介绍(2)
微软零信任是什么? Microsoft Zero Trust 是一种安全架构,旨在在没有信任任何设备、用户或网络的情况下保护网络。这种架构使用多重验证和分段技术,以确保每个请求和资源的安全性。 零信任不假定任何内部用户或设备是安全的ÿ…...
C++中对象调用成员函数this指针的作用
C中对象调用成员函数this指针的作用 Sales_data total;//定义对象 total.isbn();//调用对象中的成员函数isbn成员函数isbn()通过一个名为this的额外隐式参数来访问调用它的对象total。当我们调用一个成员函数时,用请求该函数的对象地址初始化this。 例如࿰…...
JavaScript------数组
目录 一、简介 1、什么是数组? 2、创建数组 3、数组的数据类型 4、向数组中添加元素 5、读取数组中的元素 6、实例属性:length 二、遍历数组 方式一:for循环 方式二:for...of 三、数组方法(常用)…...
迷宫《1》
一天蒜头君掉进了一个迷宫里面,蒜头君想逃出去,可怜的蒜头君连迷宫是否有能逃出去的路都不知道。看在蒜头君这么可怜的份上,就请聪明的你告诉蒜头君是否有可以逃出去的路。输入格式第一行输入两个整数 �n 和 �m&#x…...
剑指 Offer 20. 表示数值的字符串
剑指 Offer 20. 表示数值的字符串 请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。 数值(按顺序)可以分成以下几个部分: 若干空格 一个 小数 或者 整数 (可选)一个 ‘e’ 或 ‘…...
阻抗匹配之反射波形测量
稍微接触过高速信号的朋友,一定对阻抗匹配和信号反射都有所了解,甚至可以按照公式,把反射波形一路推导出来。但是,纸上得来终绝浅,绝知此事要躬行。 今天,我们就来实测一下信号反射波形,测试环…...
微信小程序 java家校通Springboot中小学家校联系电子作业系统
小程序前端框架:uniapp 小程序运行软件:微信开发者 后端技术:javaSsm(SpringSpringMVCMyBatis)vue.js 后端开发环境:idea/eclipse 数据库:mysql 通过对各种资料的收集,了解到“校讯通”是联系社会的窗口,是实现家校联系工作和学校…...
Fluent Python 笔记 第 8 章 对象引用、可变性和垃圾回收
本章先以一个比喻说明 Python 的变量:变量是标注,而不是盒子。如果你不知道引用式变量是什么,可以像这样对别人解释别名。 然后,本章讨论对象标识、值和别名等概念。随后,本章会揭露元组的一个神奇特性:元…...
转义字符的分类
什们是转义字符 可显示字符在字符集中,有一类字符具有这样的特性:当从键盘上输入这个字符时,显示器上就可以显示这个字符,即输入什么就显示什么。这类字符称为可显示字符,如a、b、c、$、和空格符等都是可显示字符。 控…...
剑指 Offer 03. 数组中重复的数字
剑指 Offer 03. 数组中重复的数字 一、题目描述: 找出数组中重复的数字。 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出…...
飞速创新更新IPO招股书:计划募资约14亿元,向伟为实际控制人
近日,深圳市飞速创新技术股份有限公司(下称“飞速创新”)预披露更新招股书,准备在深圳证券交易所主板上市。本次冲刺上市,飞速创新计划募资13.54亿元,招商证券为其保荐机构。 据介绍,飞速创新专…...
JUC(java.util.concurrent) 的常见类
1.ReentrantLock 可重入互斥锁. 和 synchronized 定位类似, 都是用来实现互斥效果, 保证线程安全. ReentrantLock 也是可重入锁. "Reentrant" 这个单词的原意就是 "可重入. ReentrantLock 的用法: lock(): 加锁, 如果获取不到锁就死等.trylock(超时时间):…...
Angular4 中 ckeditor5 插件的使用
Angular4 中 ckeditor5 插件的使用 0 环境、新建项目 环境: Windows10Angular/cli1.4.10(安装 Angular 的过程略过,Angular4 版本比较古老,这也导致项目安装插件及其他操作比较麻烦) 1. ckeditor5 官方用法 基础用…...
[python刷题模板] 前缀函数/next数组/kmp算法
[python刷题模板] 前缀函数/next数组/kmp算法 一、 算法&数据结构1. 描述2. 复杂度分析3. 常见应用4. 常用优化二、 模板代码1. 裸前缀函数2. 树上kmp3. 裸kmp三、其他四、更多例题五、参考链接一、 算法&数据结构 1. 描述 前缀函数和next数组基本上是一个东西&#…...
rust 程序设计语言入门(1)
本文是阅读《Rust程序设计语言》的学习记录,配合视频《Rust编程语言入门教程》食用更佳 环境搭建 windows下载rustup_init.exe,点击安装,默认选择msvc的toolchain,一路default即可 解决下载慢的问题,在powershell中修…...
基于蜣螂算法改进的LSTM预测算法-附代码
基于蜣螂算法改进的LSTM预测算法 文章目录基于蜣螂算法改进的LSTM预测算法1.数据2.LSTM模型3.基于蜣螂算法优化的LSTM4.测试结果5.Matlab代码摘要:为了提高LSTM数据的预测准确率,对LSTM中的参数利用蜣螂搜索算法进行优化。1.数据 采用正弦信号仿真数据&…...
Python安全开发——Scapy流量监控模块watchdog
目录 Python蓝队项目说明 (一)Python-蓝队项目-Scapy流量分析 0x01 Scapy参数介绍...
阶段二5_集合ArrayList
一.对象数组 1.对象数组使用案例 需求:将(张三,23)(李四,24)(王五,25) 封装为3个学生对象并存入数组 随后遍历数组,将学生信息输出在控制台 思路…...
十一、Python——匿名函数
1.匿名函数:简化函数定义 2.格式 lambda 参数1,参数2…:运算 3.匿名函数特点 不需要指明函数名定义只有一条语句函数体必须是一个表达式不能显示使用return 4.匿名函数实现求和 s lambda a,b:a b result s(1,2) print(result) # 35.匿名函数作…...
数组常使用的方法
1. join (原数组不受影响)该方法可以将数组里的元素,通过指定的分隔符,以字符串的形式连接起来。返回值:返回一个新的字符串const arr[1,3,4,2,5]console.log(arr.join(-);//1-3-4-2-52. push该方法可以在数组的最后面,添加一个或者多个元素结构: arr.push(值)返回值…...
2023华为软件测试笔试面试真题,抓紧收藏不然就看不到了
一、选择题 1、对计算机软件和硬件资源进行管理和控制的软件是(D) A.文件管理程序 B.输入输出管理程序 C.命令出来程序 D.操作系统 2、在没有需求文档和产品说明书的情况下只有哪一种测试方法可以进行的(A) A.错误推测法测…...
洛谷2月普及组(月赛)
🌼小宇(治愈版) - 刘大拿 - 单曲 - 网易云音乐 OI赛制且难度对标蓝桥杯省赛(😥真难,第三题做了几百年,第四题只敢骗骗分) 花了10块钱🙃 买官网的思路,结果…...
【博学谷学习记录】超强总结,用心分享 | 架构师 Spring源码学习总结
文章目录Spring的循环依赖1.循环依赖的定义&&原因2.循环依赖的场景1.构造器注入引起循环依赖2.Field属性setter注入的循环依赖3.循环依赖解决思路4.三级缓存5.面试题[三级缓存]AOP源码深度剖析概述Spring AOP的前世今生实现机制**JDK 动态代理****CGLIB 代理**流程总结…...
Linux C/C++ timeout命令实现(运行具有时间限制)
Linux附带了大量命令,每个命令都是唯一的,并在特定情况下使用。Linux timeout命令的一个属性是时间限制。可以为任何命令设置时间限制。如果时间到期,命令将停止执行。 如何使用timeout命令 我们将解释如何使用Linux timeout命令 timeout […...
西湖论剑初赛web wp
Node Magical Login 简单的js代码审计。 Flag分成了两部分。 第一部分: 这里就简单的判断了一下user是否等于admin,直接绕过。 第二部分: checkcode ! “aGr5AtSp55dRacer”,让其为真,利用数组绕过。 Flag为&#x…...
【YOLOv8/YOLOv7/YOLOv5系列算法改进NO.55】融入美团最新QARepVGG
文章目录 前言一、解决问题二、基本原理三、添加方法四、总结前言 作为当前先进的深度学习目标检测算法YOLOv8,已经集合了大量的trick,但是还是有提高和改进的空间,针对具体应用场景下的检测难点,可以不同的改进方法。此后的系列文章,将重点对YOLOv8的如何改进进行详细…...
Flutter Windows端打包并生成可安装文件流程
Windows打包 1.首先安装visual Studio 下载地址:https://visualstudio.microsoft.com/zh-hans/ 下载成功后按照下图勾选桌面应用和移动应用下的使用C的桌面开发,勾选右侧安装详细信息中的windows 11/10 sdk 中的任意一个完成安装即可 2.打包Windows …...
凸优化学习:PART3凸优化问题(持续更新)
凸优化问题 凸优化问题的广义定义: 目标函数为凸函数约束集合为凸集 一、优化问题 基本用语 一般优化问题的描述: minimizef0(x)subject to fi(x)⩽0,i1,⋯,mhi(x)0,i1,⋯,p(1)\begin{array}{ll} \operatorname{minimize} & f_0(x) \\ \text { s…...
做微网站用哪个平台/seo免费优化网站
2019独角兽企业重金招聘Python工程师标准>>> 考虑提供一种网络功能, 教师在自己机器上面画图, 能够显示给学生; 或获取学生的图形, 并在其 基础上修改绘制, 学生能看到画图过程. 设学生机器为S, 教师机器为T, 服务器为V. 一般思路: S,T 通过服务器V连接, 通过V传输…...
专业的网站制作中心/百度推广登陆网址
1 数据封装 所有数据对象如image或surface都包含在DataNode中,这些DataNode描述数据本身(mitk::BaseData及其派生类),如: - 以二维或三维的渲染方式呈现(一个mitk::Mapper列表);- 与…...
建设厅业绩可查询网站地址/网络推广网站有哪些
山西太原linux运维培训班价格思诺培训价格表。在所有市场中,对专业技能进行的培训和认证的需求都是存在的,因为企业需要它们,井且其他先进技术不断涌现。企业需要的人才不仅仅拥有产品或技术上的技能一一他们必须有能力满足特定网络工作角色中…...
怎么提高网站的权重/友链申请
IDEA整合GitLab,并进行分支使用一:IDEA安装GitLab插件二:检出项目三:将总分支代码更新到自己的分支中总结步骤3.1介绍3.2 切换总分支,更新代码3.3 将最新代码合并到自己的分支中3.4 push当前master分支的代码到自己的远…...
网站建设教程 三级分销/湘潭seo快速排名
2019独角兽企业重金招聘Python工程师标准>>> 这里是一个用Eclipse的JUnit4教程: 首先,在项目下建立一个test包,然后再就是新建测试类,右键,选择JUnit Test Case,如下图: 然后选择JUnit4&#…...
公司做网站设计要注意/南京谷歌推广
上个月把VPS迁到budgetVM,终于不用再受digitalOcean的气了,入手很方便,重点是支持支付宝付款——paypal的界面真是不习惯,开通速度挺快的,1G的内存够我折腾一段时间了~,额外送了俩IP,过段时间再…...