gpt4 book ai didi

java - 在不知道 key 的情况下对 secret 后缀进行密码学解密

转载 作者:行者123 更新时间:2023-11-30 02:37:24 27 4
gpt4 key购买 nike

我在密码学方面遇到了这个问题。问题是我必须在不知道加密 key k 的情况下通过从 Oracle 查询来找到 secret 后缀 s。

我所掌握的有关加密如何完成的信息是,它是在 DES 下使用 ECB 模式、56 位 key 和 64 位输入 block 大小完成的。

所以我的问题是,根据上述所有信息,解密的步骤是什么。根据我的研究,我发现攻击者仅使用给定的密文是没有机会的。所以我想知道在这种情况下是否可以攻击它?

我得到的主要功能如下:

 public static void main(String[] args) {
String key = "3%ac^`+="; // a different key
String ciphertext = "a(19q-j*"; // a different suffix
Oracle1 oracle = new Oracle1(key.getBytes(), ciphertext.getBytes());
Attacker1 attacker = new Attacker1(oracle);
byte[] res = attacker.decryptCiphertext();
// should be true
System.out.println(isConsistent(ciphertext, res));
}

我应该在decryptCiphertext()中执行攻击并将结果作为字节数组返回,然后与给定的密文进行比较。如果比较结果为真,则正确。

Oracle.java

public class Oracle1 {

private static Logger logger = LoggerFactory.getLogger(Oracle1.class);

final private byte[] SuffixBytes;

private Cipher cipher;
private static String ALGO = Config.ALGO;
private static int BlockSize = getAlgoBlockSize(ALGO);

public Oracle1() {
this(Config.p1Key, Config.p1Suffix);
}

private void init(byte[] keyBytes) {
Security.addProvider(new BouncyCastleProvider());
SecretKey KEY;
try {
if (isSizeLegal(keyBytes, ALGO)) {
KEY = new SecretKeySpec(keyBytes, ALGO);
} else {
throw new RuntimeException(String.format("illegal ALGO %s with key length %d", ALGO, keyBytes.length));
}
cipher = Cipher.getInstance(String.format("%s/ECB/NoPadding", ALGO));
cipher.init(Cipher.ENCRYPT_MODE, KEY);
} catch (GeneralSecurityException e) {
e.printStackTrace();
System.exit(1);
}
}

public Oracle1(byte[] keyBytes, byte[] suffixBytes) {
SuffixBytes = suffixBytes;
init(keyBytes);
}

public Oracle1(String keyString, String suffixString) {
byte[] keyBytes = keyString.getBytes();
SuffixBytes = suffixString.getBytes();
init(keyBytes);
}

public byte[] compose(String plainText) {
return compose(plainText.getBytes());
}

public byte[] compose(byte[] bytes) {
int byteLength = bytes.length;
if (byteLength > BlockSize) {
logger.info("input length {} > {}", byteLength, BlockSize);
}

byte[] inputBytes = concat(bytes, SuffixBytes);
byte[] finalBytes = paddingBytes(inputBytes, BlockSize);
byte[] cipherBytes = new byte[0];
try {
cipherBytes = cipher.doFinal(finalBytes);
logger.info("input:{}\tcipher:{}", finalBytes, cipherBytes);
} catch (GeneralSecurityException e) {
e.printStackTrace();
System.exit(1);
}
return cipherBytes;
}

}

提前致谢。

最佳答案

我们有一个加密 Oracle,它允许我们发送消息 M并将返回E(M|S) (意思是 M + S 的加密,其中后缀是)。挑战是确定 S 。我假设给出的 key 和后缀是测试数据,以便在“真正”尝试之前测试代码(因为如果我们知道 key ,我们就可以自己解密结果)。

由于加密使用ECB,因此每个 block 都是独立加密的。我们可以用它来确定 S .

DES 的 block 大小为 8 字节。如果我们创建一个 7 字节长的输入(例如 7 0x00 字节),那么 Oracle 将追加 S然后对结果进行加密。这意味着生成的密文的第一个 block 将是加密的

0x00 0x00 0x00 0x00 0x00 0x00 0x00 X

哪里XS 的第一个字节。我们记下这个密文。

如果我们随后发送一系列 8 字节 block ,我们会像这样改变最终字节:

0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x03
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x04
...
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xff

并将它们与未知的密文进行比较,我们会找到匹配的密文。这样的区 block 只有 256 个,所以这不会花很长时间。然后我们就知道后缀的第一个字节。

然后我们可以对下一个字节重复此过程,但我们首先发送 6 字节消息而不是 7 字节消息,然后使用现在已知的第一个字节构建(最多)256 条测试消息,因此如果例如,第一个字节是 0x55,它们看起来像

0x00 0x00 0x00 0x00 0x00 0x00 0x55 0x01
0x00 0x00 0x00 0x00 0x00 0x00 0x55 0x02
...

重复此操作,我们可以确定 S一次一个字节。

<小时/>

看看您给出的代码,我认为这个想法可能是让您实现 Attacker1类(class),打电话oracle.compose()decryptSuffix() 内多次方法。 main然后您拥有的方法将用于测试您的代码。然后,您将提交这个类,并将使用“真正的”预言机对其进行测试。

关于java - 在不知道 key 的情况下对 secret 后缀进行密码学解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42698202/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com