//循环位移操作 #define ROTL(x, y) (((x) << ((y) & (w - 1))) | ((x) >> (w - ((y) & (w - 1))))) #define ROTR(x, y) (((x) >> ((y) & (w - 1))) | ((x) << (w - ((y) & (w - 1)))))
1 2 3 4 5 6 7 8
uint32_t A = in[0] + S[0]; uint32_t B = in[1] + S[1]; for (int i = 1; i <= r; i++) { A = ROTL(A ^ B, B) + S[2 * i]; B = ROTL(B ^ A, A) + S[2 * i + 1]; } //in[2]是明文被分为2个块 //ROTL是循环位移
扩展密钥
子密钥生成
这一步使用两个常量P和Q。生成的子密钥数组称为S,第一个子密钥为S[0]用P值初始化。
每个后续子密钥(S[1],S[2],…)根据前面的子密钥和常量Q求出,用2的32次方
求模。这个过程要进行2(r+1)-1次,其中r位轮数。下图显示了子密钥生成的数学形式:
这个过程把主密钥 K 扩展为 S[0..25] 子密钥。
分步讲解:
1
voidgenerateSubkeys(uint8_t* K, uint32_t* S)
将字节数组 K 转换成 4个32位整数 L[0..3]
1 2 3 4 5 6
uint32_t L[c] = { 0 };
// 将密钥转换为小端序的32位字 for (int i = 0; i < b; i++) { L[i / 4] |= ((uint32_t)K[i]) << (8 * (i % 4)); }
uint32_t A = 0, B = 0; int i = 0, j = 0; for (int k = 0; k < 3 * t; k++) { A = S[i] = ROTL(S[i] + A + B, 3); B = L[j] = ROTL(L[j] + A + B, A + B); i = (i + 1) % t; j = (j + 1) % c; }
// 将密钥转换为大端序的32位字 for (int i = 0; i < b; i++) { L[i / 4] |= ((uint32_t)K[i]) << (8 * (3 - (i % 4))); }
// 子密钥生成 S[0] = 0xB7E15163;//常量Q,0x9E3779B9就是常量p for (int i = 1; i < t; i++) { S[i] = S[i - 1] + 0x9E3779B9; }
// 主,子密钥混合 uint32_t A = 0, B = 0; int i = 0, j = 0; for (int k = 0; k < 3 * t; k++) { A = S[i] = ROTL(S[i] + A + B, 3); B = L[j] = ROTL(L[j] + A + B, A + B); i = (i + 1) % t; j = (j + 1) % c; } }
// 加密函数 voidEncrypt(uint32_t* in, uint32_t* out, uint32_t* S) { uint32_t A = in[0] + S[0]; uint32_t B = in[1] + S[1]; for (int i = 1; i <= r; i++) { A = ROTL(A ^ B, B) + S[2 * i]; B = ROTL(B ^ A, A) + S[2 * i + 1]; } out[0] = A; out[1] = B; }
// 解密函数 voidDecrypt(uint32_t* in, uint32_t* out, uint32_t* S) { uint32_t A = in[0]; uint32_t B = in[1]; for (int i = r; i >= 1; i--) { B = ROTR(B - S[2 * i + 1], A) ^ A; A = ROTR(A - S[2 * i], B) ^ B; } out[0] = A - S[0]; out[1] = B - S[1]; }
uint32_tdynamic_key(uint8_t* key, int round, int offset) { int key_len = b; uint32_t val = 0;
for (int i = 0; i < 4; i++) { int index = (round * 2 + offset + i) % key_len; val |= (key[index] << (i * 8)); } return val; }
voidEncrypt(uint32_t* in, uint32_t* out, uint8_t* Key) { uint32_t A = in[0];//没有进行相加 uint32_t B = in[1]; for (int i = 1; i <= r; i++) { uint32_t K1 = dynamic_key(Key, i, 0); uint32_t K2 = dynamic_key(Key, i, 1); A = ROTL(A ^ B, B) + K1; B = ROTL(B ^ A, A) + K2; } out[0] = A; out[1] = B; }
你需要在调试器里看到 data 具体内容,才能提取 key。
有时 key 会被 RC4 或 Base64 混淆,还要先解密才行。
魔改方式四:固定的 RC5 解密逻辑,无 S盒 和 key
将 RC5 的轮函数结果写死,作为“定值函数”。
1 2 3 4 5 6 7 8 9 10 11
voidfixed_rc5_decrypt(uint32_t *in, uint32_t *out) { uint32_t A = pt[0] + 0xB7E15163; uint32_t B = pt[1] + 0x5618CB1C;
A = ((A ^ B) << (B & 0x1F)) + 0xF45044D5; B = ((B ^ A) << (A & 0x1F)) + 0x9287BE8E;