加密解决方案-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

目录
相关文章
|
28天前
|
关系型数据库 MySQL Java
【IDEA】java后台操作mysql数据库驱动常见错误解决方案
【IDEA】java后台操作mysql数据库驱动常见错误解决方案
50 0
|
1天前
|
数据库 数据安全/隐私保护 Windows
Windows远程桌面出现CredSSP加密数据修正问题解决方案
【10月更文挑战第30天】本文介绍了两种解决Windows系统凭据分配问题的方法。方案一是通过组策略编辑器(gpedit.msc)启用“加密数据库修正”并将其保护级别设为“易受攻击”。方案二是通过注册表编辑器(regedit)在指定路径下创建或修改名为“AllowEncryptionOracle”的DWORD值,并将其数值设为2。
10 3
|
2天前
|
Java API Apache
|
24天前
|
Java
短频快task的java解决方案
本文探讨了Java自带WorkStealingPool的缺陷,特别是在任务中断方面的不足。普通线程池在处理短频快任务时存在锁竞争问题,导致性能损耗。文章提出了一种基于任务窃取机制的优化方案,通过设计合理的窃取逻辑和减少性能损耗,实现了任务的高效执行和资源的充分利用。最后总结了不同场景下应选择的线程池类型。
|
28天前
|
小程序 Java
小程序访问java后台失败解决方案
小程序访问java后台失败解决方案
42 2
|
29天前
|
算法 安全 Go
RSA加密算法详解与Python和Go实现
RSA加密算法详解与Python和Go实现
72 1
|
28天前
|
存储 前端开发 Java
浅谈Java中文乱码浅析及解决方案
浅谈Java中文乱码浅析及解决方案
42 0
|
28天前
|
Java
Error:java: 无效的目标发行版: 11解决方案
Error:java: 无效的目标发行版: 11解决方案
63 0
|
29天前
|
安全 网络协议 网络安全
【HTTPS】对称加密和非对称加密
【HTTPS】对称加密和非对称加密
29 0
|
1月前
|
Java Maven Spring
用Spring导致的无法运行Java文件的问题的解决方案
本文提供了解决在IntelliJ IDEA社区版中使用Spring Initializr插件创建Spring项目后,Java文件无法运行的问题的方法,主要是通过加载Maven项目来解决。
58 0