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

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

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

問題描述

我正在 Android 應用程序中制作調試登錄功能.我有一個簡單的類,它使用 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 程序解密記錄的文件.

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

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 應用日志部分:

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這是有效內容,但您也可以看到額外的 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 是一種僅適用于塊的分組密碼.您要加密的明文可以是任意長度,因此密碼必須始終填充明文以將其填充到塊大小的倍數(或者當它已經是塊大小的倍數時添加一個完整的塊).在此 PKCS#5/PKCS#7 填充中,每個填充字節表示填充字節數.

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 并刪除始終在下一行的那些填充字節.一旦您使用多行日志消息或使用語義安全模式(稍后會詳細介紹),這將中斷.

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).

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

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.

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

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

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

相關文檔推薦

Java Remove Duplicates from an Array?(Java從數組中刪除重復項?)
How to fix Invocation failed Unexpected Response from Server: Unauthorized in Android studio(如何修復調用失敗來自服務器的意外響應:在 Android 工作室中未經授權)
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 進行加密)
主站蜘蛛池模板: 欧美一级片| 日日夜夜精品免费视频 | 激情一区| 国产成人福利在线观看 | 国产精品a一区二区三区网址 | 久久精品中文字幕 | 国产精品久久 | 老司机成人在线 | 久久婷婷国产麻豆91 | 99久久99 | 国产成人综合一区二区三区 | 欧美视频在线一区 | 亚洲欧美一区二区三区国产精品 | 精品区一区二区 | 日日干日日操 | 色在线免费视频 | 国产福利一区二区 | 国产免费一区二区 | 毛片入口 | 国产美女一区二区三区 | 久久之精品 | 天天做日日做 | 91在线视频观看免费 | www.国产一区| 久久综合av| 亚洲综合大片69999 | 欧美精品久久久久久久久久 | 中文字幕日韩欧美一区二区三区 | 影音先锋中文字幕在线观看 | 国产色爽 | 99re| 国产98色在线 | 日韩 | 日韩欧美成人一区二区三区 | 国产一区二区三区高清 | 久久综合伊人 | 免费看一级毛片 | 亚洲综合区| 午夜综合 | www.日韩| 一区二区国产精品 | 国产精品高潮呻吟久久 |