网上说JDK1.6中已经实现了RSA算法,但是看了相关文档还是不知道怎么用,只好下了个第三方的Cipher Provider——bcprov-jdk16-143.jar,我用其中的RSA加密解密.txt文件都没问题,加密.doc文件也可以,但是解密的时候就不行了,得到的都是乱码,不是原来的明文(我用的密钥绝对正确),弄了两天都没弄好,网上找资料又找不到,基本上都是关于加密解密一段字符串而已,我需要的是加密解密一个Word文件。希望好心人高手们帮帮我,时间紧啊,是一个课程设计,过几天就要交了/(ㄒoㄒ)/
我把我的源文件贴出来,ProduceKey.java是密钥生成程序,EncryptDecrypt.java是加密解密程序//ProduceKey.javapackage fileEncryption;import java.io.*;
import java.security.*;import javax.crypto.*;public class ProduceKey{
String aName,keyName1,keyName2;
int keysize;
//构造方法1
public ProduceKey(String aname,String kname1,int size){
aName=aname;
keyName1=kname1;
keysize=size;
}
//构造方法2
public ProduceKey(String aname,String kname1,String kname2,int size){
aName=aname;
keyName1=kname1;
keyName2=kname2;
keysize=size;
}
//对称密钥的生成
public void Symmetric()throws Exception{
KeyGenerator kg=KeyGenerator.getInstance(aName);//获取密钥生成器
kg.init(keysize); //初始化密钥生成器
SecretKey skey=kg.generateKey(); //生成密钥
//通过对象序列化方式将密钥保存在文件中
FileOutputStream f=new FileOutputStream(keyName1);
ObjectOutputStream a=new ObjectOutputStream(f);
a.writeObject(skey);
}
//非对称密钥的生成
public void aSymmetric()throws Exception{
KeyPairGenerator kpg=KeyPairGenerator.getInstance(aName,new org.bouncycastle.jce.provider.BouncyCastleProvider());//获取密钥生成器
kpg.initialize(keysize); //初始化密钥生成器
KeyPair pkey=kpg.generateKeyPair(); //生成密钥
PublicKey pubkey=pkey.getPublic(); //获取公钥
PrivateKey prikey=pkey.getPrivate(); //获取私钥
//保存公钥到文件中
FileOutputStream f1=new FileOutputStream(keyName1);
ObjectOutputStream b1=new ObjectOutputStream(f1);
b1.writeObject(pubkey);
//保存私钥到文件中
FileOutputStream f2=new FileOutputStream(keyName2);
ObjectOutputStream b2=new ObjectOutputStream(f2);
b2.writeObject(prikey);
//System.out.println("已成功生成密钥!");
}
public static void main(String agrs[])throws IOException{
String filename,s1,s2;
System.out.print("请输入要生成的对称密钥文件名:");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
filename=in.readLine();
ProduceKey produce=new ProduceKey("DESede",filename,168);
try {
produce.Symmetric();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print("请输入要生成的公钥文件名:");
s1=in.readLine();
System.out.print("请输入要生成的私钥文件名:");
s2=in.readLine();
ProduceKey pair=new ProduceKey("RSA",s1,s2,1024);
try {
pair.aSymmetric();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
我把我的源文件贴出来,ProduceKey.java是密钥生成程序,EncryptDecrypt.java是加密解密程序//ProduceKey.javapackage fileEncryption;import java.io.*;
import java.security.*;import javax.crypto.*;public class ProduceKey{
String aName,keyName1,keyName2;
int keysize;
//构造方法1
public ProduceKey(String aname,String kname1,int size){
aName=aname;
keyName1=kname1;
keysize=size;
}
//构造方法2
public ProduceKey(String aname,String kname1,String kname2,int size){
aName=aname;
keyName1=kname1;
keyName2=kname2;
keysize=size;
}
//对称密钥的生成
public void Symmetric()throws Exception{
KeyGenerator kg=KeyGenerator.getInstance(aName);//获取密钥生成器
kg.init(keysize); //初始化密钥生成器
SecretKey skey=kg.generateKey(); //生成密钥
//通过对象序列化方式将密钥保存在文件中
FileOutputStream f=new FileOutputStream(keyName1);
ObjectOutputStream a=new ObjectOutputStream(f);
a.writeObject(skey);
}
//非对称密钥的生成
public void aSymmetric()throws Exception{
KeyPairGenerator kpg=KeyPairGenerator.getInstance(aName,new org.bouncycastle.jce.provider.BouncyCastleProvider());//获取密钥生成器
kpg.initialize(keysize); //初始化密钥生成器
KeyPair pkey=kpg.generateKeyPair(); //生成密钥
PublicKey pubkey=pkey.getPublic(); //获取公钥
PrivateKey prikey=pkey.getPrivate(); //获取私钥
//保存公钥到文件中
FileOutputStream f1=new FileOutputStream(keyName1);
ObjectOutputStream b1=new ObjectOutputStream(f1);
b1.writeObject(pubkey);
//保存私钥到文件中
FileOutputStream f2=new FileOutputStream(keyName2);
ObjectOutputStream b2=new ObjectOutputStream(f2);
b2.writeObject(prikey);
//System.out.println("已成功生成密钥!");
}
public static void main(String agrs[])throws IOException{
String filename,s1,s2;
System.out.print("请输入要生成的对称密钥文件名:");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
filename=in.readLine();
ProduceKey produce=new ProduceKey("DESede",filename,168);
try {
produce.Symmetric();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print("请输入要生成的公钥文件名:");
s1=in.readLine();
System.out.print("请输入要生成的私钥文件名:");
s2=in.readLine();
ProduceKey pair=new ProduceKey("RSA",s1,s2,1024);
try {
pair.aSymmetric();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package fileEncryption;import java.io.*;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;import javax.crypto.*;
public class EncryptDecrypt{
String aName,fileName,keyName,outFileName;
int mode;
public EncryptDecrypt(int m,String aname,String filename,String keyname,String outfilename){
if(m==1)
mode=Cipher.ENCRYPT_MODE; //加密模式
else if(m==2)
mode=Cipher.DECRYPT_MODE; //解密模式
aName=aname;
fileName=filename;
keyName=keyname;
outFileName=outfilename;
}
public void encORdec()throws Exception{
//为要加密或解密的文件创建输入流
FileInputStream fin=new FileInputStream(fileName);
//为要加密或解密所用的密钥文件创建输入流
FileInputStream k1=new FileInputStream(keyName);
//为要加密或解密后的文件创建输出流
FileOutputStream fout=new FileOutputStream(outFileName);
ObjectInputStream ob =new ObjectInputStream(k1);
Key key=(Key)ob.readObject();
Cipher cp=Cipher.getInstance(aName);
cp.init(mode, key);
CipherInputStream cin=new CipherInputStream(fin,cp);
int b=0;
while((b=cin.read())!=-1){
fout.write(b);
}
//cout.close();
//fout.close();
//fin.close();
}//RSA加密
public void FeiEnc()throws Exception{
//为要加密或解密的文件创建输入流
FileInputStream fin=new FileInputStream(fileName);
//为要加密或解密所用的密钥文件创建输入流
FileInputStream k1=new FileInputStream(keyName);
//为要加密或解密后的文件创建输出流
FileOutputStream fout=new FileOutputStream(outFileName);
ObjectInputStream ob =new ObjectInputStream(k1);
int num=fin.available();
byte[] buffer=new byte[num];
fin.read(buffer);
Cipher cp = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
if(mode==Cipher.ENCRYPT_MODE){
RSAPublicKey key=(RSAPublicKey)ob.readObject();
cp.init(mode, key);
int blockSize = cp.getBlockSize();// 获得加密块大小,如:加密前数据为128个byte,而key_size=1024
// 加密块大小为127byte,加密后为128个byte;因此共有2个加密块,第一个127byte第二个为1个byte
int outputSize = cp.getOutputSize(buffer.length);// 获得加密块加密后块大小
int leavedSize = buffer.length % blockSize;
int blocksSize = leavedSize != 0 ? buffer.length / blockSize + 1 : buffer.length / blockSize;
byte[] ctext = new byte[outputSize * blocksSize];
int i = 0;
while (buffer.length - i * blockSize > 0) {
if (buffer.length - i * blockSize > blockSize)
cp.doFinal(buffer, i * blockSize, blockSize, ctext, i* outputSize);
else
cp.doFinal(buffer, i * blockSize, buffer.length - i* blockSize, ctext, i * outputSize);
// 这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到ByteArrayOutputStream中,
//而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了OutputSize所以只好用dofinal方法。
i++;
}
fout.write(ctext);
}
else{
RSAPrivateKey key=(RSAPrivateKey)ob.readObject();
cp.init(mode, key);
int blockSize = cp.getBlockSize();
ByteArrayOutputStream bout = new ByteArrayOutputStream();
int j = 0;
while (buffer.length - j * blockSize > 0) {
bout.write(cp.doFinal(buffer, j * blockSize, blockSize));
j++;
}
fout.write(bout.toByteArray());
}
}
public static void main(String args[])throws IOException{
/*EncryptDecrypt example1=new EncryptDecrypt(1,"DESede","haha.doc","good.dat","haha_enc.doc");
try {
example1.encORdec();
System.out.println("文件已成功加密!");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
EncryptDecrypt example2=new EncryptDecrypt(2,"DESede","haha_enc.doc","good.dat","haha_dec.doc");
try {
example2.encORdec();
System.out.println("文件已成功解密!");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
EncryptDecrypt example3=new EncryptDecrypt(1,"RSA","today.doc","zhao_pub.dat","today_rsa_enc.doc");
try {
example3.FeiEnc();
System.out.println("文件已成功加密!");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
EncryptDecrypt example4=new EncryptDecrypt(2,"RSA","today_rsa_enc.doc","zhao_pri.dat","today_rsa_dec.doc");
try {
example4.FeiEnc();
System.out.println("文件已成功解密!");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}