久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

AES 加密,解密文件中有多余的垃圾字符

AES encryption, got extra trash characters in decrypted file(AES 加密,解密文件中有多余的垃圾字符)
本文介紹了AES 加密,解密文件中有多余的垃圾字符的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧!

問題描述

我正在 Android 應(yīng)用程序中制作調(diào)試登錄功能.我有一個簡單的類,它使用 128 位 AES 加密記錄到 .txt 文件.

Im making a debug loggin function in an android app. I have a simple class which is logging to .txt file using 128 bit AES encryption.

記錄完成后,我用一個簡單的 JAVA 程序解密記錄的文件.

問題是當(dāng)我解密加密日志時我得到了一些奇怪的內(nèi)容,我也得到了加密的內(nèi)容,但是有一些額外的字符,見下文.

The problem is when i decrypt the encrypted log i got some weird content in it, i also got the encrypted content, but there are some extra characters, see below.

Android 應(yīng)用日志部分:

public class FileLogger {

//file and folder name
public static String LOG_FILE_NAME = "my_log.txt";
public static String LOG_FOLDER_NAME = "my_log_folder";

static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss_SSS");

//My secret key, 16 bytes = 128 bit
static byte[] key = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6};

//Appends to a log file, using encryption
public static void appendToLog(Context context, Object msg) {

    String msgStr;
    String timestamp = "t:" + formatter.format(new java.util.Date());

    msgStr = msg + "|" + timestamp + "
";

    File sdcard = Environment.getExternalStorageDirectory();
    File dir = new File(sdcard.getAbsolutePath() + "/" + LOG_FOLDER_NAME);
    if (!dir.exists()) {
        dir.mkdir();
    }

    File encryptedFile = new File(dir, LOG_FILE_NAME);

    try {
        
        //Encryption using my key above defined
        Key secretKey = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);

        byte[] outputBytes = cipher.doFinal(msgStr.getBytes());

        //Writing to the file using append mode
        FileOutputStream outputStream = new FileOutputStream(encryptedFile, true);
        outputStream.write(outputBytes);
        outputStream.close();
        
        
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
        e.printStackTrace();
    } catch (BadPaddingException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    }

}

}

這是解密JAVA程序:

public class Main {

    

//output file name after decryption
private static String decryptedFileName;
//input encrypted file
private static String fileSource;
//a prefix tag for output file name
private static String outputFilePrefix = "decrypted_";
//My key for decryption, its the same as in the encrypter program.
static byte[] key = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 };

