如何用新加密的数据更新部分加密数据? [英] How to update part of the encrypted data with newly encrypted data?

查看:163
本文介绍了如何用新加密的数据更新部分加密数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在生成音频文件时对其进行加密。我正在使用虚拟数据加密标头(因为我不知道音频数据的实际大小),并在运行时加密音频数据。我的计划是用音频文件的实际数据大小更新最后的标题。

I need to encrypt an audio file while it is being generated. I am encrypting header with dummy data(because I don't know the actual size of audio data) at the starting and encrypting the audio data on the fly. My plan is to update the header at the end with actual data size of audio file.

但是,当我试图用新加密的标题数据覆盖加密的标题数据时通过使用相同的密钥和IV相同的大小,并尝试稍后解密,我正在生成垃圾数据。

But, When I tried to overwrite the encrypted header data with newly encrypted header data of same size by using same key and IV and try to decrypt later, I am getting junk data generated.

为什么即使我使用相同的密钥和IV也会发生这种情况?在下面的代码中,我试图模拟我正在做的事情。生成大小为64字节的加密文件,生成大小为50字节的解密文件。

Why is this happening even though I am using same key and IV? In the below code I tried to simulate what I am doing. Encrypted file of size 64 bytes generated and decrypted file of size 50 bytes generated.

无更新:abcdabcdab0123456789012345678901234567890123456789

Without updation: abcdabcdab0123456789012345678901234567890123456789

使用标题更新:ABCDABCDAB÷<þ@óMCKLZƒÖ^Ô234567890123456789

With header updation: ABCDABCDAB÷‹þ@óMCKL­ZƒÖ^Ô234567890123456789

预期输出:ABCDABCDAB0123456789012345678901234567890123456789

Expected output: ABCDABCDAB0123456789012345678901234567890123456789

这是否正确实现已加密数据部分更新的方法?

Is this the right approach to achieve partial update of already encrypted data?

protected void Encrypt()
{

    byte[] numBytes = {'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9', '0','1','2','3','4','5','6','7','8','9', '0','1','2','3','4','5','6','7','8','9'};
    byte[] smallCase = {'a','b','c','d','a','b','c','d','a','b','c','d','a','b','c','d'};
    byte[] capitalCase = {'A','B','C','D','A','B','C','D','A','B','C','D','A','B','C','D'};

    try {
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2withHmacSHA1And8BIT");
        KeySpec spec = new PBEKeySpec("junglebook".toCharArray(), "Salt".getBytes(), 65536, 256);
        SecretKey tmp = null;
        tmp = factory.generateSecret(spec);
        SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

        /* Encryption cipher initialization. */
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secret);

        AlgorithmParameters params = cipher.getParameters();
        byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();

        Log.d("Encryption" + "iv data :", iv.toString());

        /*Open two Cipher ouput streams to the same encrypted file*/
        FileOutputStream os = new FileOutputStream(sdCard.getAbsolutePath() + "/Notes/sample.encrypted");
        CipherOutputStream cos = new CipherOutputStream(os,cipher);

        FileOutputStream os1 = new FileOutputStream(sdCard.getAbsolutePath() + "/Notes/sample.encrypted");
        CipherOutputStream cos1 = new CipherOutputStream(os1,cipher);

        int offset = 0;
        Log.d("Encryption", "Writing cipher text to output file");
        //Write 16 bytes header data with smallCase array
        cos.write(smallCase, offset, 16);
        // write 40 bytes actual data
        cos.write(numBytes, offset, 40);

        FileOutputStream ivStream = new FileOutputStream(sdCard.getAbsolutePath() + "/Notes/iv.dat");
        if (ivStream != null) {
            Log.d("Encryption", "Writing iv data to output file");
            ivStream.write(iv);
        }
        cos.close();

        // Overwrite header data with capitalCase array data
        cos1.write(capitalCase, offset, 16);
        cos1.close();

        ivStream.close();

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

protected void Decrypt()
{
    byte[] dBytes = new byte[200];

    try {

        Log.d("Decryption", "Reading iv data ");
        File f1 = new File(sdCard.getAbsolutePath()+"/Notes/iv.dat");
        byte[] newivtext = new byte[(int)f1.length()];
        FileInputStream readivStream = new FileInputStream(sdCard.getAbsolutePath()+"/Notes/iv.dat");
        if(readivStream != null) {
            readivStream.read(newivtext);
        }

        // Generate the secret key from same password and salt used in encryption
        SecretKeyFactory dfactory = SecretKeyFactory.getInstance("PBKDF2withHmacSHA1And8BIT");
        KeySpec dspec = new PBEKeySpec("junglebook".toCharArray(), "Salt".getBytes(), 65536, 256);
        SecretKey dtmp = dfactory.generateSecret(dspec);
        SecretKey dsecret = new SecretKeySpec(dtmp.getEncoded(), "AES");

        // Initialize dcipher
        Cipher dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        dcipher.init(Cipher.DECRYPT_MODE, dsecret, new IvParameterSpec(newivtext));

        FileInputStream inputStream = new FileInputStream(sdCard.getAbsolutePath()+"/Notes/sample.encrypted");
        CipherInputStream cis = new CipherInputStream(inputStream,dcipher);
        FileOutputStream os = new FileOutputStream(sdCard.getAbsolutePath() + "/Notes/sample.decrypted");

        int b = cis.read(dBytes);
        while(b != -1) {
            Log.d("Decryption","Bytes decrypted" + b);
            os.write(dBytes, 0, b);
            b = cis.read(dBytes);
        }
        cis.close();
        os.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}


推荐答案

我建议你更新几件事:


  1. 你打开多个输出流到SAME文件,这很奇怪,运行时不应该允许你这样做。所以 - 如果你想要任何可预测的结果,只用一个输出写。

  1. you are opening multiple outputstreams to the SAME file, which is very strange, the runtime should not allow you to do that. So - write only with a single output if you want any predictable results.

你可以阅读有关操作模式的信息,请参阅 CRT 模式不使用填充,并允许您仅更新密文的一部分(假设您不使用认证加密)。所以 AES / CTR / NoPadding 可以解决您的问题。 (并且如果你正确地执行它应该没有额外的字节)

You may read about the mode of operations see the CRT mode uses no padding and allows you to update only a portion of the ciphertext (assuming you use no authenticated encryption). So AES/CTR/NoPadding could solve your problem. (and there should be no extra bytes if you do it correctly)

你可以使用 RandomAccessFile 并覆盖所需密文的部分内容。

you can update a portion of the file using the RandomAccessFile and overwrite portion of the ciphertext what is needed.

这篇关于如何用新加密的数据更新部分加密数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