Android中RSA公钥加密后Java服务端私钥无法解密问题解决

工作中经常需要Android客户端使用RSA公钥加密敏感数据,服务端再使用配套的RSA私钥解密数据,最近碰到一个问题,使用RSA加密后服务端无法解密,查阅相关资料后,发现是这个问题:

RSA操作的填充方式不对。

android系统的RSA实现是"RSA/None/NoPadding",

而标准JDK实现是"RSA/None/PKCS1Padding" ,

那解决方法是加解密填充方法改成一致呗。

比如填充方式统一改成:RSA/ECB/PKCS1Padding

另外注意服务端用的是java.util.Base64

客户端用的是android.util.Base64

服务端RsaUtils.java

package com.figo.study2024.utils;import org.springframework.beans.factory.annotation.Value;import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class RsaUtils {/*** 加密算法.*/public static final String KEY_ALGORITHM_KEY = "RSA";public static final String KEY_ALGORITHM = "RSA/ECB/PKCS1Padding";/*** 私钥解密.** @param privateKeyString 私钥* @param text             待解密的文本* @return 解密后的文本*/public static String decryptByPrivateKey(String privateKeyString, String text) {try {PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyString));KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM_KEY);PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] result = cipher.doFinal(Base64.getDecoder().decode(text));return new String(result);} catch (Exception e) {e.printStackTrace();return null;}}/*** 公钥加密.** @param publicKeyString 公钥* @param text            待加密的文本* @return 加密后的文本*/public static String encryptByPublicKey(String publicKeyString, String text) {try {X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyString));KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM_KEY);PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] result = cipher.doFinal(text.getBytes());return new String(Base64.getEncoder().encode(result));} catch (Exception e) {e.printStackTrace();return null;}}/*** 构建RSA密钥对.** @return 生成后的公私钥信息*/public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM_KEY);keyPairGenerator.initialize(2048);KeyPair keyPair = keyPairGenerator.generateKeyPair();RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();String publicKeyString = new String(Base64.getEncoder().encode(rsaPublicKey.getEncoded()));String privateKeyString = new String(Base64.getEncoder().encode(rsaPrivateKey.getEncoded()));return new RsaKeyPair(publicKeyString, privateKeyString);}/*** RSA密钥对对象.*/public static class RsaKeyPair {public RsaKeyPair(String publicKey, String privateKey) {this.publicKey = publicKey;this.privateKey = privateKey;}/*** 公钥.*/private String publicKey;/*** 私钥.*/private String privateKey;public String getPublicKey() {return publicKey;}public void setPublicKey(String publicKey) {this.publicKey = publicKey;}public String getPrivateKey() {return privateKey;}public void setPrivateKey(String privateKey) {this.privateKey = privateKey;}}public static void main(String[] args){// 生成公私钥对RsaKeyPair keyPair = null;try {keyPair = generateKeyPair();} catch (NoSuchAlgorithmException e) {e.printStackTrace();}System.out.println("keyPair.getPublicKey() = " + keyPair.getPublicKey());System.out.println("keyPair.getPrivateKey() = " + keyPair.getPrivateKey());String text = "figo";System.out.println("原明文 = " + text);// 公钥加密String encryptStr = RsaUtils.encryptByPublicKey(keyPair.getPublicKey(), text);// 私钥解密String plain = RsaUtils.decryptByPrivateKey(keyPair.getPrivateKey(), encryptStr);
//        String publicKey="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA42XXuzyZROCrRHVlHiDotl90KG0gSrrZzPuMrl608Pj2MU9sZAGpsMcbJ627Uv6vrzGigeC0qCdv7cRTW2CuF6jQhIYjo6bmNtVK+ysvWl0KEacAik2gvL4g/686J/7FBnv4xZywQ1+A2Bevh4ZaEVqE09zC0TJM8DU5mfalOGnA13m7QS9bvjPB27Tzl2TA1SYE7+FfI1mTycZJmvhEv6+jiWxS/08OASsEPzdB/j5vn4Y/WvsgYw+3ZoahfvdpMCIhlpW6Wsf9dhGcPtYqfGpn6ldh6b+nJQ0NGpS6c1ov16RYGwZFOWQfpbTVKF0enVMumXwN+OWgr0NQxP7nBQIDAQAB";
//        String privateKey="MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDjZde7PJlE4KtEdWUeIOi2X3QobSBKutnM+4yuXrTw+PYxT2xkAamwxxsnrbtS/q+vMaKB4LSoJ2/txFNbYK4XqNCEhiOjpuY21Ur7Ky9aXQoRpwCKTaC8viD/rzon/sUGe/jFnLBDX4DYF6+HhloRWoTT3MLRMkzwNTmZ9qU4acDXebtBL1u+M8HbtPOXZMDVJgTv4V8jWZPJxkma+ES/r6OJbFL/Tw4BKwQ/N0H+Pm+fhj9a+yBjD7dmhqF+92kwIiGWlbpax/12EZw+1ip8amfqV2Hpv6clDQ0alLpzWi/XpFgbBkU5ZB+ltNUoXR6dUy6ZfA345aCvQ1DE/ucFAgMBAAECggEBAMYrJbMFX2iYBolVaTa1ZTgxvU/RsfeOGGq7uWDoJfVucVaNqZ8Jl/D3wyF0FLCCRWZ+8ekPg0Cbhb6GfkI+4di6hGVJZNukgjG89WgnvU+Zj0HM8PqWJgL2ClnoQd1C+D7rYOQN5coA+47WLWEE448F/IWJeLnIhSY8rCMRv/CFC6BQXgftQFGIzpnCPE6vIfVKlbP0gmhBlD15VXUQ9QWuTDY3Nu8dN0JvsRQggH6X2TjX1MhrW/l/ClacV+xBmk8L8FwBxpqvLV19ujYLgUdNIRoiAXC/e7to0LvOhbFREz/61LK92Z/Z47g8xo6+CQ9xKGI+dAarZqC499yCjoECgYEA/uNoiHhBQy2/T+0dCfPjKKaggSx53y+lqCnCgvhy07hO15NRfJaTkXpdyenzRzSp5uO72QzrKxY/KGr6kkQt1acNVBB7T4fz0Jzd89hvBGhXEbJhKdl1qjfuUjp8xfO8Or2M55nAeYJCvHysxgs3fu7kQZtJxGW/coec9a5XaaECgYEA5GO9gvId9jeQokaooalfI+q10igzxsUAWLrA+vkuVfUEWndVVNh1Y8//oACa3fctczXymVSun1RSkdEnkCArPVG22eLp+U+HTqorDG73KRP2Lox3hwspW98ns/cdHdJqd1qjDWuUg1TTbGSxl1IpVN+ZYPjE4G+6TpIUkvDZKuUCgYBQlrQpWeRAiklPyweAaxUqeCyNSvOphlYZKkLuyAD+QerjrBd6jd1QhOD8gzTBEbyaXOy6vqPoNpt3ewOIlXfscmn7Z06lobWMAt0GSSsouJi25rBj2/ahABgg9Y8Xw22DIQVZALrjcDULhVvXLhq4zm1q9N9I8maqnogZAatvoQKBgQDhP+2cxCYAu/SN15phNqZ6yfXg+311QL6CxE2oOTIV3L0abC9gqsu8UVwP9gjHegz9X+uQhhBjW8rDvcCDSPbcV0c7xax1EpakYvhqHtbtUJ6wciFAsyVrUr/ZopK44tnWNTIy/jNPA84xTW5Ji+LvrkebeD7UC913uGNKOPg2cQKBgC/n6d1VXKqhPBU58MdJj+1GoV8BZj/p+ja7jQVT/slYG/DgNho7PZ5+At8ehryYPO2MmPkxr1LiCedclvGpAPeCD9vtST43nuVLU7qkdxmC11iriobbgu3ZkUWSyJoy/3uBgZWHL8bofDsnonLLZFwdZEat0ROkEs3ttEJ9Nqxf";// 公钥加密
//        String encryptStr = RsaUtils.encryptByPublicKey(publicKey, text);System.out.println("密文 = " + encryptStr);// 私钥解密
//        encryptStr="gdKu0MC4M30O2pUTm3IxObYT/XtSwWlp9F8jCoTYt57L2kan0TsKFQlUXoYZSFnXH/bTymEGGNYVQ06MX6ZwjIJYBW73tbQauJ4L69WpfXDOP8z+IYBfSTCQZGO0c1A3Qo5Nq0ZOTImrHvp8lEmyf0B526KOinALLFWxoOxt/f0QCQIrty3AMUpyc4sdB/DTWWYhZVCwY/6cGBUQHrgDaeXXjn9In5kqJZkgEhlxdUNUpAkixYBB/jS0iDyzyPH+9BXhZejypTGtnAkp/bs4qge8Aio2Xnqf/R6uMUEpse6ymJfsfnpfLHfWvJ9ecZqLL+UVWLWjrLebE8rFlsxzag==";
//        String plain = RsaUtils.decryptByPrivateKey(privateKey, encryptStr);System.out.println("解密后 = " + plain);}}

客户端RsaUtils.java

package com.figo.myapplication.utils;import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import android.util.Base64;
public class RsaUtils {/*** 加密算法.*/public static final String KEY_ALGORITHM_KEY = "RSA";public static final String KEY_ALGORITHM = "RSA/ECB/PKCS1Padding";/*** 私钥解密.** @param privateKeyString 私钥* @param text             待解密的文本* @return 解密后的文本*/public static String decryptByPrivateKey(String privateKeyString, String text) {try {PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decode(privateKeyString,Base64.DEFAULT));KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM_KEY);PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] result = cipher.doFinal(Base64.decode(text,Base64.NO_WRAP));return new String(result);} catch (Exception e) {e.printStackTrace();return null;}}/*** 公钥加密.** @param publicKeyString 公钥* @param text            待加密的文本* @return 加密后的文本*/public static String encryptByPublicKey(String publicKeyString, String text) {try {X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decode(publicKeyString,Base64.DEFAULT));KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM_KEY);PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, publicKey);byte[] result = cipher.doFinal(text.getBytes());return new String(Base64.encode(result,Base64.NO_WRAP));} catch (Exception e) {e.printStackTrace();return null;}}/*** 构建RSA密钥对.** @return 生成后的公私钥信息*/public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM_KEY);keyPairGenerator.initialize(2048);KeyPair keyPair = keyPairGenerator.generateKeyPair();RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();//必须使用NO_WRAP,否则会出现换行符,导致服务端无法解密String publicKeyString = new String(Base64.encode(rsaPublicKey.getEncoded(),Base64.NO_WRAP));String privateKeyString = new String(Base64.encode(rsaPrivateKey.getEncoded(),Base64.NO_WRAP));return new RsaKeyPair(publicKeyString, privateKeyString);}/*** RSA密钥对对象.*/
//    @Data
//    @NoArgsConstructor
//    @AllArgsConstructorpublic static class RsaKeyPair {public RsaKeyPair(String publicKey, String privateKey) {this.publicKey = publicKey;this.privateKey = privateKey;}/*** 公钥.*/private String publicKey;/*** 私钥.*/private String privateKey;public String getPublicKey() {return publicKey;}public void setPublicKey(String publicKey) {this.publicKey = publicKey;}public String getPrivateKey() {return privateKey;}public void setPrivateKey(String privateKey) {this.privateKey = privateKey;}}public static void main(String[] args){// 生成公私钥对RsaKeyPair keyPair = null;try {keyPair = generateKeyPair();} catch (NoSuchAlgorithmException e) {e.printStackTrace();}System.out.println("keyPair.getPublicKey() = " + keyPair.getPublicKey());System.out.println("keyPair.getPrivateKey() = " + keyPair.getPrivateKey());// 公钥加密String text = "zhu";String encryptStr = RsaUtils.encryptByPublicKey(keyPair.getPublicKey(), text);System.out.println("密文 = " + encryptStr);// 私钥解密String plain = RsaUtils.decryptByPrivateKey(keyPair.getPrivateKey(), encryptStr);System.out.println("明文 = " + plain);}}

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

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

