0

这是我的代码:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

public class EncryptedLogger {

private static Date lastLogTime = null;
private static EncryptedLogger instance = null;
private static FileOutputStream fos = null;
private static CipherOutputStream cos = null;
private static PrintWriter writer = null;
private Cipher cipher;
byte[] Key ={(byte) 0x12,(byte) 0x34,0x55,(byte) 0x66,0x67,(byte)0x88,(byte)0x90,0x12,(byte) 0x23,0x45,0x67,(byte)0x89,0x12,0x33,(byte) 0x55,0x74};

public static EncryptedLogger getInstance(){
    if (instance==null) {
        instance = new EncryptedLogger();
    }
    return instance;
}

private EncryptedLogger(){

    class SQLShutdownHook extends Thread{
        @Override
        public void run() {
            EncryptedLogger.close();
            super.run();
        }
    }

    SecretKeySpec sks = new SecretKeySpec(Key,"AES");
    try {
        cipher = Cipher.getInstance("AES/ECB/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE,sks);

        fos = new FileOutputStream(new File("log.txt"),true);
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    cos = new CipherOutputStream(fos, cipher);
    writer = new PrintWriter(cos);

    SQLShutdownHook hook = new SQLShutdownHook();
    Runtime.getRuntime().addShutdownHook(hook);
}

public synchronized void logSQL(String s){
    if ((lastLogTime==null)||((new Date().getTime() -lastLogTime.getTime())>1000)){
        lastLogTime = new Date();
        writer.printf("-- %1$tm-%1$te-%1$tY %1$tH-%1$tM-%1$tS\n%2$s\n",new Date(),s);   
    }
    else{
        writer.println(s);
    }
}

public synchronized void logComment(String s){
    writer.printf("-- %1$tm-%1$te-%1$tY %1$tH-%1$tM-%1$tS: %2$s\n",new Date(),s);
}

public static void close(){
    writer.flush();
    writer.close();
}

public static void main(String[] args) throws InterruptedException {
    EncryptedLogger.getInstance().logSQL("1");
    EncryptedLogger.getInstance().logSQL("22");
    EncryptedLogger.getInstance().logSQL("33333");
    EncryptedLogger.getInstance().logSQL("4900");
    EncryptedLogger.getInstance().logSQL("5");
    EncryptedLogger.getInstance().logSQL("66666");
    EncryptedLogger.getInstance().logSQL("Some test logging statement");
    EncryptedLogger.getInstance().logSQL("AAAAAAAAAAAAAAAAAAAAAAAAAA");
    EncryptedLogger.getInstance().logComment("here is test commentary");
}

}

如您所见,我正在尝试通过 PrintWriter->CipherOutputStream->FileOutputStream 链对文本条目进行加密。但是当我解密结果文件时,缺少字节。我试图在 EncryptedLogger.close() 方法中刷新cosfos - 结果相同。显然我错过了一些东西。怎么了?

编辑:这是我使用的解密代码。它不是我的,取自教程或其他东西......并且在使用类似加密时它工作正常。但是当使用我的代码时......

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class AESDecrypter
{
        Cipher dcipher;

        public AESDecrypter(SecretKey key)
        {

                try
                {
                        dcipher = Cipher.getInstance("AES");
                        dcipher.init(Cipher.DECRYPT_MODE, key);
                }
                catch (Exception e)
                {
                        e.printStackTrace();
                }
        }

        byte[] buf = new byte[1024];

        public void decrypt(InputStream in, OutputStream out)
        {
            System.out.println("decrypting");
            try
                {
                        in = new CipherInputStream(in, dcipher);
                        int numRead = 0;
                        while ((numRead = in.read(buf)) >= 0)
                        {
                                out.write(buf, 0, numRead);
                        }
                        out.close();
                }
                catch (java.io.IOException e)
                {
                }
        }

        public static void main(String args[])
        {
                try
                {
                        byte[] keystr ={(byte) 0x12,(byte) 0x34,0x55,(byte) 0x66,0x67,(byte)0x88,(byte)0x90,0x12,(byte) 0x23,0x45,0x67,(byte)0x89,0x12,0x33,(byte) 0x55,0x74};
                        SecretKeySpec sks = new SecretKeySpec(keystr,"AES");                        
                        AESDecrypter encrypter = new AESDecrypter(sks);
                        encrypter.decrypt(new FileInputStream("sqllogenc.log"),new FileOutputStream("sqllogdec.log"));
                }
                catch (Exception e)
                {
                        e.printStackTrace();
                }
        }
}

EDIT2:当我直接写信给fos我得到这个输出:

-- 04-19-2012 16-17-56
1
22
33333
4900
5
66666 + delay starting 1100
Some test logging statement
AAAAAAAAAAAAAAAAAAAAAAAAAA
-- 04-19-2012 16-17-56: here is test commentary

在使用cos编写和解密时:

-- 04-19-2012 16-22-13
1
22
33333
4900
5
66666 + delay starting 1100
Some test logging statement
AAAAAAAAAAAAAAAAAAAAAAAAAA
-- 04-19-2012 16-22-13: here 

如您所见,最后一行的一部分丢失了,包括换行符。

4

2 回答 2

1

AES/ECB/NoPadding您应该在两侧使用相同的加密转换(例如)。另外,请注意,NoPadding模式不允许您传递任意大小的数据,因此您需要指定其他类型的填充。

所以,你需要在两边构造Ciphers 。Cipher.getInstance("AES/ECB/PKCS5Padding")

另外,请注意 rossum 关于使用CBCorCTR代替ECB.

于 2012-04-19T14:17:31.553 回答
1

好吧,AES 的块大小固定为 128 位。当您使用 AES/ECB/NoPadding 时,您有责任确保消息的大小是块大小的倍数。

可能不是,因此解密时获得的文本更少。

对于任意长度的文本,您应该使用 AES/ECB/NoPadding。

于 2012-04-19T14:29:39.667 回答