当前位置: 首页 > article >正文

Java RSA密钥转换,从RSAPrivateKey得到RSAPublicKey

概述:

在Java编程中,我们经常用到如下一段代码来生成RSA公私钥,分别拿到公私钥然后加解密计算:

KeyPairGenerator keyPairGen;
keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(2048, new SecureRandom());
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

本文讲述仅有RSAPrivateKey privateKey,没有KeyPair keyPair,如何通过RSAPrivateKey privateKey得到RSAPublicKey publicKey

分析RSAPrivateKey:

RSAPrivateKey privateKey,通过函数privateKey.getAlgorithm()查看,或者通过privateKey.getEncoded()数据分析,可以得到默认是PKCS#8格式,
privateKey.getEncoded()的数据例子:

在这里插入图片描述
通过TLV分析工具查看:
在这里插入图片描述
在这里插入图片描述
可以看到,RSAPrivateKey privateKey里面,RSA密钥的参数N、E、D、P、Q等都包含在内的。
其中N、E是私钥对应的公钥RSAPublicKey publicKey,所需的全部参数。
因此,是可以从RSAPrivateKey privateKey拿到对应的RSAPublicKey publicKey

开发环境:

`IDE:eclipse版本4.20.0
编译器:JDK1.8
导入的包:bouncycastle,jar文件名bcprov-jdk18on-171.jar

转换函数:

public static byte[] p8PrvKey2P1PrvKeyBytes(PrivateKey privateKey) throws Exception {
      PrivateKeyInfo privateKeyInfo = PrivateKeyInfo.getInstance(privateKey.getEncoded());
       ASN1Encodable privateKeyPKCS1ASN1Encodable = privateKeyInfo.parsePrivateKey();
       ASN1Primitive asn1Primitive = privateKeyPKCS1ASN1Encodable.toASN1Primitive();        
       return asn1Primitive.getEncoded();
   } 
   	
public static RSAPublicKey rsaGetPubKeyFromPriKey(RSAPrivateKey privateKey) {
	RSAPublicKeySpec rsaPubKeySpec = null;
	KeyFactory keyFactory = null;
	org.bouncycastle.asn1.pkcs.RSAPrivateKey rP = null;

	try {
		keyFactory = KeyFactory.getInstance("RSA");
		rP = org.bouncycastle.asn1.pkcs.RSAPrivateKey.getInstance(p8PrvKey2P1PrvKeyBytes(privateKey));
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	
	try {
		keyFactory = KeyFactory.getInstance("RSA");
		rsaPubKeySpec = new RSAPublicKeySpec(rP.getModulus(), rP.getPublicExponent());
		return (RSAPublicKey) keyFactory.generatePublic(rsaPubKeySpec);
	} catch (InvalidKeySpecException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
		return null;
	} catch (NoSuchAlgorithmException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
		return null;
	}
}

注意导入bcprov-jdk18on-171.jar中类

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;

还要注意,bouncycastle里面有RSAPrivateKey
jdk自带公共:java.security.interfaces.RSAPrivateKey;

bouncycastle包里面的:org.bouncycastle.asn1.pkcs.RSAPrivateKey

测试代码:

public static void main(String[] args) {		
	testRsa();
}

public static void testRsa() {
	KeyPairGenerator keyPairGen;
	try {
		keyPairGen = KeyPairGenerator.getInstance("RSA");
		
		keyPairGen.initialize(2048, new SecureRandom());
   
		KeyPair keyPair = keyPairGen.generateKeyPair();

		RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
		
		//System.out.println("privateKey:" + hexToString(privateKey.getEncoded(), 0, privateKey.getEncoded().length));
		//RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
		RSAPublicKey publicKey = rsaGetPubKeyFromPriKey(privateKey);
		
		String out1 = encrypt("1234567890", publicKey);
		System.out.println("encrypt:" + out1);
		String out2 = decrypt(out1, privateKey);
		System.out.println("decrypt:" + out2);
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}        
}


public static String encrypt(String str, RSAPublicKey publicKey) throws Exception {
	//base64编码的公钥
	//byte[] decoded = Base64.getDecoder().decode(publicKey);
	//RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
	//RSA加密
	Cipher cipher = Cipher.getInstance("RSA");
	cipher.init(Cipher.ENCRYPT_MODE, publicKey);
	String outStr = Base64.getEncoder().encodeToString(cipher.doFinal(str.getBytes("UTF-8")));
	return outStr;
}
public static String decrypt(String str, RSAPrivateKey privateKey) throws Exception {
	//64位解码加密后的字符串
	byte[] inputByte = Base64.getDecoder().decode(str);
	//base64编码的私钥
	//byte[] decoded = Base64.getDecoder().decode(privateKey);
	//RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
	//RSA解密
	Cipher cipher = Cipher.getInstance("RSA");
	cipher.init(Cipher.DECRYPT_MODE, privateKey);
	String outStr = new String(cipher.doFinal(inputByte));
	return outStr;
}

测试结果:

在这里插入图片描述


http://www.kler.cn/a/18335.html

相关文章:

  • Qwen2 系列大型语言模型
  • 第二天python笔记
  • 从0开始深度学习(28)——序列模型
  • 快速学习Serde包实现rust对象序列化
  • 树-好难-疑难_GPT
  • vue+Leaflet.PM插件实现创建和编辑几何图形(点、线、面、圆等)
  • HTML5字体集合的实践经验
  • ( 位运算 ) 268. 丢失的数字 ——【Leetcode每日一题】
  • 当生命里有程序来串门——一个北邮信通大一学生的漫谈
  • Linux权限 - 概念与管理 | 文件权限的修改与转让 【详解】
  • 给你安利一款不需要魔法就能免费使用的idea插件Bito-ChatGPT
  • IO-Netty
  • Linux_红帽8学习笔记分享_10(SELinux管理与防火墙)
  • SpringBoot——入门程序的简单介绍
  • wiringPi常用函数
  • 使用 ChatGPT 辅助学习——为自己找一个老师
  • docker部署SpringBoot项目
  • 【sop】基于灵敏度分析的有源配电网智能软开关优化配置(Matlab代码实现)
  • Linux 安装 NFS 实现文件目录共享
  • SpringBoot创建和使用
  • RESTful风格(个人笔记)
  • MySQL事务:原理、类型和使用场景
  • taro小程序中如何引入css_moudle?配置后不生效的解决方法
  • HTML 中的常用标签用法
  • Vue中的路由设置
  • 学习大数据有推荐的么