【问题标题】:Increased cipher length in Integer array AES encryption整数数组 AES 加密中增加的密码长度
【发布时间】:2015-11-22 02:41:24
【问题描述】:

在下面的代码中,我采用了一个整数数组并执行了 AES 加密。输入是一个大小为 16 的整数数组。当我加密数据时,我得到 cipher byte[] 大小为 64。 很明显,一个整数占用4B,所以16 * 4 = 64,就是密码长度。但是如果我在图像(512 X 512)上实现相同的技术,那么密码图像的大小可能是原始图像的四倍! 在图像的情况下如何使密码长度等于明文长度??

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.security.MessageDigest;
import java.util.Arrays;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class StreamDemo2 {
    static String IV = "AAAAAAAAAAAAAAAA";
    static String encryptionKey = "0123456789abcdef";

    public static void main(String ad[])
    {
        StreamDemo2 st = new StreamDemo2();

        ByteArrayOutputStream baos = new ByteArrayOutputStream ();
        DataOutputStream dos = new DataOutputStream (baos);
        int arr[] = new int[16];

        for(int k = 0 ; k < 16; k++)
            arr[k] = k + 11;

        for(int k = 0 ; k < 16; k++)
            System.out.println(" USER Plain text = " + arr[k]);



        try{
            for(int i = 0; i < 16;i++)
                dos.writeInt (arr[i]);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        byte[] data = baos.toByteArray();
        // conversion to bytes ends here
        // Now follows the mehtod invoking
        byte[] c = null;

        try{
             c = st.encrypt(data, encryptionKey);
        }
        catch(Exception e )
        {
            e.printStackTrace();
        }

        System.out.println("Cipher length = " + c.length);

        // Now follows the code to decrypt

        byte[] d = null;

       try{
            d = st.decrypt(c, encryptionKey);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

        ByteArrayInputStream bais = new ByteArrayInputStream (d);
        DataInputStream dis = new DataInputStream (bais);
        int j;

        System.out.println("Original data is : ");
        try{
            for(int k =0; k < 16; k++)
                System.out.print(dis.readInt() + "\t");
            }
        catch(Exception e)
        {
            e.printStackTrace();
        }

    }

    public static byte[] encrypt(byte[] ciph, String encryptionKey) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
    cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
    return cipher.doFinal(ciph);
  }

  public static byte[] decrypt(byte[] cipherText, String encryptionKey) throws Exception{
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
    cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
    //return new String(cipher.doFinal(cipherText),"UTF-8"); // changed since the receiveing side expects the byte[]
    return cipher.doFinal(cipherText);
  }
}

【问题讨论】:

    标签: java image encryption encoding aes


    【解决方案1】:

    (AES) 加密直接作用于字节。它不知道您的图像有多大或如何编码。这是你必须考虑的。如果你有一个 512x512 像素的图像,那么你应该考虑它在序列化时是如何表示的。

    一个像素通常由三个通道组成。一个例子是 RGB(红 - 绿 - 蓝),其他的是 HSL/HSV/YCrCb。每个通道的常见细节深度为 8 位。所以你可以用 3 个字节来表示每个像素。如果您想正确读取这些像素,您应该知道尺寸有多大,因此您在图像数据格式的开头添加两个整数(尺寸限制)就完成了。这是最基本的格式

    3 * 512 * 512 + 2 * 4 bytes = 786440 bytes
    

    这不是 16 字节的倍数,因此需要填充以进行加密。这可以通过实例化提供填充的Cipher 直接实现。否则,您将不得不自己这样做:

    Cipher.getInstance("AES/CBC/PKCS5Padding");
    

    当然,如果您只有灰度图像或不同的通道深度(例如 16 位)以获得更高质量,则此示例计算看起来会有所不同。

    当你说的时候

    那么密码图像的大小可能是原始图像的四倍

    您将苹果与橙子(像素与字节)进行比较。但是,您可以将密文解释为图像数据。这是一个有趣的实验。看看ECB penguin。


    在测试阶段结束时,请务必使用正确的随机生成的加密密钥。可打印的密钥比随机生成的密钥更容易暴力破解。

    始终为每次加密使用新的随机生成的 IV。这提供了语义安全性。

    使用经过身份验证的加密来防止填充预言攻击和检测(恶意)操纵。这可以通过像 GCM 或 EAX 这样的身份验证模式来完成,或者使用像 HMAC-SHA256 这样具有强大 MAC 功能的 encrypt-then-MAC 方案来完成。

    【讨论】:

    • 主要任务是用图像格式表示密文。这就是为什么我正在考虑使用密文(以字节为单位)来编写图像。
    • 您的意思是即使明文不是图像,也可以从任意密文中写入图像?恐怕我不明白你想做什么。
    • 不...我的意思是这个。我从图像中读取像素,假设我读取图像的第一行像素并执行 AES 加密,我将得到密文;我将在每一行上重复相同的内容,我有所有行的密文。现在我不能将那些密码字节写回图像,因为它有负值,对吧?图像不会接受其像素的负值...我只需要具有普通图像的相应密码图像!这可以在研究论文中展示..
    • 这些并不是真正的负值。这是它们向您显示的方式,但字节的值可以是 0 到 255。有时它显示为值 128 到 255 映射到 -128 到 -1,但里面的数据仍然相同。您没有提供任何代码或关于您的实际问题的描述,坦率地说,这与我回答的问题完全不同。
    • @Arjtom B 请检查此链接 [stackoverflow.com/questions/33776494/…
    猜你喜欢
    • 1970-01-01
    • 2020-02-07
    • 2012-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-11
    相关资源
    最近更新 更多