加密解决方案-Java实现RSA非对称加密

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 本文基于RSA加密算法原理,详述什么是RSA算法、RSA加密解密原理进行实践的过程。

一、什么是RSA加密算法:

RSA加密算法是一种非对称加密算法,所谓非对称,就是指该算法加密和解密使用不同的密钥,即使用加密密钥进行加密、解密密钥进行解密。在RAS算法中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的,由于无法计算出大数n的欧拉函数phi(N),所以不能根据PK计算出SK。

也就是说,对极大整数做因数分解的难度决定了RSA算法的可靠性。理论上,只要其钥匙的长度n足够长,用RSA加密的信息实际上是不能被解破的。

RSA算法通常是先生成一对RSA密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位(对标文章结尾补充说明)。这就使加密的计算量很大。为减少计算量,在传送信息时,常采用传统加密方法与公开密钥加密方法相结合的方式,即信息采用改进的DES或IDEA密钥加密,然后使用RSA密钥加密对话密钥和信息摘要。对方收到信息后,用不同的密钥解密并可核对信息摘要。

二、RSA加密方式

RSA加密是对明文的E次方后除以N后求余数的过程。所以,只要知道E和N任何人都可以进行RSA加密了,所以说E、N是RSA加密的密钥,也就是说E和N的组合就是公钥,我们用(E,N)来表示公钥:

密文=明文EmodN密文=明文EmodN

三、RSA解密过程

密文进行D次方后除以N的余数就是明文,这就是RSA解密过程。知道D和N就能进行解密密文了,所以D和N的组合就是私钥:

明文=密文DmodN明文=密文DmodN

四、进行实践

1、确定加密算法

// 加密算法privatefinalstaticStringALGORITHM_RSA="RSA";

2、生成公钥私钥密钥对

//生成公钥,私钥的密钥对publicstaticList<String>getRSAKeyString(intmodulus) throwsNoSuchAlgorithmException{
List<String>keyList=newArrayList<>(2);
//密钥对生成,生成规范-RSA算法KeyPairGeneratorkeyPairGen=KeyPairGenerator.getInstance(ALGORITHM_RSA);
//初始化模长keyPairGen.initialize(modulus);
//生成密钥对KeyPairkeyPair=keyPairGen.generateKeyPair();
StringpublicKey=Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
StringprivateKey=Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
keyList.add(publicKey);
keyList.add(privateKey);
returnkeyList;
}
// Java中RSAPublicKeySpec、X509EncodedKeySpec支持生成RSA公钥// 此处使用X509EncodedKeySpec生成publicstaticRSAPublicKeygetPublicKey(StringpublicKey) throwsException {
KeyFactorykeyFactory=KeyFactory.getInstance(ALGORITHM_RSA);
byte[] keyBytes=Base64.getDecoder().decode(publicKey);
X509EncodedKeySpecspec=newX509EncodedKeySpec(keyBytes);
return (RSAPublicKey) keyFactory.generatePublic(spec);
}
// Java中只有RSAPrivateKeySpec、PKCS8EncodedKeySpec支持生成RSA私钥// 此处使用PKCS8EncodedKeySpec生成publicstaticRSAPrivateKeygetPrivateKey(StringprivateKey) throwsException {
KeyFactorykeyFactory=KeyFactory.getInstance(ALGORITHM_RSA);
byte[] keyBytes=Base64.getDecoder().decode(privateKey);
PKCS8EncodedKeySpecspec=newPKCS8EncodedKeySpec(keyBytes);
return (RSAPrivateKey) keyFactory.generatePrivate(spec);
}

3、编写公钥加密步骤

//公钥加密publicstaticStringencryptByPublicKey(Stringdata, RSAPublicKeypublicKey)throwsException {
Ciphercipher=Cipher.getInstance(ALGORITHM_RSA);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
// 模长n转换成字节数intmodulusSize=publicKey.getModulus().bitLength() /8;
// PKCS Padding长度为11字节,所以实际要加密的数据不能要 - 11byteintmaxSingleSize=modulusSize-11;
// 切分字节数组,每段不大于 maxSingleSizebyte[][] dataArray=splitArray(data.getBytes(), maxSingleSize);
ByteArrayOutputStreamout=newByteArrayOutputStream();
// 分组加密,并将加密后的内容写入输出字节流for (byte[] s : dataArray) {
out.write(cipher.doFinal(s));
    }
// 使用Base64将字节数组转换String类型returnBase64.getEncoder().encodeToString(out.toByteArray());
}

4、编写私钥解密过程

//私钥解密publicstaticStringdecryptByPrivateKey(Stringdata, RSAPrivateKeyprivateKey)
throwsException {
Ciphercipher=Cipher.getInstance(ALGORITHM_RSA);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
// RSA加密算法的模长 nintmodulusSize=privateKey.getModulus().bitLength() /8;
byte[] dataBytes=data.getBytes();
// 之前加密的时候做了转码,此处需要使用Base64进行解码byte[] decodeData=Base64.getDecoder().decode(dataBytes);
// 切分字节数组,使每段不大于modulusSizebyte[][] splitArrays=splitArray(decodeData, modulusSize);
ByteArrayOutputStreamout=newByteArrayOutputStream();
for(byte[] arr : splitArrays){
out.write(cipher.doFinal(arr));
    }
returnnewString(out.toByteArray());
}

