网上说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();
}
}

}

解决方案 »

  1.   


    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();
    }

    }

    }
      

  2.   

    我也碰到过,好像是没有padding的原因吧,Cipher.getInstance("RSA/ECB/PKCS1Padding") 加密解密改用这个试试