RSA算法是使用整数进行加密和解密运算的,
加密:在RSA公钥中包含了两个信息:公钥对应的整数e和用于取模的整数n。对于明文数字m,计算密文的公式是: m^e mod n.
解密:跟加密类似,私钥对应的指数e和用于取模的整数m.其中模m和加密时的加密的模n完全相同。对于密文数字d,计算公式d^e mod n。加密和解密最大的不同在于幂e不同。
本实例以加密和解密一个字符串”I am a student” 为例,演示了如何使用生成的RSA公钥文件进行加密。
使用RSA算法加密的技术要点如下:
1.用FileInputStream获取公钥
2.用RSAPublicKey类中的方法获取公钥的参数(e,n)
3.用BigInteger m=new BigInteger(ptext);来获取明文整数(m)
4.执行计算
使用RSA算法解密的技术要点如下:
1.利用FileInputStream读取密文Enc_RSA.dat
2.利用RSAPrivateKey类的readObject()方法获取私钥
3.利用RSAPrivateKey类获取私钥的BigInteger类型的参数(e,m)
4.利用BigInteger的modPow()方法执行解密的计算
5.解析出明文整型数对应的字符串
package core;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStreamWriter;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
/**
* RSA算法加密和解密
* */
public class Password_Test {
public static void main(String[] args) {
try {
new Password_Test();
Encryption_RSA();
Decryption_RSA();
} catch (Exception e) {
e.printStackTrace();
}
}
public Password_Test() throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");// 生成实现RSA算法的KeyPairGenerator对象
kpg.initialize(1024);// 初始化确定密钥的大小
KeyPair kp = kpg.generateKeyPair();// 生成密钥对
PublicKey pbkey = kp.getPublic();// 创建公钥
PrivateKey prkey = kp.getPrivate();// 创建私钥
/* 保存公钥和私钥 */
// 保存公钥
FileOutputStream file1 = new FileOutputStream("Skey_RSA_pub.dat");
ObjectOutputStream ob1 = new ObjectOutputStream(file1);// 创建ObjectOutputStream
ob1.writeObject(pbkey);
// 保存私钥
FileOutputStream file2 = new FileOutputStream("Skey_RSA_priv.dat");
ObjectOutputStream ob2 = new ObjectOutputStream(file2);// 创建ObjectOutputStream
ob2.writeObject(prkey);
//关闭流
ob1.close();
ob2.close();
}
public static void Encryption_RSA() throws Exception{
System.out.println("根据公钥生成密文:");
String string="I am a student";
//获取公钥
FileInputStream f_in=new FileInputStream("Skey_RSA_pub.dat");
ObjectInputStream o_in=new ObjectInputStream(f_in);
RSAPublicKey pbk=(RSAPublicKey) o_in.readObject();
//获取参数e,n
BigInteger e=pbk.getPublicExponent();//返回此公钥的指数
BigInteger n=pbk.getModulus();//返回此公钥的模
System.out.println("公钥的指数 e="+e);
System.out.println("公钥的模 n="+n);
//明文 bit
byte bt[]=string.getBytes("UTF8");
BigInteger bit=new BigInteger(bt);
//计算密文c,打印
BigInteger c=bit.modPow(e, n);
System.out.println("生成密文为: "+ c+"\n");
//保存密文
String save=c.toString();
BufferedWriter out=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("Enc_RSA.dat")));//保存密文
out.write(save, 0, save.length());
o_in.close();
out.close();
}
public static void Decryption_RSA() throws Exception{
System.out.println("根据私钥破解密文");
//读取密文
BufferedReader in=new BufferedReader(new InputStreamReader(new FileInputStream("Enc_RSA.dat")));
String ctext=in.readLine();
BigInteger d=new BigInteger(ctext);
//读取私钥
FileInputStream f=new FileInputStream("Skey_RSA_priv.dat");
ObjectInputStream b=new ObjectInputStream(f);
RSAPrivateKey prk=(RSAPrivateKey) b.readObject();
//获取私钥指数和模
BigInteger e=prk.getPrivateExponent();//返回私钥的指数
BigInteger m=prk.getModulus();//返回私钥的模
BigInteger jie=d.modPow(e, m);
System.out.println("私钥的指数 e= "+e);
System.out.println("私钥的模 m="+m);
System.out.println("解密结果 : "+jie);
byte mt[]=jie.toByteArray();
System.out.print("解密后的文本内容为: ");
for (int i = 0; i < mt.length; i++) {
System.out.print((char)mt[i]);
}
in.close();
b.close();
}
}
源程序解读
(1)Password_Test()构造方法中主要介绍了RSA公钥和私钥文件的生成。创建密钥对生成器KeyPairGenerator,指定非对称加密所使用的算法,常用的有RSA、DSA等。
初始化密钥生成器。关于密钥长度,对于RSA算法,这里指定的其实是RSA算法中所用的模的位数,可以在512-2048之间。
通过KeyPair类的getPublic()和getPrivate()方法获得公钥和私钥对象.
(2)Encryption_RSA()方法中主要介绍了如何使用生成好的RSA公钥文件对字符串进行加密。
获取公钥。从生成的公钥文件Skey_RSA_pub.dat中读取公钥,由于生成该文件时使用的是RSA算法,因此从文件读取公钥对象后强制转换为RSAPublicKey类型,以便后续读取RSA算法所需要的参数。
获取明文。明文是一个字符串,为了用整数表达这个字符串,先使用字符串的getByte()方法将其转换为byte类型数组,它其实是字符串中各个字符的二进制表达方式,这一串二进制数转换为一个整数将非常大,因此仍旧使用BigInteger类将这个二进制串转换为整型。
执行加密计算。计算公式: m^e mod n。BigInteger类中已经提供了方法modPow()来执行这个计算。方法返回的结果为密文。
(3)Decryption_RSA()法中主要介绍了如何使用生成好的RSA公钥文件对字符串进行加密。
从生成的密文文件Enc_RSA.dat中读取密文,由于加密后只是一行字符串,因此只要一条readLine()语句即可
从生成的私钥文件Skey_RSA_priv.dat中读取私钥,由于生成该私钥使用的算法是RSA算法,因此从文件读取公钥对象后强制转换为RSAPrivateKey类型,以便后续读取RSA所需的参数。在获取私钥的参数(e,m)的时候可以使用RSAPrivateKey类的getPrivateExponent()和getModulus()方法分别获得私钥中e和m的值。RSA算法解密的结果jie是一个很大的整数,为了计算出其对应的字符串的值,先使用BigInteger类的toByteArray()方法得到代表该整型数的字节数组,然后将数组中每个元素转换为字符,组成字符串。
使用BigInteger的modPow()方法计算前面的公式: d^e mod n,方法返回的结果即是明文。