5、切分数组工具方法

//切分数组privatestaticbyte[][] splitArray(byte[] data,intlen){
intdataLen=data.length;
if (dataLen<=len) {
returnnewbyte[][]{data};
    }
byte[][] result=newbyte[(dataLen-1)/len+1][];
intresultLen=result.length;
for (inti=0; i<resultLen; i++) {
if (i==resultLen-1) {
intslen=dataLen-len*i;
byte[] single=newbyte[slen];
System.arraycopy(data, len*i, single, 0, slen);
result[i] =single;
break;
        }
byte[] single=newbyte[len];
System.arraycopy(data, len*i, single, 0, len);
result[i] =single;
    }
returnresult;
}

6、主方法

publicstaticvoidmain(String[] args) throwsException {
Stringmessage="红色基因是一种革命精神的传承,鼓舞着一代又一代中华儿女为了实现中华民族的伟大复兴的中国梦而坚强自立、坚持梦想、勇往直前!";
// 使用字符串生成公钥、私钥完成加解密List<String>keyStringList=AsyEnc.getRSAKeyString(1024);
StringpukString=keyStringList.get(0);
StringprkString=keyStringList.get(1);
System.out.println("公钥:"+pukString);
System.out.println("私钥:"+prkString);
// 生成公钥RSAPublicKeypuk=AsyEnc.getPublicKey(pukString);
// 生成私钥RSAPrivateKeyprk=AsyEnc.getPrivateKey(prkString);
// 加密messageStringencryptedMsg=AsyEnc.encryptByPublicKey(message, puk);
StringdecryptedMsg=AsyEnc.decryptByPrivateKey(encryptedMsg, prk);
System.out.println("加密后 message : "+encryptedMsg);
System.out.println("解密后 message : "+decryptedMsg);
}

7、测试执行

image.png

8、补充说明

主方法中 :getRSAKeyString(1024)为自设定mod值,也为下图中RAS密钥长度

           image.png

目录
相关文章
|
1月前
|
关系型数据库 MySQL Java
【IDEA】java后台操作mysql数据库驱动常见错误解决方案
【IDEA】java后台操作mysql数据库驱动常见错误解决方案
68 0
|
7天前
|
安全 Java 开发者
Java多线程编程中的常见问题与解决方案
本文深入探讨了Java多线程编程中常见的问题,包括线程安全问题、死锁、竞态条件等,并提供了相应的解决策略。文章首先介绍了多线程的基础知识,随后详细分析了每个问题的产生原因和典型场景,最后提出了实用的解决方案,旨在帮助开发者提高多线程程序的稳定性和性能。
|
13天前
|
人工智能 监控 数据可视化
Java智慧工地信息管理平台源码 智慧工地信息化解决方案SaaS源码 支持二次开发
智慧工地系统是依托物联网、互联网、AI、可视化建立的大数据管理平台,是一种全新的管理模式,能够实现劳务管理、安全施工、绿色施工的智能化和互联网化。围绕施工现场管理的人、机、料、法、环五大维度,以及施工过程管理的进度、质量、安全三大体系为基础应用,实现全面高效的工程管理需求,满足工地多角色、多视角的有效监管,实现工程建设管理的降本增效,为监管平台提供数据支撑。
30 3
|
19天前
|
Java API Apache
|
1月前
|
Java Maven 数据安全/隐私保护
如何实现Java打包程序的加密代码混淆,避免被反编译?
【10月更文挑战第15天】如何实现Java打包程序的加密代码混淆,避免被反编译?
47 2
|
1月前
|
Java
短频快task的java解决方案
本文探讨了Java自带WorkStealingPool的缺陷,特别是在任务中断方面的不足。普通线程池在处理短频快任务时存在锁竞争问题,导致性能损耗。文章提出了一种基于任务窃取机制的优化方案,通过设计合理的窃取逻辑和减少性能损耗,实现了任务的高效执行和资源的充分利用。最后总结了不同场景下应选择的线程池类型。
|
1月前
|
小程序 Java
小程序访问java后台失败解决方案
小程序访问java后台失败解决方案
44 2
|
1月前
|
算法 安全 Go
RSA加密算法详解与Python和Go实现
RSA加密算法详解与Python和Go实现
97 1
|
1月前
|
算法 安全 网络安全
使用 Python 实现 RSA 加密
使用 Python 实现 RSA 加密
55 2
|
1月前
|
安全 算法 Java
数据库信息/密码加盐加密 —— Java代码手写+集成两种方式,手把手教学!保证能用!
本文提供了在数据库中对密码等敏感信息进行加盐加密的详细教程,包括手写MD5加密算法和使用Spring Security的BCryptPasswordEncoder进行加密,并强调了使用BCryptPasswordEncoder时需要注意的Spring Security配置问题。
140 0
数据库信息/密码加盐加密 —— Java代码手写+集成两种方式,手把手教学!保证能用!