相关文章

Android中如何动态的调整Dialog的背景深暗

本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点 在 Android 开发中,当你使用 Dialog 或 DialogFragment 时,可以通过设置 Window 的背景变暗来突出它的可见性。这个效果…

【密码学】分组密码

文章目录 分组密码的模式分组密码与流密码模式明文分组与密文分组 ECB模式ECB定义ECB特点对ECB模式的攻击改变分组顺序攻击 CBC模式CBC定义初始化向量IVCBC特点对CBC模式的攻击对初始向量进行反转攻击填充提示攻击 CFB模式CFB定义对CFB模式的攻击重放攻击 OFB模式OFB定义CFB模式…

05-5.5.3 并查集的进一步优化

👋 Hi, I’m Beast Cheng 👀 I’m interested in photography, hiking, landscape… 🌱 I’m currently learning python, javascript, kotlin… 📫 How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以…

游戏心理学Day23

游戏中的道德与文化 游戏与道德 道德在汉语中最早可追溯到老子的道德经,老子说道生之,德畜之,物行之,势成之,是以万物莫不遵循而贵德。道之贵,德之贵,夫莫之命,而常于自然。其中&a…

全面分析一下前端框架Angular的来龙去脉,分析angular的技术要点和难点,以及详细的语法和使用规则,底层原理-小白进阶之路

