java - 在java中解密加密的二进制文件(AES_CTR模式)
问题描述
我知道以前有人问过这个问题。我只需要一个方向来完成这些代码。如果有人能在我的代码中指出问题,那将非常有帮助
这是用于解密的Java代码
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.File;
class Decode{
public static void main(String []args){
try{
Decode.decrypt();
System.out.println("Decrypted");
}catch(Exception e){
System.out.println(e);
}
}
public static void decrypt() throws Exception {
byte[] initialIV;
final byte[] buf = new byte[128];
final Cipher c = Cipher.getInstance("AES/CTR/NoPadding");
final InputStream is = new FileInputStream("/home/neki/python/encVideo.mp4");
byte[] buffer = new byte[16];
is.read(buffer);
c.init(Cipher.DECRYPT_MODE,new SecretKeySpec("1234567890123456".getBytes(), "AES"),new IvParameterSpec(buffer));
final OutputStream os = new CipherOutputStream(new FileOutputStream("/home/neki/python/javaDecVideo.mp4"), c);
while (true) {
int n = is.read(buf);
if (n == -1) break;
os.write(buf, 0, n);
}
os.close(); is.close();
}
}
}
这是加密文件的python代码
import os, random, struct
from Crypto.Cipher import AES
from os import urandom
from Crypto.Util import Counter
def encrypt_file(key, in_filename, out_filename=None, chunksize=128):
if not out_filename:
out_filename = in_filename + '.enc'
iv = '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'
encryptor = AES.new(key, AES.MODE_CTR, counter = lambda : iv)
filesize = os.path.getsize(in_filename)
with open(in_filename, 'rb') as infile:
with open(out_filename, 'wb') as outfile:
# outfile.write(struct.pack('<Q', filesize))
outfile.write(iv)
while True:
chunk = infile.read(chunksize)
if len(chunk) == 0:
break
outfile.write(encryptor.encrypt(chunk))
encrypt_file("1234567890123456".encode(),"/home/neki/python/Eduaid.mp4","/home/neki/python/encVideo.mp4")
我还在stackoverflow中找到了一些想法。但不能很好理解。
解决方案
您配置此密码的方式非常不安全。不要使用此代码。
通过设置:
counter = lambda : iv
在 Python 中初始化 AES 密码时,您已强制 AES-CTR 对每个块使用完全相同的计数器。这将密码从 AES-CTR 简化为简单的滚动 XOR。观察:
>>> key = "abcd1234abcd1234"
>>> iv = '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'
>>> encryptor = AES.new(key, AES.MODE_CTR, counter = lambda : iv)
>>> encryptor.encrypt("example block 01")
'\xda\x7f\x00\xbdp\x1c\xe4\xf3=|\x88\xe2\xe5%\x80\xab'
>>> encryptor.encrypt("example block 01")
'\xda\x7f\x00\xbdp\x1c\xe4\xf3=|\x88\xe2\xe5%\x80\xab'
>>> encryptor.encrypt("example block 02")
'\xda\x7f\x00\xbdp\x1c\xe4\xf3=|\x88\xe2\xe5%\x80\xa8'
请注意:
重复加密同一块会产生相同的输出。
加密相似的块会产生相似的输出。(从技术上讲,
a XOR b = E(a) XOR E(b)
。)
要解决此问题,您需要使用Counter
已导入的类:
encryptor = AES.new(key, AES.MODE_CTR, counter=Counter.new(128))
正确配置 AES-CTR 后,您现有的 Java 代码应该能够解密它。
但是,请注意,如果重复使用相同的密钥来加密多个文件,这种模式仍然是不安全的。您必须为每个文件使用不同的密钥。
推荐阅读
- java - 如何在主线程中没有执行代码的情况下保持粘性服务的活动?
- android - Android Studio - 我无法在实时数据库 Fire base 中使用意图
- actionscript-3 - 尝试连接到 C# 服务器时,AS3 失败并出现“错误 #2048:违反安全沙箱”
- c++ - 模板参数表示“具有特定签名的可调用对象”
- typescript - 在不同的变量中排序数组打字稿离子
- c++ - C++:为什么我不需要取消引用来初始化动态数组?
- javascript - 我如何构建这个新逻辑以适应预先存在的代码?
- haskell - Haskell 不能传递变量
- java - 如何将此while循环转换为java中的for循环?
- r - R: '...' 在不正确的上下文中使用