//Decrypting function
public static void decrypt(byte[] key, File inputFile, File outputFile) throws Exception {
    try {

        Key secretKey = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);

        FileInputStream inputStream = new FileInputStream(inputFile);
        byte[] inputBytes = new byte[(int) inputFile.length()];
        inputStream.read(inputBytes);

        byte[] outputBytes = cipher.doFinal(inputBytes);

        FileOutputStream outputStream = new FileOutputStream(outputFile, true);
        outputStream.write(outputBytes);

        inputStream.close();
        outputStream.close();

    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

//first argument is the intput file source
public static void main(String[] args) {

    if (args.length != 1) {
        System.out.println("Add log file name as a parameter.");

    } else {
        fileSource = args[0];

        try {
            File sourceFile = new File(fileSource);
            if (sourceFile.exists()) {
                
                //Decrption
                decryptedFileName = outputFilePrefix + sourceFile.getName();
                File decryptedFile = new File(decryptedFileName);
                decrypt(key, sourceFile, decryptedFile);
            } else {
                System.out.println("Log file not found: " + fileSource);
            }

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

        System.out.println("Decryption done, output file: " + decryptedFileName);
    }

}

}

輸出解密后的日志(用notepad++打開):

T這是有效內(nèi)容,但您也可以看到額外的 thrash 字符.如果我使用默認的 windows 文本編輯器打開,我也會得到 thrash 字符,但不同.

There is the valid content, but you also can see the extra thrash characters. If I open with the default windows text editor i also got thrash charaters, but different ones.

這是我第一次嘗試使用 encrypt -decrypt,我做錯了什么?有什么想法嗎?

This is my first try with encrypt -decrypt, what m i doing wrong? Any ideas?

推薦答案

AES 是一種僅適用于塊的分組密碼.您要加密的明文可以是任意長度,因此密碼必須始終填充明文以將其填充到塊大小的倍數(shù)(或者當(dāng)它已經(jīng)是塊大小的倍數(shù)時添加一個完整的塊).在此 PKCS#5/PKCS#7 填充中,每個填充字節(jié)表示填充字節(jié)數(shù).

AES is a block cipher which only works on blocks. The plaintext that you want to encrypt can be of any length, so the cipher must always pad the plaintext to fill it up to a multiple of the block size (or add a complete block when it already is a multiple of the block size). In this PKCS#5/PKCS#7 padding each padding byte denotes the number of padded bytes.

簡單的解決方法是在解密期間迭代 outputBytes 并刪除始終在下一行的那些填充字節(jié).一旦您使用多行日志消息或使用語義安全模式(稍后會詳細介紹),這將中斷.

The easy fix would be to iterate over outputBytes during decryption and remove those padding bytes which are always on the next line. This will break as soon as you use multiline log messages or use a semantically secure mode (more on that later).

更好的解決方法是在消息之前寫入每個日志消息的字節(jié)數(shù),讀取它并僅解密那么多字節(jié).這也可能更容易通過文件流實現(xiàn).

The better fix would be to write the number of bytes for each log message before the message, read that and decrypt only that many bytes. This also probably easier to implement with file streams.

您當(dāng)前使用 Cipher.getInstance("AES"); 這是 Cipher.getInstance("AES/ECB/PKCS5Padding"); 的非完全限定版本;.ECB 模式在語義上并不安全.它只是用 AES 和密鑰加密每個塊(16 個字節(jié)).因此,相同的塊在密文中將是相同的.這尤其糟糕,因為一些日志消息以相同的開頭,攻擊者可能能夠區(qū)分它們.這也是為什么整個文件的解密工作盡管被分塊加密的原因.您應(yīng)該使用隨機 IV 的 CBC 模式.

You currently use Cipher.getInstance("AES"); which is a non-fully qualified version of Cipher.getInstance("AES/ECB/PKCS5Padding");. ECB mode is not semantically secure. It simply encrypts each block (16 bytes) with AES and the key. So blocks that are the same will be the same in ciphertext. This is particularly bad, because some log messages start the same and an attacker might be able to distinguish them. This is also the reason why the decryption of the whole file worked despite being encrypted in chunks. You should use CBC mode with a random IV.

以下是一些示例代碼,用于在 CBC 模式下正確使用 AES,并使用流進行隨機 IV:

Here is some sample code for proper use of AES in CBC mode with a random IV using streams:

private static SecretKey key = generateAESkey();
private static String cipherString = "AES/CBC/PKCS5Padding";

public static void main(String[] args) throws Exception {
    ByteArrayOutputStream log = new ByteArrayOutputStream();
    appendToLog("Test1", log);
    appendToLog("Test2 is longer", log);
    appendToLog("Test3 is multiple of block size!", log);
    appendToLog("Test4 is shorter.", log);

    byte[] encLog = log.toByteArray();

    List<String> logs = decryptLog(new ByteArrayInputStream(encLog));

    for(String logLine : logs) {
        System.out.println(logLine);
    }
}

private static SecretKey generateAESkey() {
    try {
        return KeyGenerator.getInstance("AES").generateKey();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return null;
}

private static byte[] generateIV() {
    SecureRandom random = new SecureRandom();
    byte[] iv = new byte[16];
    random.nextBytes(iv);
    return iv;
}

public static void appendToLog(String s, OutputStream os) throws Exception {
    Cipher cipher = Cipher.getInstance(cipherString);
    byte[] iv = generateIV();
    cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
    byte[] data = cipher.doFinal(s.getBytes("UTF-8"));
    os.write(data.length);
    os.write(iv);
    os.write(data);
}

public static List<String> decryptLog(InputStream is) throws Exception{
    ArrayList<String> logs = new ArrayList<String>();
    while(is.available() > 0) {
        int len = is.read();
        byte[] encLogLine = new byte[len];
        byte[] iv = new byte[16];
        is.read(iv);
        is.read(encLogLine);

        Cipher cipher = Cipher.getInstance(cipherString);
        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
        byte[] data = cipher.doFinal(encLogLine);
        logs.add(new String(data, "UTF-8"));
    }
    return logs;
}

這篇關(guān)于AES 加密,解密文件中有多余的垃圾字符的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!

【網(wǎng)站聲明】本站部分內(nèi)容來源于互聯(lián)網(wǎng),旨在幫助大家更快的解決問題,如果有圖片或者內(nèi)容侵犯了您的權(quán)益,請聯(lián)系我們刪除處理,感謝您的支持!

相關(guān)文檔推薦

Java Remove Duplicates from an Array?(Java從數(shù)組中刪除重復(fù)項?)
How to fix Invocation failed Unexpected Response from Server: Unauthorized in Android studio(如何修復(fù)調(diào)用失敗來自服務(wù)器的意外響應(yīng):在 Android 工作室中未經(jīng)授權(quán))
AES Error: Given final block not properly padded(AES 錯誤:給定的最終塊未正確填充)
Detecting incorrect key using AES/GCM in JAVA(在 JAVA 中使用 AES/GCM 檢測不正確的密鑰)
AES-256-CBC in Java(Java 中的 AES-256-CBC)
Using BouncyCastle to encrypt with ECIES in Java(在 Java 中使用 BouncyCastle 使用 ECIES 進行加密)
主站蜘蛛池模板: 欧美精品福利 | 成人欧美一区二区三区在线观看 | 国产一区 | 中文字幕在线观看一区二区 | 国产精品99久久久久 | 亚洲精品久久久久久一区二区 | 羞羞视频在线网站观看 | 黑人巨大精品欧美黑白配亚洲 | 国产丝袜av | 久久久久久91 | 欧美一区二区三区 | 黄色毛片在线播放 | 视频一区二区三区四区五区 | 国产精品一区二区av | 在线日韩不卡 | 国产精品视频久久久 | 国产三级精品三级在线观看四季网 | 午夜丁香视频在线观看 | 一级片在线观看 | 99精品一区二区三区 | 国产精品婷婷 | 国产精品视频999 | 免费在线观看av网站 | 久久国产精品久久久久久 | 欧美性一区二区三区 | av在线免费看网址 | 欧美99 | 久久久这里都是精品 | 日本久草 | 久久久久亚洲 | 91精品久久久久久久久 | 国产粉嫩尤物极品99综合精品 | 精品国产乱码久久久久久蜜柚 | aaa精品| 日本久久久影视 | 99热热| 久久国际精品 | 日韩毛片免费视频 | 天天搞天天操 | 成人av片在线观看 | 成年人视频在线免费观看 |