PKZIP加解密密钥推导流程及密钥获取方法技术问询
PKZIP流密码密钥获取详解
一、PKZIP流密码基础
PKZIP流密码是对称加密方案,加解密共用同一密钥,该密钥用于为一次性密码本算法生成字节密钥流。其96位内部状态由三个32位值组成:key0、key1、key2。
二、密钥初始化流程(解密步骤1)
根据PKWARE规范,密钥初始化分为初始赋值和密码迭代更新两个阶段:
1. 初始密钥赋值
先设置三个密钥的初始固定值:
Key(0) <- 305419896 Key(1) <- 591751049 Key(2) <- 878082192
2. 密码迭代更新(update_keys函数)
遍历密码的每个字符,调用update_keys函数迭代更新密钥,函数逻辑如下:
update_keys(char): Key(0) <- crc32(key(0), char) // 用当前字符更新key0的CRC32值 Key(1) <- Key(1) + (Key(0) & 0x000000FF) // 取key0的低8位加到key1 Key(1) <- Key(1) * 134775813 + 1 // 线性变换更新key1 Key(2) <- crc32(key(2), (Key(1) >> 24)) // 取key1的高8位更新key2的CRC32值
以示例密码1234为例,先将每个字符转换为ASCII值('1'=0x31,'2'=0x32,'3'=0x33,'4'=0x34),依次传入update_keys,即可得到步骤1完成后的初始密钥。
三、通过加密头更新密钥(解密步骤2)
完成步骤1后,需要读取12字节加密头,逐个字节解密并同步更新密钥,最终得到用于解密压缩数据的密钥,流程如下:
- 生成伪随机字节:从当前密钥生成用于解密的伪随机字节,函数逻辑:
generate_byte(): temp = Key(2) | 2 return (temp * (temp ^ 1)) >> 8 - 解密字节:对加密头的单个字节执行异或运算:
plain_byte = cipher_byte ^ generate_byte() - 更新密钥:用解密得到的
plain_byte调用update_keys函数,更新三个密钥 - 重复上述三步,处理完12个加密头字节后,得到的三个密钥就是最终可用的解密密钥
额外验证逻辑:解密后的12字节明文头的CRC32值需与给定的校验值匹配(示例中为
E07B8FC3),若不匹配则说明密码错误。
四、示例数据验证步骤
以你的测试数据为例:
- 密码:
1234 - 加密头:
3A CE 1D 8D E4 D1 ED D1 E5 08 4F EC - 校验CRC:
E07B8FC3
执行流程:
- 用初始密钥 + 密码
1234迭代更新,得到步骤1的密钥; - 逐个处理加密头的12个字节:每个字节先解密,再用解密后的字节更新密钥;
- 解密完成后,计算明文头的CRC32值,若等于
E07B8FC3,则此时的三个密钥即为正确的解密密钥。
内容的提问来源于stack exchange,提问作者terry franklin
相关产品推荐
相关产品推荐

