我用RSA对文本文件进行加密,但当我的文本文件大小超过1kb时加密、解密就会出错。密钥初始用的1024。希望前辈能指导下。最好能写出关键的源代码(比如,数据的缓冲区设为多大)。

解决方案 »

  1.   

    补充一下:
    以下是我写的源代码,我不明白为什么要加密的文件一长,就会出错。我测试过,此文本文件的长度在二行以内就不会出错》package rsa;import java.io.FileOutputStream;
    import java.io.ObjectOutputStream;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.util.logging.Level;
    import java.util.logging.Logger;/**
     *
     * @author Administrator
     */
    public class GenKey {
        public static void main(String[] args){//生成密钥
            try {
                //创建密钥对生成器
                KeyPairGenerator KPG = KeyPairGenerator.getInstance("RSA");
                //初始化密钥生成器
                KPG.initialize(1024);
                //生成密钥对
                KeyPair KP=KPG.genKeyPair();
                //获取公钥和密钥
                PublicKey pbKey=KP.getPublic();
                PrivateKey prKey=KP.getPrivate();
                //保存公钥到文件
                FileOutputStream out=new FileOutputStream("RSAPublic.dat");
                ObjectOutputStream fileOut=new ObjectOutputStream(out);
                fileOut.writeObject(pbKey);
                //保存密钥到文件
                FileOutputStream outPrivate=new FileOutputStream("RSAPrivate.dat");
                ObjectOutputStream privateOut=new ObjectOutputStream(outPrivate);
                privateOut.writeObject(prKey);
            } catch (Exception ex) {
                Logger.getLogger(GenKey.class.getName()).log(Level.SEVERE, null, ex);
            }    }}
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */package rsatest;import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.ObjectInputStream;
    import java.io.OutputStreamWriter;
    import java.math.BigInteger;
    import java.security.interfaces.RSAPublicKey;
    import java.util.logging.Level;
    import java.util.logging.Logger;/**
     *
     * @author Administrator
     */
    public class RSAEncrypt {
        public static void main(String[] args){
            //读取公钥
            FileInputStream publicIn=null;
             ObjectInputStream objectPublic=null;
            try {
               // String codeString = "how are you?\n你是?"; //要加密的字符串
                publicIn = new //读取公钥
                FileInputStream("RSAPublic.dat");
               objectPublic=new ObjectInputStream(publicIn);
               RSAPublicKey publicKey=(RSAPublicKey)objectPublic.readObject();           //得到公钥的两个重要参数e,n
               BigInteger e=publicKey.getPublicExponent();
               BigInteger n=publicKey.getModulus();
               System.out.println("加密的密钥为:"+e);
               System.out.println("加密的模为:"+n);
               //读取明文           FileInputStream in=new FileInputStream("test.txt");
              // System.out.println(in.available());
              int size=in.available();
              byte[] encode=new byte[size];
               in.read(encode);          
             String  codeString=new String(encode);
              System.out.println(codeString);
             // codeString = "vi超强挂机类网赚";
               //将明文转为大整数
               byte[] codeStringByte=codeString.getBytes();
               BigInteger m=new BigInteger(codeStringByte);
               //加密处理
               BigInteger codeStringBigInt=m.modPow(e, n);
               String cString=codeStringBigInt.toString();
                   //保存密文
               BufferedWriter out=new BufferedWriter(new OutputStreamWriter
                       (new FileOutputStream("RSAmi.dat")));
               out.write(cString, 0, cString.length());
              
               out.close();
            } catch (Exception ex) {
                Logger.getLogger(RSAEncrypt.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
                try {
                    publicIn.close();
                    objectPublic.close();
                } catch (IOException ex) {
                    Logger.getLogger(RSAEncrypt.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }}/*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */package rsatest;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.OutputStreamWriter;
    import java.math.BigInteger;
    import java.security.interfaces.RSAPrivateKey;
    import java.util.logging.Level;
    import java.util.logging.Logger;/**
     *
     * @author Administrator
     */
    public class RSADecrypt {
        public static void main(String[] args){
            try {
                //读取密文
                BufferedReader in = new BufferedReader(new InputStreamReader
                        (new FileInputStream("RSAmi.dat")));
                String ctext=null;
                if((ctext=in.readLine())!=null){
                    //将密文转为大整数
                    BigInteger bigCtext=new BigInteger(ctext);
                    //取得密钥
                    ObjectInputStream objectStream=new ObjectInputStream(new
                            FileInputStream("RSAPrivate.dat"
                            ));
                    RSAPrivateKey privateKey=(RSAPrivateKey)objectStream.readObject();
                    //取得密钥的e,n
                    BigInteger e=privateKey.getPrivateExponent();
                    BigInteger n=privateKey.getModulus();
                    //解密
                    BigInteger decodeBigInt=bigCtext.modPow(e, n);
                    byte decodeStringByte[]=decodeBigInt.toByteArray();
                    String decodeString=new String(decodeStringByte);//此处的编码要和加密时的编码一样,否则会出错
                    System.out.println("解密后的明文为:"+decodeString);
                    BufferedWriter out=new BufferedWriter(new OutputStreamWriter
                       (new FileOutputStream("RSAming.txt")));
               out.write(decodeString, 0, decodeString.length());
               out.close();
                }
            } catch (Exception ex) {
                Logger.getLogger(RSADecrypt.class.getName()).log(Level.SEVERE, null, ex);
            }
        }}
      

  2.   

    自己又换了一种形式解决了,和大家分享一下。有关更多的加密算法到我空间看看/*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */package rsa;import java.io.FileOutputStream;
    import java.io.ObjectOutputStream;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.util.logging.Level;
    import java.util.logging.Logger;/**
     *
     * @author Administrator
     */
    public class GenKey {
        public static void main(String[] args){//创建密钥
            try {
                //创建密钥对生成器
                KeyPairGenerator KPG = KeyPairGenerator.getInstance("RSA");
                //初始化密钥生成器
                KPG.initialize(1024);
                //生成密钥对
                KeyPair KP=KPG.genKeyPair();
                //获取公钥和密钥
                PublicKey pbKey=KP.getPublic();
                PrivateKey prKey=KP.getPrivate();
                //保存公钥到文件
                FileOutputStream out=new FileOutputStream("RSAPublic.dat");
                ObjectOutputStream fileOut=new ObjectOutputStream(out);
                fileOut.writeObject(pbKey);
                //保存密钥到文件
                FileOutputStream outPrivate=new FileOutputStream("RSAPrivate.dat");
                ObjectOutputStream privateOut=new ObjectOutputStream(outPrivate);
                privateOut.writeObject(prKey);
            } catch (Exception ex) {
                Logger.getLogger(GenKey.class.getName()).log(Level.SEVERE, null, ex);
            }    }}
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package rsatest;import cipherinputstream.EncryptAndDecrypt;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.security.Key;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.crypto.Cipher;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;/**
     *
     * @author Administrator
     */
    public class RRSSA {    public static void main(String[] args) {
            //要用作加密或解密的文件名
            String dataFileName = args[0];
            //是区分是加密还是解密,加密为encrypt,解密为decrypt
            String opMode = args[1];
            String keyFileName = null;
            //密钥存放的文件名
            if (opMode.equalsIgnoreCase("encrypt")) {
                keyFileName = "RSAPublic.dat";
            } else {
                keyFileName = "RSAPrivate.dat";
            }        try {
                //生成密钥
                FileInputStream keyFIS = new FileInputStream(keyFileName);
                ObjectInputStream OIS = new ObjectInputStream(keyFIS);
                Key key = (Key) OIS.readObject();            //创建并初始化密码器
                Cipher cp = Cipher.getInstance("RSA", new BouncyCastleProvider());//此处不能少
                //BouncyCastLeProvider类在bcprov-ext-jdk16-141.jar中
                if (opMode.equalsIgnoreCase("encrypt")) {                cp.init(Cipher.ENCRYPT_MODE, key);
                } else if (opMode.equalsIgnoreCase("decrypt")) {
                    cp.init(Cipher.DECRYPT_MODE, key);
                } else {
                    return;
                }            FileInputStream dataFIS = new FileInputStream(dataFileName);
                //取得要加密的数据
                int size = dataFIS.available();
                byte[] encryptByte = new byte[size];
                dataFIS.read(encryptByte);
                //如果是加密操作
                if (opMode.equalsIgnoreCase("encrypt")) {
                    //建立文件输出流
                    FileOutputStream FOS = new FileOutputStream("mi.txt");
                    //RSA算法必须采用分块加密
                    //取得RSA加密的块的大小
                    int blockSize = cp.getBlockSize();
                    //根据给定的输入长度 inputLen(以字节为单位),返回保存下一个 update 或 doFinal 操作结果所需的输出缓冲区长度(以字节为单位)。
                    int outputBlockSize = cp.getOutputSize(encryptByte.length);                //确定要加密的次数(加密块的个数)
                    int leavedSize = encryptByte.length % blockSize;
                    int blocksNum = leavedSize == 0 ? encryptByte.length / blockSize
                            : encryptByte.length / blockSize + 1;
        
                    byte[] cipherData = new byte[blocksNum * outputBlockSize];
                    //对每块数据分别加密
                    for (int i = 0; i < blocksNum; i++) {                    if ((encryptByte.length - i * blockSize) > blockSize) {
                            cp.doFinal(encryptByte, i * blockSize, blockSize, cipherData, i * outputBlockSize);
                        } else {
                            cp.doFinal(encryptByte, i * blockSize, encryptByte.length - i * blockSize, cipherData, i * outputBlockSize);
                        }                    FOS.write(cipherData);
                    }
                    FOS.close();            } else {//如果是解密操作                FileOutputStream FOS = new FileOutputStream("jiemi.txt");
                    int blockSize = cp.getBlockSize();
                    int j = 0;                //分别对各块数据进行解密
                    while ((encryptByte.length - j * blockSize) > 0) {
                        FOS.write(cp.doFinal(encryptByte, j * blockSize, blockSize));
                        j++;
                    }                FOS.close();            }
            } catch (Exception ex) {
                Logger.getLogger(EncryptAndDecrypt.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }