1

ファイルを暗号化および復号化するための小さなツールをコーディングしています。暗号化されたファイルは zip アーカイブに追加されます。次のコードはこれまでのところ機能しています。テキストファイル以外のファイルを暗号化できます。テキストファイルを選択すると、不完全に書き込まれます。「one two three test check check test」というテキストがある場合、「one two three test che」のように切り取られます。

数バイトが欠落しているだけで例外はスローされません。その他のファイル (pdf、mp3、mp4、exe など) は完全に書き込まれます。

package encryptme.crypto;

import encryptme.fileoperations.FileIn;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;

public class Encrypt {

    private String algorithm;
    private int keylength;
    private Key key;
    private KeyPair keypair;
    private File[] source;
    private String destination;

    public Encrypt(String a, int kl, Key k, File[] s, String dest) {
        this.algorithm = a;
        this.keylength = kl;
        this.key = k;
        this.source = s;
        this.destination = dest;
        this.output = o;
    }

    public void encOut() {
        CipherOutputStream cout = null;
        ZipOutputStream zout = null;
        OutputStream out = null;
        Cipher cipher;
        try {
            out = new FileOutputStream(this.destination);
            System.out.println(this.destination);
            zout = new ZipOutputStream(out);
            cipher = Cipher.getInstance(this.algorithm);
            cipher.init(Cipher.ENCRYPT_MODE, this.key);
            for (int i = 0; i < this.source.length; i++) {
                FileInputStream in = new FileInputStream(this.source[i].getAbsolutePath());
                ZipEntry ze = new ZipEntry(this.source[i].getName());                 
                zout.putNextEntry(ze);
                cout = new CipherOutputStream(zout, cipher);
                byte[] buffer = new byte[1024];
                long bytesRead = 0;
                for (bytesRead = 0; (bytesRead = in.read(buffer)) != -1;) {
                    cout.write(buffer, 0, (int) bytesRead);
                }
                zout.closeEntry();
                in.close();
            }
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(Encrypt.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchPaddingException ex) {
            Logger.getLogger(Encrypt.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidKeyException ex) {
            Logger.getLogger(Encrypt.class.getName()).log(Level.SEVERE, null, ex);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Encrypt.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Encrypt.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                if (cout != null) {
                    cout.close();
                }
                if (zout != null) {
                    zout.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException ex) {
                Logger.getLogger(Encrypt.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}

暗号化するファイルは jFileChooser で選択され、上記のクラスにパラメーターとして渡される配列に追加されます。私は、「textfile.txt」や「textfile.odt」などの末尾でそれらを識別するテキストファイルに PrintWriter を使用することを考えました。しかし、ファイルに「textfile」のように末尾がない場合はどうすればよいでしょうか?

私はJavaとコーディング全般にかなり慣れていないので、問題の原因となる悪い間違いがあることを願っています.

4

2 に答える 2

0

暗号がバッファリングした残りのデータをフラッシュするために、cout呼び出す前にを閉じる必要があります。zout.closeEntry残念ながら、cout.close()will を呼び出しますがzout.close()、それ以上のエントリを書くことができなくなるため、絶対に望ましくありません。

commons-io の CloseShieldOutputStreamを使用します。

cout = new CipherOutputStream(new CloseShieldOutputStream(zout), cipher);

このクラスは、close()呼び出しが基になるラップされたストリーム (この場合はzout) に伝播するのを防ぐように設計されています。

于 2013-11-29T22:54:50.127 に答える
-1

何を求めているのか 100% はわかりませんが、受信したファイルの配列を Encrypt クラスにサニタイズしますか? 1 つの方法は、ファイル拡張子を確認することです。

public class ImageFileFilter implements FileFilter {

        private String[] imageExtentions = {"png", "jpg", "gif" };

        @Override
        public boolean accept(File file) {
                for(String ext : imageExtentions){
                        if(file.isFile()){
                                if(file.getName().toLowerCase().endsWith(ext))
                                        return true;
                        }
                }
                return false;
        }
}

上記の例は、画像拡張機能を処理することになっているクラスですが、汎用であるため、accept メソッドに渡される任意の拡張機能に対して機能します。重要なのは、FileFilter インターフェイスを実装することです。そうすれば、ファイルをサニタイズできます。

編集: ああ、あなたは質問を編集して、あなたが何を望んでいるのかをより明確にしました。

于 2013-11-29T19:20:36.497 に答える