- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个问题。以我在密码学方面的有限经验。
如何在没有身份验证标签的情况下解密 AES-128-GCM。
我找到了 AES GCM decryption bypassing authentication in JAVA好像解决了一些问题。但只有 iv 等于 96 位才能工作。
shadowsocksr OpenSSL support aes-128-gcm .不同于其他使用认证标签的aes-128-gcm加密或解密。
我写了一个测试脚本并得到了结果。
脚本:
from shadowsocks import encrypt
import binascii
ivLength = 16
key, iv = encrypt.EVP_BytesToKey(b"killer",16,12,None)
print("key: ",binascii.hexlify(key))
print("iv: ",binascii.hexlify(iv))
cipher = encrypt.Encryptor("killer","aes-128-gcm",iv=iv)
hello = cipher.encrypt(bytes("hello","utf-8"))
dehello = cipher.decrypt(hello)
print("origin: " ,binascii.hexlify(b'hello'))
print("Ciphertext: ",binascii.hexlify(hello))
print("Cleartext: ",binascii.hexlify(dehello))
当 ivLength 设置为 12 时:
key: b'b36d331451a61eb2d76860e00c347396'
iv: b'271d7f17d03ed7cd1f443274'
origin: b'68656c6c6f'
Ciphertext: b'e0fc2227c40bc9ea9343a1faafa4e23da750a9ad00'
Cleartext: b'68656c6c6f'
当 ivLength 设置为 16 时:
key: b'b36d331451a61eb2d76860e00c347396'
iv: b'271d7f17d03ed7cd1f44327456aebfa2'
origin: b'68656c6c6f'
Ciphertext: b'271d7f17d03ed7cd1f44327456aebfa215988b0365'
Cleartext: b'68656c6c6f'
我想用Java解密。正如提到的方法 Maarten Bodewes。我写了一个Java代码来解密上面的结果:
环境:
操作系统环境:window 10
jdk版本:JDK11
依赖:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0.1-jre</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
代码:
package server;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.ArrayUtils;
import org.junit.Test;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
public class StackOverflow {
@Test
public void AES_128_GCM_DECRYPT_TEST() throws IOException, NoSuchAlgorithmException, InvocationTargetException, NoSuchMethodException, InvalidKeyException, InvalidAlgorithmParameterException, NoSuchPaddingException, BadPaddingException, IllegalAccessException, DecoderException, ShortBufferException, IllegalBlockSizeException, ClassNotFoundException {
String ciphertext_with_iv_12 = "e0fc2227c40bc9ea9343a1faafa4e23da750a9ad00";
String ciphertext_with_iv_16 = "a54a0301968953c0b45288f4d78c4011800f974c2d";
System.out.println("--------------- descript with iv 12 ---------------");
AES_128_GCM_DECRYPT(ciphertext_with_iv_12, "killer", 16, 12);
System.out.println("--------------- descript with iv 16 ---------------");
AES_128_GCM_DECRYPT(ciphertext_with_iv_12, "killer", 16, 16);
}
public static void AES_128_GCM_DECRYPT(String ciphertext,String password,int keyLength,int ivLength) throws DecoderException, NoSuchPaddingException, NoSuchAlgorithmException, IOException, InvalidAlgorithmParameterException, InvalidKeyException, ShortBufferException, BadPaddingException, IllegalBlockSizeException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
byte[] cipherdata = Hex.decodeHex(ciphertext);
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
Object[] item = EVP_BytesToKey(password, keyLength, ivLength);
byte[] key = (byte[]) item[0];
byte[] iv = ArrayUtils.subarray(cipherdata, 0, ivLength);
//byte[] counter = Bytes.concat(iv, new byte[4]);
byte[] counter = getJ0Proxy(iv, key);
inc(counter);
final IvParameterSpec gcmParameterSpec = new IvParameterSpec(counter);
final SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
byte[] data = ArrayUtils.subarray(cipherdata, 16, cipherdata.length);
byte[] result = cipher.doFinal(data, 0, data.length);
System.out.println(String.format("key: %s", Hex.encodeHexString(key)));
System.out.println(String.format("iv: %s", Hex.encodeHexString(iv)));
System.out.println(String.format("origin: %s", Hex.encodeHexString("hello".getBytes())));
System.out.println(String.format("Ciphertext: %s", Hex.encodeHexString(data)));
System.out.println(String.format("Cleartext: %s", Hex.encodeHexString(result)));
}
/**
* if iv is not 96 bit,it need more complex approach to generate iv
*
* @param key
* @return
*/
public static final byte[] getSubKey(byte[] key) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> galoisCounterMode = Class.forName("com.sun.crypto.provider.GaloisCounterMode");
Class<?> aesCrypt = Class.forName("com.sun.crypto.provider.AESCrypt");
Constructor constructor = aesCrypt.getDeclaredConstructor();
constructor.setAccessible(true);
Object aesCryptInstance = constructor.newInstance();
Method aesInstanceInit = aesCrypt.getDeclaredMethod("init", boolean.class, String.class, byte[].class);
aesInstanceInit.setAccessible(true);
aesInstanceInit.invoke(aesCryptInstance, false, "AES", key);
byte[] subKey = new byte[16];
Method aesInstanceEncryptBlock = aesCrypt.getDeclaredMethod("encryptBlock", byte[].class, int.class, byte[].class, int.class);
aesInstanceEncryptBlock.setAccessible(true);
aesInstanceEncryptBlock.invoke(aesCryptInstance, new byte[16], 0, subKey, 0);
return subKey;
}
/**
* generator iv for CTR use.
*
* @param iv
* @param subkey
* @return
*/
public static final byte[] getJ0Proxy(byte[] iv, byte[] subkey) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class<?> galoisCounterMode = Class.forName("com.sun.crypto.provider.GaloisCounterMode");
Method getJ0 = galoisCounterMode.getDeclaredMethod("getJ0", byte[].class, byte[].class);
getJ0.setAccessible(true);
return (byte[]) getJ0.invoke(null, iv, subkey);
}
/**
* invok jdk com.sun.crypto.provider.GaloisCounterMode static method increment32
*
* @param counter iv
*/
private static final void inc(byte[] counter) throws InvocationTargetException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException {
Class<?> galoisCounterMode = Class.forName("com.sun.crypto.provider.GaloisCounterMode");
Method getJ0 = galoisCounterMode.getDeclaredMethod("increment32", byte[].class);
getJ0.setAccessible(true);
getJ0.invoke(null, counter);
}
/**
* for generator key and iv
*
* @param password password
* @param keyLength keyLength
* @param ivLength ivLength
* @return array have 2 element the index of 0 is key and index of 1 is iv.
* @throws NoSuchAlgorithmException
* @throws UnsupportedEncodingException
*/
public static Object[] EVP_BytesToKey(String password, int keyLength, int ivLength) throws NoSuchAlgorithmException, UnsupportedEncodingException {
ArrayList<byte[]> m = new ArrayList();
int i = 0;
while (getByteArray(m) < keyLength + ivLength) {
String data = password;
if (i > 0) {
data = new String(m.get(i - 1), "ISO-8859-1") + password;
}
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] dataDigest = digest.digest(data.getBytes("ISO-8859-1"));
m.add(dataDigest);
i += 1;
}
byte[] ms = joinByteArray(m);
byte[] key = ArrayUtils.subarray(ms, 0, keyLength);
byte[] iv = ArrayUtils.subarray(ms, keyLength, keyLength + ivLength);
return new Object[]{key, iv};
}
public static int getByteArray(List<byte[]> array) {
int length = 0;
for (byte[] item : array) {
length += item.length;
}
return length;
}
public static byte[] joinByteArray(List<byte[]> array) {
int length = getByteArray(array);
byte[] result = new byte[length];
int pos = 0;
for (byte[] item : array) {
System.arraycopy(item, 0, result, pos, item.length);
pos += item.length;
}
return result;
}
}
结果:
--------------- descript with iv 12 ---------------
key: b36d331451a61eb2d76860e00c347396
iv: e0fc2227c40bc9ea9343a1fa
origin: 68656c6c6f
Ciphertext: a750a9ad00
Cleartext: 68656c6c6f
--------------- descript with iv 16 ---------------
key: b36d331451a61eb2d76860e00c347396
iv: e0fc2227c40bc9ea9343a1faafa4e23d
origin: 68656c6c6f
Ciphertext: a750a9ad00
Cleartext: dead0c78cf
当iv的长度不是96bit时,结果是错误的。
我希望有人能告诉我哪里出了问题。
提前致谢。
最佳答案
这是预期的结果。如果您查看 Nist 800-38D ,第 15 页,您会看到:
if len(IV)=96 then
Y0=IV||0^31||1
else
Y0=GHASH(H,{},IV).
因此,较大的 IV 不会被修剪,因此建议进行额外的操作。通过这种方式,您的 IV 可以获得更高的熵。
关于java - 没有身份验证标签的 AES GCM 解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53567849/
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!