Monte Carlo 测试的 AES CBC 解密验证

AES CBC decryption validation for Monte Carlo Tests

我正在尝试在 AES CBC 上执行 MCT。伪代码记录在此处:https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/aes/AESAVS.pdf section 6.4.2

注意伪代码有错误,这里揭示:

通过结合这两个参考资料,我能够为 MCT 提出一个有效的加密测试。以下代码显示了工作加密模块(给定初始密钥 iv 和明文作为十六进制字符串):

def monte_carlo_encrypt(key_len, initial_key, initial_iv, initial_pt):

    key_array = []
    iv_array = []
    pt_array = []
    ct_array = []

    key_array.append(bytes.fromhex(initial_key))
    iv_array.append(bytes.fromhex(initial_iv))
    pt_array.append(bytes.fromhex(initial_pt))

    for j in range(0, 1000):
        if j == 0:
            ct = encrypt(key_array[0], iv_array[0], pt_array[j])
            ct_array.append(ct)
            pt_array.append(iv_array[0])
        else:
            ct = encrypt(key_array[0], ct_array[j - 1], pt_array[j])
            ct_array.append(ct)
            pt_array.append(ct_array[j - 1])

    if key_len == 128:
        key_array.append(bytes(a ^ b for a, b in zip(key_array[0], ct_array[j])))
    elif key_len == 256:
        key_array.append(bytes(a ^ b for a, b in zip(key_array[0], ct_array[j - 1] + ct_array[j])))

    iv_array.append(ct_array[-1])
    pt_array.clear()
    pt_array.append(ct_array[-2])

    return key_array[-1], iv_array[-1], pt_array[-1], ct_array[-1]
                    
for k in range(0, 100):
    (next_key, next_iv, next_pt, next_ct) = monte_carlo_encrypt(key_len * 8,
                                                                key.hex().upper(),
                                                                iv.hex().upper(),
                                                                given_pt.hex().upper())

     key = next_key
     iv = next_iv
     given_pt = next_pt

以上测试产生了正确的结果,可以使用上面链接的 Whosebug 问题中概述的标准进行测试。

现在,当我尝试将其改编为解密时,问题出现了。根据 NIST 参考资料,“
的伪代码 解密可以通过将所有 PT 替换为 CT 并将所有 CT 替换为 PT 来获得。 “

所以,我试过了,想出了这个:

def monte_carlo_decrypt(key_len, initial_key, initial_iv, initial_ct):

    key_array = []
    iv_array = []
    pt_array = []
    ct_array = []

    key_array.append(bytes.fromhex(initial_key))
    iv_array.append(bytes.fromhex(initial_iv))
    ct_array.append(bytes.fromhex(initial_ct))

    for j in range(0, 1000):
        if j == 0:
            pt = decrypt(key_array[0], iv_array[0], ct_array[j])
            pt_array.append(pt)
            ct_array.append(iv_array[0])
        else:
            pt = decrypt(key_array[0], pt_array[j - 1], ct_array[j])
            pt_array.append(pt)
            ct_array.append(pt_array[j - 1])

    if key_len == 128:
        key_array.append(bytes(a ^ b for a, b in zip(key_array[0], pt_array[j])))
    elif key_len == 256:
        key_array.append(bytes(a ^ b for a, b in zip(key_array[0], pt_array[j - 1] + pt_array[j])))

    iv_array.append(pt_array[-1])
    ct_array.clear()
    ct_array.append(pt_array[-2])

    return key_array[-1], iv_array[-1], pt_array[-1], ct_array[-1]

for k in range(0, 100):
    (next_key, next_iv, next_pt, next_ct) = monte_carlo_decrypt(key_len * 8,
                                                                key.hex().upper(),
                                                                iv.hex().upper(),
                                                                given_ct.hex().upper())
     key = next_key
     iv = next_iv
     given_ct = next_ct

但是这个解密模块在第一次迭代时就把解密弄错了。给定:

        "iv": "9982F2D532BC341791ECC30A1FEA9A3F",
        "key": "A58C28340553879F488E161CF815D104",
        "ct": "349F129B75B99E845D99090B26801D12"

它应该产生:

            "key": "A58C28340553879F488E161CF815D104",
            "iv": "9982F2D532BC341791ECC30A1FEA9A3F",
            "pt": "9B2F1D63DE3809F47E40EFB885F01277",
            "ct": "349F129B75B99E845D99090B26801D12"

但我的产生:

                            "key": "A58C28340553879F488E161CF815D104",
                            "iv": "9982F2D532BC341791ECC30A1FEA9A3F",
                            "pt": "23119C0130042FDA973D171E9E9E4921",
                            "ct": "349F129B75B99E845D99090B26801D12"

有人看到我的解密实施哪里出了问题吗?

我找到了答案。我找到了这个参考,它在伪代码方面比 NIST 参考更有帮助:https://www.ipa.go.jp/security/jcmvp/jcmvp_e/documents/atr/atr01b_en.pdf section 3.4.3.2.2

这是有效的解密代码:

def monte_carlo_decrypt(key_len, initial_key, initial_iv, initial_ct):

    key_array = []
    iv_array = []
    pt_array = []
    ct_array = []

    key_array.append(bytes.fromhex(initial_key))
    iv_array.append(bytes.fromhex(initial_iv))
    ct_array.append(bytes.fromhex(initial_ct))

    for j in range(0, 1000):
        pt = decrypt(key_array[0], iv_array[j], ct_array[j])
        pt_array.append(pt)
        if j == 0:
            tmp = ct_array[j]
            ct_array.append(iv_array[j])
            iv_array.append(tmp)
        else:
            iv_array.append(ct_array[j])
            ct_array.append(pt_array[j - 1])

    if key_len == 128:
        key_array.append(bytes(a ^ b for a, b in zip(key_array[0], pt_array[j])))
    elif key_len == 256:
        key_array.append(bytes(a ^ b for a, b in zip(key_array[0], pt_array[j - 1] + pt_array[j])))

    iv_array.append(pt_array[-1])
    ct_array.clear()
    ct_array.append(pt_array[-2])

    return key_array[-1], iv_array[-1], pt_array[-1], ct_array[-1]

for k in range(0, 100):
    (next_key, next_iv, next_pt, next_ct) = monte_carlo_encrypt(key_len * 8,
                                                            key.hex().upper(),
                                                            iv.hex().upper(),
                                                       given_pt.hex().upper())
    key = next_key
    iv = next_iv
    given_pt = next_pt