pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

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

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

問(wèn)題描述

我正在 Android 應(yīng)用程序中制作調(diào)試登錄功能.我有一個(gè)簡(jiǎn)單的類(lèi),它使用 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.

記錄完成后,我用一個(gè)簡(jiǎn)單的 JAVA 程序解密記錄的文件.

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

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++打開(kāi)):

T這是有效內(nèi)容,但您也可以看到額外的 thrash 字符.如果我使用默認(rèn)的 windows 文本編輯器打開(kāi),我也會(huì)得到 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,我做錯(cuò)了什么?有什么想法嗎?

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

推薦答案

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

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

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

更好的解決方法是在消息之前寫(xiě)入每個(gè)日志消息的字節(jié)數(shù),讀取它并僅解密那么多字節(jié).這也可能更容易通過(guò)文件流實(shí)現(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 模式在語(yǔ)義上并不安全.它只是用 AES 和密鑰加密每個(gè)塊(16 個(gè)字節(jié)).因此,相同的塊在密文中將是相同的.這尤其糟糕,因?yàn)橐恍┤罩鞠⒁韵嗤拈_(kāi)頭,攻擊者可能能夠區(qū)分它們.這也是為什么整個(gè)文件的解密工作盡管被分塊加密的原因.您應(yīng)該使用隨機(jī) 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,并使用流進(jìn)行隨機(jī) 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 加密,解密文件中有多余的垃圾字符的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!

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

相關(guān)文檔推薦

Java Remove Duplicates from an Array?(Java從數(shù)組中刪除重復(fù)項(xiàng)?)
How to fix Invocation failed Unexpected Response from Server: Unauthorized in Android studio(如何修復(fù)調(diào)用失敗來(lái)自服務(wù)器的意外響應(yīng):在 Android 工作室中未經(jīng)授權(quán))
AES Error: Given final block not properly padded(AES 錯(cuò)誤:給定的最終塊未正確填充)
Detecting incorrect key using AES/GCM in JAVA(在 JAVA 中使用 AES/GCM 檢測(cè)不正確的密鑰)
AES-256-CBC in Java(Java 中的 AES-256-CBC)
Using BouncyCastle to encrypt with ECIES in Java(在 Java 中使用 BouncyCastle 使用 ECIES 進(jìn)行加密)
主站蜘蛛池模板: 沥青车辙成型机-车托式混凝土取芯机-混凝土塑料试模|鑫高仪器 | 北京森语科技有限公司-模型制作专家-展览展示-沙盘模型设计制作-多媒体模型软硬件开发-三维地理信息交互沙盘 | 长春网站建设,五合一网站设计制作,免费优化推广-长春网站建设 | 釜溪印象网络 - Powered by Discuz! | 不锈钢轴流风机,不锈钢电机-许昌光维防爆电机有限公司(原许昌光维特种电机技术有限公司) | NMRV减速机|铝合金减速机|蜗轮蜗杆减速机|NMRV减速机厂家-东莞市台机减速机有限公司 | 柴油发电机组_柴油发电机_发电机组价格-江苏凯晨电力设备有限公司 | 托利多电子平台秤-高精度接线盒-托利多高精度电子秤|百科 | 合肥防火门窗/隔断_合肥防火卷帘门厂家_安徽耐火窗_良万消防设备有限公司 | 新疆乌鲁木齐网站建设-乌鲁木齐网站制作设计-新疆远璨网络 | 聚天冬氨酸,亚氨基二琥珀酸四钠,PASP,IDS - 远联化工 | 青岛空压机,青岛空压机维修/保养,青岛空压机销售/出租公司,青岛空压机厂家电话 | 专业甜品培训学校_广东糖水培训_奶茶培训_特色小吃培训_广州烘趣甜品培训机构 | 反渗透阻垢剂-缓蚀阻垢剂厂家-循环水处理药剂-山东鲁东环保科技有限公司 | 冷柜风机-冰柜电机-罩极电机-外转子风机-EC直流电机厂家-杭州金久电器有限公司 | 蓝莓施肥机,智能施肥机,自动施肥机,水肥一体化项目,水肥一体机厂家,小型施肥机,圣大节水,滴灌施工方案,山东圣大节水科技有限公司官网17864474793 | 铜镍-康铜-锰铜-电阻合金-NC003 - 杭州兴宇合金有限公司 | 苗木价格-苗木批发-沭阳苗木基地-沭阳花木-长之鸿园林苗木场 | 玻纤土工格栅_钢塑格栅_PP焊接_单双向塑料土工格栅_复合防裂布厂家_山东大庚工程材料科技有限公司 | 广州企亚 - 数码直喷、白墨印花、源头厂家、透气无手感方案服务商! | 工业用品一站式采购平台|南创工品汇-官网|广州南创 | 单柱拉力机-橡胶冲片机-哑铃裁刀-江都轩宇试验机械厂 | 高通量组织研磨仪-多样品组织研磨仪-全自动组织研磨仪-研磨者科技(广州)有限公司 | 工装定制/做厂家/公司_工装订做/制价格/费用-北京圣达信工装 | PC构件-PC预制构件-构件设计-建筑预制构件-PC构件厂-锦萧新材料科技(浙江)股份有限公司 | 卫生人才网-中国专业的医疗卫生医学人才网招聘网站! | 气动调节阀,电动调节阀,自力式压力调节阀,切断阀「厂家」-浙江利沃夫自控阀门 | 铝机箱_铝外壳加工_铝外壳厂家_CNC散热器加工-惠州市铂源五金制品有限公司 | 安徽净化板_合肥岩棉板厂家_玻镁板厂家_安徽科艺美洁净科技有限公司 | 东莞螺杆空压机_永磁变频空压机_节能空压机_空压机工厂批发_深圳螺杆空压机_广州螺杆空压机_东莞空压机_空压机批发_东莞空压机工厂批发_东莞市文颖设备科技有限公司 | 污水处理设备,一体化泵站,一体化净水设备-「梦之洁环保设备厂家」 | 网站优化公司_北京网站优化_抖音短视频代运营_抖音关键词seo优化排名-通则达网络 | 冷却塔改造厂家_不锈钢冷却塔_玻璃钢冷却塔改造维修-广东特菱节能空调设备有限公司 | 实战IT培训机构_IT培训班选大学生IT技术培训中心_中公优就业 | 申江储气罐厂家,储气罐批发价格,储气罐规格-上海申江压力容器有限公司(厂) | 西安中国国际旅行社(西安国旅) | 橡胶接头|可曲挠橡胶接头|橡胶软接头安装使用教程-上海松夏官方网站 | 临沂招聘网_人才市场_招聘信息_求职招聘找工作请认准【马头商标】 | 哈尔滨发电机,黑龙江柴油发电机组-北方星光 | 上海公司注册-代理记账-招投标审计-上海昆仑扇财税咨询有限公司 上海冠顶工业设备有限公司-隧道炉,烘箱,UV固化机,涂装设备,高温炉,工业机器人生产厂家 | 新材料分散-高速均质搅拌机-超声波分散混合-上海化烁智能设备有限公司 |