【问题标题】:LPC18S37 - AES engine encrypts differently than Python libraryLPC18S37 - AES 引擎的加密方式与 Python 库不同
【发布时间】:2020-07-08 14:30:11
【问题描述】:

我正在尝试在 ECB 模式下使用 LPC18S37 的 AES 引擎来加密 16 字节的明文。我获得了一个密文,然后我通过解密过程来验证我得到了相同的原始明文,我确实这样做了。

但是,作为一项安全措施,我还希望使用外部资源进行验证,因此在 ECB 模式下使用 Python API (Crypto.Cipher.AES) 加密了相同的明文,但我没有得到相同的结果来自MCU的密文。问题是当我解密Python版本的密文时,结果是相同的原始明文。

我验证了 lib 的算法实现,并将其与 FIPS-197 标准进行了比较:它是正确实现的。

因此,我认为问题很可能来自我在 MCU 中的代码实现。

我当然会注意验证密钥和明文在两种情况下是否完全相同。

如果有人有建议或知道如何解决问题,我很乐意欢迎任何想法。

以下是单片机程序实现的相关部分:

Board_Init();

Chip_AES_Init();

//Set buffers :
        uint8_t RX_plaintext[16]; / /Contains a 16-bytes plaintext
        uint8_t TX_plaintext[16]; // WILL contain a 16-bytes plaintext after decryption
        uint8_t RX_key[16]; // Contains a 16-bytes key
        uint8_t TX_ciphertext[16]; // WILL contain the 16-bytes ciphertext after encryption

         ...

Chip_AES_LoadKeySW((uint8_t *) RX_key); // I like using verbose casts but this works the same way even without them

Chip_AES_SetMode(CHIP_AES_API_CMD_ENCODE_ECB);
Chip_AES_Operate((uint8_t *)TX_ciphertext, (uint8_t *)RX_plaintext, 1);

Chip_AES_SetMode(CHIP_AES_API_CMD_DECODE_ECB);
Chip_AES_Operate((uint8_t *)TX_plaintext, (uint8_t *)TX_ciphertext, 1);

还有 Python 部分(版本 3.8.2):

from Crypto.Cipher import AES
import numpy as np

...

t_plaintext = np.random.randint(0, 255, size = 16, dtype = np.uint8)
t_key = np.random.randint(0, 255, size = 16, dtype = np.uint8)

...

o_cryptoEngine = AES.new(bytes(t_key), AES.MODE_ECB)

t_AES_by_Python = np.frombuffer(o_cryptoEngine.encrypt(bytes(t_plaintext)),dtype=np.uint8)
t_decryption_by_Python = np.frombuffer(o_cryptoEngine.decrypt(bytes (t_AES_by_Python)),dtype=np.uint8)

由于密钥和明文是随机生成的,因此输出每次都在变化,但在 MCU 和 Python 之间永远不会完全相同。不过,解密又回到了相同的原始明文。

提前谢谢你。

【问题讨论】:

  • 你也可以发布等效的python代码吗?请告诉你正在使用的python版本。两者的输出也会有所帮助。还请提供密钥,以便重现。
  • 你的数据类型已经是uint8_t *,不需要在你的c代码中转换任何东西。
  • Python 代码和版本已在 :) 中编辑过

标签: python c encryption aes lpc


【解决方案1】:

我修好了:-)

如果有一天有人遇到类似的问题:这与 AES 引擎处理数据的方式有关。该数组是从 MCU(具有硬件 AES 引擎)和 Python 脚本(具有软件实现)之间的相对侧处理的。

处理数据的方式无法更改,因此在 MCU 处理之前翻转密钥和明文缓冲区并在加密后再次翻转它们就可以了。

【讨论】:

    【解决方案2】:

    您总是可以使用已知的测试向量来查看哪个算法是错误的。

    https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/aes/KAT_AES.zip

    例如有针对 AES CBC 128 的已知测试

    KEY = 10a58869d74be5a374cf867cfb473859
    PLAINTEXT = 00000000000000000000000000000000
    CIPHERTEXT = 6d251e6944b051e04eaa6fb4dbf78465
    

    等效的python实现

    from Crypto.Cipher import AES
    
    key = bytearray.fromhex('10a58869d74be5a374cf867cfb473859')
    cipher = AES.new(bytes(key), AES.MODE_ECB)
    plaintext = bytearray.fromhex('00000000000000000000000000000000')
    print(cipher.encrypt(bytes(plaintext)).hex())
    # will print '6d251e6944b051e04eaa6fb4dbf78465' so it is correct
    

    你可以对C做同样的事情,看看它是错的还是你用错了。

    uint8_t key[16] = {0x10, 0xa5, 0x88, 0x69, 0xd7, 0x4b, 0xe5, 0xa3, 0x74, 0xcf, 0x86, 0x7c, 0xfb, 0x47, 0x38, 0x59};
    uint8_t plaintext[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    uint8_t ciphertext[16] = {};
    uint8_t expected_ciphertext[16] = {0x6d, 0x25, 0x1e, 0x69, 0x44, 0xb0, 0x51, 0xe0, 0x4e, 0xaa, 0x6f, 0xb4, 0xdb, 0xf7, 0x84, 0x65};
    
    Chip_AES_Init();
    Chip_AES_LoadKeySW(key);
    Chip_AES_SetMode(CHIP_AES_API_CMD_ENCODE_ECB);
    Chip_AES_Operate(ciphertext, plaintext, 1);
    
    if(memcmp(ciphertext, expected_ciphertext, 16) != 0) {
       // LPC implementation is wrong and is not compliant
    }
    
    

    您也可以使用mbedtls 代替 LPC 提供的蹩脚函数。

    【讨论】:

      猜你喜欢
      • 2014-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-01
      • 2020-11-09
      • 1970-01-01
      • 2020-04-29
      • 2012-03-12
      相关资源
      最近更新 更多