【问题标题】:Python convert integer to 16-byte bytesPython 将整数转换为 16 字节字节
【发布时间】:2016-05-19 21:19:04
【问题描述】:

我正在尝试在我的代码中使用 AES-CTR-128。我使用 Python 2.7 并利用 cryptography 模块进行加密。

我需要设置特定的Counter值,例如counter_iv = 112。当我尝试时

import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
backend = default_backend()
key = os.urandom(32)
counter_iv = 112
cipher = Cipher(algorithms.AES(key), modes.CTR(counter_iv), backend=backend)
encryptor = cipher.encryptor()
ciphertext = encryptor.update(b"a secret message") + encryptor.finalize()

这给了我一条错误消息:

Traceback (most recent call last):
File "aestest.py", line 14, in <module>
  cipher = Cipher(algorithms.AES(key), modes.CTR(counter_iv), backend=backend)
File "/usr/local/lib/python2.7/dist-packages/cryptography/hazmat/primitives/ciphers/modes.py", line 139, in __init__
  raise TypeError("nonce must be bytes")
TypeError: nonce must be bytes

我认为它告诉我 counter_iv 应该是一个 16 字节的字符串。

我的问题是如何将整数或长整数转换为 16 字节字符串?

此外,有没有办法将整数转换为任意长度的字符串?感谢您的帮助。

【问题讨论】:

  • 什么是encryptor
  • @Padraic Cunningham 忘记添加了。现在它就在那里。
  • 警告:你的计数器不应该是静态的,当然不能用于 CTR 模式。请理解 nonce 和计数器值之间的区别,否则您的方案可能非常不安全。

标签: python cryptography type-conversion data-conversion


【解决方案1】:

首先,您是否有充分的理由使用低级别的有害材料而不是高级 API?此级别只能通过高级 API 用于特殊用途。

接下来,您写modes.CTR(counter_iv) 会误导任何进一步的读者,因为根据其documentationcounter 模式不使用初始化向量,而是使用 nonce .你得到的错误是正常的,因为文档声明 nonce 应该是一个与密码块大小相同的字节字符串,所以对于 AES,它必须是 128 位或 16 字节。

顺便说一句,文档还指出永远不应该重复使用随机数

... 永远不要用给定的键重用 nonce 是至关重要的。任何重复使用具有相同密钥的随机数都会危及使用该密钥加密的每条消息的安全性。

Nayuki 的回答解释了如何从您的 int 构建一个 16 字节的字符串,但如果您使用低级别的危险材料

,请务必正确使用密码术

【讨论】:

  • 您的回答让我们深入了解了如何正确使用该库。谢谢你:)
【解决方案2】:

在 Python 2 中,您可以像这样将整数转换为 little endian 的字节字符串:

counter_iv = 112  # This can be a pretty big number
iv_bytes = "".join(chr((counter_iv >> (i * 8)) & 0xFF) for i in range(16))

扩展代码说明:

counter_iv = 112  # Can be from 0 to 3.40e38
temp = []  # Will be an array of bytes
for i in range(16):
    # Get the i'th byte counting from the least significant end
    b = (counter_iv >> (i * 8)) & 0xFF
    temp.append(b)
# For example, temp == [0x70, 0x00, ... 0x00]

# Will be an array of 1-character strings
temp2 = [chr(b) for b in temp]
# For example, temp2 == ['\x70', '\x00', ..., '\x00']

# Concatenate all the above together
iv_bytes = "".join(temp2)
# For example, iv_bytes == '\0x70\0x00...\0x00'

【讨论】:

  • 很好用。你能给我简要解释一下吗?谢谢。
  • 在python3中,可以直接counter_iv.to_bytes(16,"little")
  • @PadraicCunningham 太棒了!今天学到了一些新东西
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-05
  • 2013-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多