nsa的simon和speck分组密码的实现
simonspeckciphers的Python项目详细描述
python 3.x/2.x中的simon&speck块密码
Simon and Speck块密码的纯python实现。这些是由{a2}设计的小型密码,用于受限硬件和软件环境,如微控制器或小型asic/fpgas。
警告以下实现仅用于参考/研究/娱乐,不应被视为100%没有错误或副频道攻击。不鼓励在生产环境中使用。
安装
simon/speck套件可以通过pip
从PyPi安装:
pip install simonspeckciphers
如果pip
不可用,则下载或克隆此项目并从以下目录运行:
python setup.py install
其中python
是最受欢迎的python interperator
您可以使用:
python setup.py test# or py.test -xvvv
基本用法
西蒙和斯派克工作原理相同。一旦代码复制到您的项目中,就可以导入密码:
>>> from speck import SpeckCipher >>> from simon import SimonCipher
一旦导入,就可以创建存储密码状态的密码对象。初始化密码对象所需的唯一参数是加密密钥。
>>> my_speck= SpeckCipher(0x123456789ABCDEF00FEDCBA987654321) >>> my_simon= SimonCipher(0xABBAABBAABBAABBAABBAABBAABBAABBA)
一旦初始化,密码就可以使用encrypt()
和decrypt()
方法加密或解密提供的明文或密文值。只要对象存在,对象将继续处理加密/解密请求。
>>> my_plaintext= 0xCCCCAAAA55553333 >>> speck_ciphertext= my_speck.encrypt(my_plaintext) >>> speck_plaintext= my_speck.decrypt(speck_ciphertext) >>> simon_ciphertext= my_simon.encrypt(0xFFFF0000EEEE1111) >>> simon_plaintext= my_simon.decrypt(simon_ciphertext)
可以通过key
属性读取或更新加密密钥
>>> hex(my_speck.key)'0x123456789abcdef00fedcba987654321'
块和键大小
规范中描述的所有有效键和块大小都支持作为可选参数。以位为单位的有效块和密钥大小为:
block size | key sizes |
---|---|
32 | 64 |
48 | 72,96 |
64 | 96,128 |
96 | 96,144 |
128 | 128,192,256 |
如果在初始化时未提供,则两个密码将默认为128位加密密钥和块大小。如果未使用默认值,建议明确指定密钥大小和块。
>>> tiny_cipher= SpeckCipher(0x123456789ABCDEF0, key_size=64, block_size=32) >>> big_cipher= SimonCipher(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF0000, key_size=256, block_size=128) >>> trunc_cipher= SimonCipher(0x111122223333444455556666777788889999, key_size=96, block_size=48) >>> hex(trunc_cipher.key)'0x444455556666777788889999'
所有输入值(键、明文、ivs等)将被截断或用零填充到块和键大小指定的位大小。当前的键和块大小可以通过key_size
和block_size
属性来访问
块模式
为了方便起见,两个密码都支持分组密码操作的most common modes。
- 电子码本
ECB
(speck/simon的默认模式) - 计数器
CTR
- 密码块链
CBC
- 传播密码块链
PCBC
- 密码反馈
CFB
- 输出反馈
OFB
这些可以在初始化时使用mode
可选参数启用,也可以在创建后通过mode
属性启用。
除了ecb,这些模式还需要额外的初始化向量(iv)和可能的计数器。可以在创建密码时使用init
和counter
可选参数设置这些值。
密码在加密和解密操作之间自动更新或增加内部的iv和计数器值。操作之间不需要手动更新它们。
>>> ofb_cipher= SpeckCipher(1234, mode='OFB', init=0x999999) >>> ctr_cipher= SimonCipher(0x525354, mode='CTR', init=0xCABCABCAB, counter=1) >>> ctr_cipher.counter 1 >>> ofb_cipher.update_iv()10066329
在密码对象生命周期中,也可以使用update_iv()
方法随时更改或读取iv。如果提供了新的iv,此方法将返回当前的iv,否则,它将返回刚刚更新的iv。可通过counter
属性读取和更改密码内部计数器值。
数据类型
目前,speck和simon密码都希望输入int密钥、ivs、计数器、明文和密文。提供的任何值如果与键、明文等的位大小不匹配,则将被截断或用0填充msb,直至达到正确的大小。如果应用程序需要字符串或bytearray,则可以轻松地将输入和输出值转换为int或从int转换为int。
>>> key_bytes= bytes([0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00])# For Python 3.x Only >>> key_int= int.from_bytes(key_bytes, byteorder='big', signed='False')# Python 2.x/3.x >>> import binascii >>> key_int= int(binascii.hexlify(key_bytes),16) >>> hex(key_int)'0x112233445566778899aabbccddeeff00' >>> msg='ATTACK AT DAWN!!' >>> msg_int= sum([ord(c) << (8 * x)for x, c in enumerate(reversed(msg))]) >>> hex(msg_int)'0x41545441434b204154204441574e2121' >>> new_cipher= SimonCipher(key_int, key_size=128, block_size=128) >>> my_secret= new_cipher(msg_int) >>> my_secret_bytes= bytearray.fromhex('{:032x}'.format(my_secret)) >>> my_secret_bytes bytearray(b'HD\xbb\xe4\xa1\xed\x95\xd8>\x1bx<HOL[')
测试和示例
在tests.py
中提供了一个健壮的pytest套件。在这里,所有的官方测试向量和随机值都被执行呃。测试异常以及分组密码模式。有关如何使用每个模式的干净示例,请参阅这些测试。