加密包含表和结构的文本

时间:2016-10-19 11:35:05

标签: java x509certificate public-key-encryption

我正在通过java中本地repo的证书加密解密文件。 但对于包含表格,图表的文字处理文件,文件与实际文件不同。我正在使用普通文件输入/输出流。 任何帮助都将非常有用。

public int encryptFileWithpubkey(String filepath,PublicKey pubkey){
    int retval=0;
    FileInputStream fis = null;
    File file=null;
    final String location = filepath;
    PublicKey pubKey= pubkey;
    try{
    try {
        fis = AccessController.doPrivileged(
         new PrivilegedExceptionAction<FileInputStream>() {
             public FileInputStream run() throws FileNotFoundException {

                 return new FileInputStream(location);
             }
         });
     } catch (PrivilegedActionException e) {
         throw (FileNotFoundException) e.getException();
     }
        InputStream is =  fis;
      //long length = file.length();

        byte[] bytes = new byte[fis.available()];
        int offset = 0;
        int numRead = 0;
        while (offset < bytes.length
               && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
            offset += numRead;
        }
        is.close();
        file=null;




            String encString="";        
            int iFixedLen=110;
            if(bytes.length>=iFixedLen){

                int noOfBlocks=(int)Math.ceil((bytes.length/110.0));
            //  System.out.println("Noof blocks :"+noOfBlocks);
                for(int i=0;i<noOfBlocks;i++){
                    byte[] tempStr=null;
                    if(i==noOfBlocks-1){
                        //System.out.println("Last block");
                        tempStr=new byte[(bytes.length-(i*iFixedLen))];
                        System.arraycopy(bytes, (i*iFixedLen), tempStr, 0,(bytes.length-(i*iFixedLen)));
                    }
                    else
                    {   
                        //System.out.println("i : "+i);
                        tempStr=new byte[iFixedLen];
                        //tempStr=new byte[iFixedLen];
                        System.arraycopy(bytes, (i*iFixedLen), tempStr, 0,iFixedLen);
                        //tempStr=plainText.substring(0,110) ;
                        //plainText=plainText.substring(110);
                    }
                    encString+= encryptBytes(tempStr,pubKey)+"    ";
                }
                encString=encString.substring(0,encString.length()-1);
                retval=noOfBlocks;
            }else{
                encString=encryptBytes(bytes,pubKey);
                retval=1;

            }

        FileOutputStream fos = null;
    try {
        fos = AccessController.doPrivileged(
         new PrivilegedExceptionAction<FileOutputStream>() {
             public FileOutputStream run() throws FileNotFoundException {

                 return new FileOutputStream(location);
             }
         });
     } catch (PrivilegedActionException e) {
         throw (FileNotFoundException) e.getException();
     }
    fos.write(encString.getBytes());
    fos.close();
    }catch(Exception e){
        e.printStackTrace();
        return 0;
    }
return retval;
}

encryptBytes函数跟随:

public String encryptBytes(byte[] rawData,PublicKey pubkey){
        String retval=null;

       try{

        byte[] rawByteData=rawData;
        Cipher cp=Cipher.getInstance("RSA/ECB/PKCS1PADDING");
        cp.init( Cipher.ENCRYPT_MODE,pubkey);
        byte[] getDat=cp.doFinal(rawByteData);

        retval=java.util.Base64.getEncoder().encodeToString(getDat);

         }catch(Exception e)
         {
        e.printStackTrace();
         }
        return retval;
    }

2 个答案:

答案 0 :(得分:0)

你在这里已经犯了几乎所有的错误。

        InputStream is =  fis;
      //long length = file.length();

        byte[] bytes = new byte[fis.available()];

InputStream.available()不是输入流长度的指示符。请参阅Javadoc,其中包含针对您在此处所做的具体警告。在进行任何类型的I / O时,实际上总是可以使用固定大小的缓冲区,并且很少需要将整个文件读入内存。编译器没有这样做:你为什么要这样做?

        int offset = 0;
        int numRead = 0;
        while (offset < bytes.length
               && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
            offset += numRead;
        }
        is.close();
        file=null;

file = null;语句在这里毫无意义,整个循环可以省略,如下所示。

            String encString="";

String不是二进制数据的容器。

            int iFixedLen=110;

幻数110来自何处?

            if(bytes.length>=iFixedLen){

                int noOfBlocks=(int)Math.ceil((bytes.length/110.0));
            //  System.out.println("Noof blocks :"+noOfBlocks);
                for(int i=0;i<noOfBlocks;i++){
                    byte[] tempStr=null;
                    if(i==noOfBlocks-1){
                        //System.out.println("Last block");
                        tempStr=new byte[(bytes.length-(i*iFixedLen))];
                        System.arraycopy(bytes, (i*iFixedLen), tempStr, 0,(bytes.length-(i*iFixedLen)));
                    }
                    else
                    {   
                        //System.out.println("i : "+i);
                        tempStr=new byte[iFixedLen];
                        //tempStr=new byte[iFixedLen];
                        System.arraycopy(bytes, (i*iFixedLen), tempStr, 0,iFixedLen);
                        //tempStr=plainText.substring(0,110) ;
                        //plainText=plainText.substring(110);
                    }
                    encString+= encryptBytes(tempStr,pubKey)+"    ";
                }
                encString=encString.substring(0,encString.length()-1);
                retval=noOfBlocks;
            }else{
                encString=encryptBytes(bytes,pubKey);
                retval=1;

            }

我不知道所有这一切应该做什么,但你不应该使用110字节的块,或字符,或者它们是什么,或者将字节数组形式的加密数据转换为String,以及你不应该为它添加四个空格。

        FileOutputStream fos = null;
    try {
        fos = AccessController.doPrivileged(
         new PrivilegedExceptionAction<FileOutputStream>() {
             public FileOutputStream run() throws FileNotFoundException {

                 return new FileOutputStream(location);
             }
         });
     } catch (PrivilegedActionException e) {
         throw (FileNotFoundException) e.getException();
     }
    fos.write(encString.getBytes());

在这里你可以编写实际加密产生的原始字节数组,避免了整个问题。

您尚未发布encryptBytes()方法,因此无法进一步发表评论。

    fos.close();
    }catch(Exception e){
        e.printStackTrace();
        return 0;
    }
return retval;
}

答案 1 :(得分:0)

文件是否包含表格或其他结构与现代加密完全无关,因为它适用于已经从&#34;文档&#34;中序列化的二进制数据。

您正在尝试将RSA应用于原始文件的某些块。这是非常棘手的,因为你必须确保输入小于考虑填充的RSA模数。然后,您必须确保每个密文块具有完全相同的长度,以便您在解密期间知道哪些字节属于哪个块。在RSA中,不能保证输出总是具有相同的字节数。与填充输入相比,它可以更小。所以你需要一致地填充密文块。

更好的想法是使用hybrid encryption。您可以使用AES加密实际数据,并使用RSA加密随机生成的AES密钥。一个简单的格式应该很容易做到:

4 bytes - Length of the RSA-encrypted AES key (= x)
x bytes - RSA-encrypted AES key
remaining bytes - AES-encrypted file

当然,如果您正在进行AES加密,则必须考虑操作模式,填充模式,如何处理初始化向量以及是否要添加经过身份验证的加密。