1 条题解

  • 0
    @ 2025-5-19 20:23:16

    解题思路分析

    本题的核心在于利用两个加密消息之间的关联,通过异或运算的性质恢复密钥。关键在于分析两条消息对应的明文关系,结合异或运算的可逆性推导密钥。 问题建模 设两条加密消息对应的明文分别为:

    第一条明文C=[C1,C2,,CN]C = [C_1, C_2, \dots, C_N](长度为 N)第二条明文:C=[32,C1,C2,,CN]C' = [32, C_1, C_2, \dots, C_N](长度为 N+1N+1,开头添加空格字符 32) 设密钥为 K=[K1,K2,,KN+1]K = [K_1, K_2, \dots, K_{N+1}],则根据加密规则: 第一条加密消息:E1[i]=KiCiE_1[i] = K_i \oplus C_i1iN1 \leq i \leq N)第二条加密消息:E2[i]=KiCiE_2[i] = K_i \oplus C'_i1iN+11 \leq i \leq N+1,其中 C1=32C'_1 = 32Ci>1=Ci1C'_{i>1} = C_{i-1}

    关键推导

    推导 K1K_1 第二条明文的第一个字节为 32,对应加密结果 E2[1]=K132E_2[1] = K_1 \oplus 32,因此:K1=E2[1]32K_1 = E_2[1] \oplus 32推导 Ki>1K_{i>1} 对于 2iN+12 \leq i \leq N+1,第二条明文的第 i 字节等于第一条明文的第 i1i-1 字节,即 Ci=Ci1C'_i = C_{i-1}。 根据加密规则:$E_1[i-1] = K_{i-1} \oplus C_{i-1} \quad \text{(第一条消息)}$ E2[i]=KiCi1(第二条消息)E_2[i] = K_i \oplus C_{i-1} \quad \text{(第二条消息)} 将两式相异或(消去 Ci1C_{i-1}):E1[i1]E2[i]=Ki1KiE_1[i-1] \oplus E_2[i] = K_{i-1} \oplus K_i 由于 Ki1K_{i-1} 已知(通过前序推导),可递推得到 KiK_iKi=Ki1E1[i1]E2[i]K_i = K_{i-1} \oplus E_1[i-1] \oplus E_2[i]

    实现步骤

    输入解析

    将两条十六进制加密消息转换为字节数组(整数形式)。第一条消息长度为 N,对应字节数为 N;第二条长度为 N+1,对应字节数为 N+1。初始化

    密钥

    计算 K1K_1:通过第二条消息的第一个字节与 32 异或得到。递推计算后续密钥 对于 i 从 2 到 N+1N+1:取第一条消息的第 i2i-2 字节(索引从 0 开始)和第二条消息的第 i1i-1 字节。通过异或运算递推得到 Ki=Ki1E1[i2]E2[i1]K_i = K_{i-1} \oplus E_1[i-2] \oplus E_2[i-1]

    输出结果

    将密钥数组转换为十六进制字符串(大写,两位表示每个字节)。编辑分享如何进一步分析两条消息对应的明文关系?有没有其他方法可以恢复密钥?密钥的长度对恢复过程有什么影响?

    代码

    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int N=10001;
    inline int cread(){
    	int ch=getchar();
    	while((ch<'0'||ch>'9')&&(ch<'A'||ch>'F')&&ch!='\n'){
    		if(ch==EOF) return -2;
    		ch=getchar();
    	}
    	if(ch=='\n') return -1;
    	if(ch>='0'&&ch<='9') return ch-'0';
    	return ch-'A'+10;
    }
    short a[N],len;
    int main(){
    	int x=cread(),y;
    	while(x!=-2){
    		len=0;
    		while(1){
    			if(x==-1) break;
    			y=cread();
    			a[len++]=x*16+y;
    			x=cread();
    		}
    		int ex=32;
    		for(int i=0;i<=len;i++){
    			x=cread(),y=cread();
    			int b=x*16+y;
    			ex=b^ex;
    			printf("%02X",ex);
    			ex=ex^a[i];
    		}
    		puts("");
    		x=cread();
    		while(x==-1) x=cread();
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    1175
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    5
    已通过
    1
    上传者