Java 如何通过DCT使用AES进行加密&;IDCT并将其解密回来?
目前,我正在Android中进行图像加密和离散余弦变换(从概念上讲,它在中的工作应该几乎相同,但加密/解密步骤不同,并且没有洗牌步骤) 加密代码如下:Java 如何通过DCT使用AES进行加密&;IDCT并将其解密回来?,java,android,encryption,dct,Java,Android,Encryption,Dct,目前,我正在Android中进行图像加密和离散余弦变换(从概念上讲,它在中的工作应该几乎相同,但加密/解密步骤不同,并且没有洗牌步骤) 加密代码如下: 每个8x8块中的DCT 加密阵列坐标(0,0)处的DC值/低频值 将加密的字节转换为双数组 将第一个双精度数组保存到坐标(0,0) 将第二个双精度阵列保存到坐标(7,7) 执行IDCT 使用color.RGBA()函数将结果块从IDCT转换为RGBA颜色 把它和像素放在一起形成图像 解密本身: 每个8x8块中的DCT 从坐标(0,0)和(7,7)
color.RGBA()
函数将结果块从IDCT转换为RGBA颜色color.RGBA()
函数将结果块从IDCT转换为RGBA颜色//加密
私有静态字节[]加密(字节[]原始,字节[]清除)引发异常{
SecretKeySpec skeySpec=新SecretKeySpec(原始,加密算法);
Cipher Cipher=Cipher.getInstance(“AES”);
cipher.init(cipher.ENCRYPT_模式,skeySpec);
返回密码.doFinal(清除);
}
//解密
私有静态字节[]解密(字节[]原始,字节[]加密)引发异常{
SecretKeySpec skeySpec=新SecretKeySpec(原始,加密算法);
Cipher Cipher=Cipher.getInstance(“AES”);
cipher.init(cipher.DECRYPT_模式,skeySpec);
返回cipher.doFinal(加密);
}
公共静态字节[]toByteArray(双值){
字节[]字节=新字节[8];
ByteBuffer.wrap(字节).putDouble(值);
返回字节;
}
公共静态字节[]toByteArray(双[]双数组){
整数倍=Double.SIZE/Byte.SIZE;
字节[]字节=新字节[doubleArray.length*倍];
对于(int i=0;我有一个提示:您可以在CTR模式下使用AES创建一个流密码,只需按照本文操作即可,不过如果要重用密钥,您需要将IV存储在某个位置。@MaartenBodewes我最后提出了一个新问题,即如何将字节数组转换为8位int数组
// To encrypt
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, encryptAlgorithm);
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
return cipher.doFinal(clear);
}
// To decrypt
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, encryptAlgorithm);
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
return cipher.doFinal(encrypted);
}
public static byte[] toByteArray(double value) {
byte[] bytes = new byte[8];
ByteBuffer.wrap(bytes).putDouble(value);
return bytes;
}
public static byte[] toByteArray(double[] doubleArray){
int times = Double.SIZE / Byte.SIZE;
byte[] bytes = new byte[doubleArray.length * times];
for(int i=0;i<doubleArray.length;i++){
ByteBuffer.wrap(bytes, i*times, times).putDouble(doubleArray[i]);
}
return bytes;
}
public static double[] toDouble(byte[] bytes) {
ByteBuffer bb = ByteBuffer.wrap(bytes);
DoubleBuffer db = bb.asDoubleBuffer();
double[] copy = new double[db.capacity()];
db.get(copy);
return copy;
}
public static Bitmap applyEncryption(Bitmap image, int blockSize) throws Exception {
int xPos = 0, yPos = 0, a = 0, b = 0;
int _w = image.getWidth();
int _h = image.getHeight();
int reconstImage[][] = new int[_w][_h];
double dctArrayGray[][] = new double[8][8];
// It will convert image bitmap pixels to 2-D arrays
int[][] imageData = bitmapToArray(image);
for (int i = 0; i< (_w / blockSize); i++) {
xPos = i * blockSize;
for (int j = 0; j < (_h / blockSize); j++) {
yPos = j * blockSize;
for (a = 0; a < blockSize; a++) {
for (b = 0; b < blockSize; b++) {
dctArrayGray[a][b] = (double) Color.red(imageData[xPos + a][yPos + b]);
}
}
DoubleDCT_2D dct = new DoubleDCT_2D(blockSize, blockSize);
dct.forward(dctArrayGray, true);
// Perform Encryption here....
byte[] chiperBytes = encrypt("ThisIsASecretKey".getBytes(), toByteArray(dctArrayGray[0][0]));
// This is the problem
// it will overflow the minimum/maximum DCT values, since there are max/min
// when performing DCT
// 1. Save the first array in coordinate (0,0)
dctArrayGray[0][0] = toDouble(chiperBytes)[0];
// 2. save the second array in coordinate (7,7)
dctArrayGray[7][7] = toDouble(chiperBytes)[1];
// This is the problem I think, it may have "bits lost", after I perform `Color.rgba()` on each block to get pixel values, after below looping.
// If I perform `dct.reverse` again, I will not get the same value as the `chiperBytes`
// since it will also be decrypted (see the decryption function below this function).
dct.inverse(dctArrayGray, true);
for (a = 0; a < blockSize; a++) {
for (b = 0; b < blockSize; b++) {
int red = (int) Math.round(dctArrayGray[a][b]);
reconstImage[xPos+a][yPos + b] = Color.argb(0xFF, red, red, red);
}
}
}
}
// It will convert back the 2-D array to Bitmap image
return arrayToBitmap(reconstImage);
}
// Decryption
public static Bitmap applyDecryption(Bitmap decryptedImage, int blockSize) throws Exception {
int xPos = 0, yPos = 0, a = 0, b = 0;
int _w = decryptedImage.getWidth();
int _h = decryptedImage.getHeight();
int reconstImage[][] = new int[_w][_h];
double dctArrayGray[][] = new double[8][8];
// It will convert image bitmap pixels to 2-D arrays
int[][] imageData = bitmapToArray(decryptedImage);
for (int i = 0; i< (_w / blockSize); i++) {
xPos = i * blockSize;
for (int j = 0; j < (_h / blockSize); j++) {
yPos = j * blockSize;
for (a = 0; a < blockSize; a++) {
for (b = 0; b < blockSize; b++) {
dctArrayGray[a][b] = (double) Color.red(imageData[xPos + a][yPos + b]);
}
}
DoubleDCT_2D dct = new DoubleDCT_2D(blockSize, blockSize);
dct.forward(dctArrayGray, true);
// Perform Decryption here....
// Get back the double values
double[] encryptedDoubleValues = new double[2];
encryptedDoubleValues[0] = dctArrayGray[0][0];
encryptedDoubleValues[1] = dctArrayGray[7][7];
// I got chiper block not completed EXCEPTION since I got bits lost during saving the encryption
// block to image and after converting to RGBA from IDCT (Inverse DCT)
byte[] chiperBytes = decrypt("ThisIsASecretKey".getBytes(), toByteArray(encryptedDoubleValues));
// 1. Save the first array in coordinate (0,0)
// This line below suppose to bring back the original value / almost the same with original
dctArrayGray[0][0] = toDouble2(chiperBytes);
// 2. save the second array in coordinate (7,7) and set it to zero
// (since AC values are expected to be loss and not necessary needed)
dctArrayGray[7][7] = 0;
dct.inverse(dctArrayGray, true);
for (a = 0; a < blockSize; a++) {
for (b = 0; b < blockSize; b++) {
int red = (int) Math.round(dctArrayGray[a][b]);
reconstImage[xPos+a][yPos + b] = Color.argb(0xFF, red, red, red);
}
}
}
}
// It will convert back the 2-D array to Bitmap image
return arrayToBitmap(reconstImage);
}