Angular 前端框架全面分析 Angular 是一个由 Google 维护的开源前端框架。它最早在 2010 年发布,最初版本称为 AngularJS。2016 年,团队发布了一个完全重写的版本,称为 Angular 2,之后的版本(如 Angular 4、Angular 5…

什么是CSS原子化?

CSS原子化,也被称为功能性CSS或工具类CSS,是一种构建样式表的方法,它将传统CSS中的“多属性-多值”类转变为“单属性-单值”的类。这种方法最主要的特点是提高了样式的可复用性和模块化程度。 CSS原子化的详细说明: 结构和命名 …

【LocalAI】(13):LocalAI最新版本支持Stable diffusion 3,20亿参数图像更加细腻了,可以继续研究下

最新版本v2.17.1 https://github.com/mudler/LocalAI/releases Stable diffusion 3 You can use Stable diffusion 3 by installing the model in the gallery (stable-diffusion-3-medium) or by placing this YAML file in the model folder: Stable Diffusion 3 Medium 正…

PriorityQueue详解(含动画演示)

目录 PriorityQueue详解1、PriorityQueue简介2、PriorityQueue继承体系3、PriorityQueue数据结构PriorityQueue类属性注释完全二叉树、大顶堆、小顶堆的概念☆PriorityQueue是如何利用数组存储小顶堆的?☆利用数组存储完全二叉树的好处? 4、PriorityQueu…

python json反序列化为对象

在Python中,将JSON数据反序列化为对象通常意味着将JSON格式的字符串转换为一个Python的数据结构(如列表、字典)或者一个自定义的类实例。虽然Python的标准库json模块不提供直接将JSON数据映射到类的实例的功能,但我们可以通过一些…

React AntDesign Layout组件布局刷新页面错乱闪动

大家最近在使用React AntDesign Layout组件布局后刷新页面时,页面布局错乱闪动 经过组件属性的研究才发现,设置 hasSider 为 true 就能解决上面的问题,耽搁了半天的时间,接着踩坑接着加油!!! …

pytorch实现的面部表情识别

一、绪论 1.1 研究背景 面部表情识别 (Facial Expression Recognition ) 在日常工作和生活中,人们情感的表达方式主要有:语言、声音、肢体行为(如手势)、以及面部表情等。在这些行为方式中,面部表情所携带的表达人类…

QT/QMessageBox/QTimerEvent/使用定时器制作一个闹钟

1.使用定时器制作一个闹钟 代码: widget.cpp: #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget), speecher(new QTextToSpeech(this))//给语音对象申请空间 {ui->setup…

SQL找出所有员工当前薪水salary情况

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 描述 有一个薪水表…

Debian Linux安装minikubekubectl

minikube&kubectl minkube用于在本地开发环境中快速搭建一个单节点的Kubernetes集群,还有k3s,k3d,kind都是轻量级的k8skubectl是使用K8s API 与K8s集群的控制面进行通信的命令行工具 这里使用Debian Linux演示,其他系统安装见官网,首先…

红队内网攻防渗透:内网渗透之内网对抗:横向移动篇Kerberos委派安全RBCD资源Operators组成员HTLMRelay结合

基于资源的约束委派(RBCD)是在Windows Server 2012中新加入的功能,与传统的约束委派相比,它不再需要域管理员权限去设置相关属性。RBCD把设置委派的权限赋予了机器自身,既机器自己可以决定谁可以被委派来控制我。也就是说机器自身可以直接在自己账户上配置msDS-AllowedToAct…

使用SpringCache实现Redis缓存

目录 一 什么是Spring Cache 二 Spring Cache 各注解作用 ①EnableCaching ②Cacheable ③CachePut ④CacheEvict 三实现步骤 ①导入spring cache依赖和Redis依赖 ②配置Redis连接信息 ③在启动类上加上开启spring cache的注解 ④ 在对应的方法上加上需要的注解 一 什么…

green bamboo snake

green bamboo snake 【竹叶青蛇】 为什么写这个呢,因为回县城听说邻居有人被蛇咬伤,虽然不足以危及生命,严重的送去市里了。 1)这种经常都是一动不动,会躲在草地、菜地的菜叶里面、果树上、有时候会到民房大厅休息&a…

什么是网络安全

标题:《网络安全:守护我们的数字世界》 在这个数字时代,网络已经成为了我们生活中不可或缺的一部分。我们用网络进行社交、购物、学习、工作等各种活动。然而,网络世界并非完全安全,网络安全威胁日益增加,…

Qt——系统

目录 概述 事件 鼠标事件 进入、离开事件 按下事件 释放事件 双击事件 移动事件 滚轮事件 按键事件 单个按键 组合按键 定时器 QTimerEvent QTimer 窗口事件 文件 输入输出设备 文件读写类 文件和目录信息类 多线程 常用API 线程安全 互斥锁 条件变量…

python列表常见去重方法

列表去重在python实际运用中,十分常见,也是最基础的重点知识。 1. 使用for循环实现列表去重 此方法去重后,原顺序保持不变。 # for循环实现列表去重 list1 [a, 4, 6, 4, b, hello, hello, world, 9, 9, 4, a] list2 [] for l1 in list1:…