我正在使用numpy在以下代码中创建字符串或位数组,并使用微小的转换方法。
我想知道的是,给定明文,可以给出block_size = 128, 可以使用以下代码中的ECB使用AES标准解密全文吗?
from operator import add
from itertools import imap, izip
import numpy as np
from Crypto.Cipher import AES
ASCII_BITS = 8
XOR = lambda k,m: k ^ m
#converts a string to list of binary repr of char
mbin = lambda word: imap(np.binary_repr,imap(ord, word))
#concatenates list of N ASCII_BIT binary repr of char to one string
string_to_bits = lambda word: reduce(add,(i.zfill(ASCII_BITS) for i in mbin(word)))
#Converts byte string to int to ascii character
bits_to_string = lambda bitstr: ''.join([chr(int(bitstr[i:i+ASCII_BITS], 2)) for i in xrange(0,len(bitstr), ASCII_BITS)])
#Convert byte string to 1D matrix of bits
strbits_to_bitmat = lambda X: np.matrix(list(X), dtype=int)
#Convert 1D matrix of bits to byte string
bitmat_to_strbits = lambda X: ''.join((np.matrix(X, dtype=str)).tolist()[0])
def arr_ascii_bin_strchops(string, block_size):
'''Array of ASCII Binary String Chops of size block_size'''
return (string[i:i+block_size] for i in xrange(0,len(string),block_size))
这些是我正在使用的标准转换功能。
arr_ascii_bin_strchops :将一个字符串切换成block_size长度位字符串列表
编码器和解码器
def aes_encoder(block, key):
#block = pad_bits_append(block, len(key))
maxibit = abs(len(block)-len(key))
block += ''.zfill(maxibit)
# the pycrypto library expects the key and block in 8 bit ascii
# encoded strings so we have to convert from the bit string
block = bits_to_string(block)
key = bits_to_string(key)
ecb = AES.new(key, AES.MODE_ECB)
return string_to_bits(ecb.encrypt(block))
def aes_decoder(block, key):
#block = pad_bits_append(block, len(key))
maxibit = abs(len(block)-len(key))
block += ''.zfill(maxibit)
# the pycrypto library expects the key and block in 8 bit ascii
# encoded strings so we have to convert from the bit string
block = bits_to_string(block)
key = bits_to_string(key)
#AES.new( self.key, AES.MODE_CBC, iv )
ecb = AES.new(key, AES.MODE_ECB)
return string_to_bits(ecb.decrypt(block))
CBC加密及其依赖方法
def crypto_cal(m,k,cminus,block_size,block_enc):
'''
for Cipher Block Chaining - Main Block_Enc(M^IV,Key)
'''
m += ''.zfill(block_size - len(m))
k += ''.zfill(block_size - len(k))
cminus += ''.zfill(block_size - len(cminus))
cminus = np.matrix(list(cminus), dtype=int)
m = np.matrix(list(m), dtype=int)
#convert 1D XORed matrix of int to byte string
xor = ''.join(np.matrix(XOR(cminus,m),dtype=str).tolist()[0])
cminus = block_enc(xor,k) #xor = iv ^ mbloc0
return cminus
def cipher_block_chaining(plaintext, key, init_vec, block_size, block_enc):
"""Return the cbc encoding of `plaintext`
Args:
plaintext: bits to be encoded
key: bits used as key for the block encoder
init_vec: bits used as the initalization vector for
the block encoder
block_size: size of the block used by `block_enc`
block_enc: function that encodes a block using `key`
"""
cipher = []
key = string_to_bits(key)
iv = string_to_bits(init_vec)
plaintext = string_to_bits(plaintext)
mbloc = arr_ascii_bin_strchops(plaintext,block_size)
kbloc = arr_ascii_bin_strchops(key,block_size)
iv = next(arr_ascii_bin_strchops(iv,block_size))
mbloc0 = next(mbloc)
kbloc0 = next(kbloc)
cminus = crypto_cal(mbloc0,kbloc0,iv,block_size,block_enc)
cipher.append(cminus)
for m,k in izip(mbloc, kbloc):
assert len(cminus) == block_size #len(''.zfill(block_size - len(cminus)))
cminus = crypto_cal(m,k,cminus,block_size,block_enc)
cipher.append(cminus)
return ''.join(cipher)
CBC解密及其依赖方法
def decrypto_cal(cipher_msg,key,cminus,block_size,block_enc):
key += ''.zfill(block_size - len(key))
cminus += ''.zfill(block_size - len(cminus))
return bitmat_to_strbits(XOR(strbits_to_bitmat(block_enc(cipher_msg,key)),\
strbits_to_bitmat(cminus)))
def cipher_block_decrypt(cipher, key, init_vec, block_size, block_enc):
'''
Return the cbc decoding of `cipher`
Args:
cipher: bit string to be decoded
key: bits used as symmetric key for the block decoder
init_vec: bits used as the initalization vector for
the block encoder/decoder
block_size: size of the block used by `block_enc`
block_enc: function that decodes a block using `key`
'''
cipher_blocks = []
key = string_to_bits(key)
iv = string_to_bits(init_vec)
cipher = string_to_bits(cipher)
#print "init vec {}".format(init_vec)
iv = next(arr_ascii_bin_strchops(iv,block_size))
kbloc = (arr_ascii_bin_strchops(key,block_size))
cipher_chops = (arr_ascii_bin_strchops(cipher, block_size))
lst = zip(cipher_chops, kbloc)
cipher_blocks.extend([decrypto_cal(cipher_msg,key,lst[num-1][0],block_size,block_enc)\
if num > 0 else decrypto_cal(cipher_msg,key,iv,block_size,block_enc) \
for num,(cipher_msg,key) in enumerate(lst)])
return ''.join(cipher_blocks)
def test():
block_size = 256
key = '4h8f.093mJo:*9#$'
iv = '89JIlkj3$%0lkjdg'
plaintext = "One if by land; two if by sea"
cipher = (cipher_block_chaining(plaintext, key, iv, block_size, aes_encoder))
cipher = bits_to_string(cipher)
print "cipher {}".format(cipher)
msg_bits = cipher_block_decrypt(cipher, key, iv, block_size, aes_decoder)
p = bits_to_string(msg_bits)
print p
return
它使用256块大小并且能够解密整个明文但是使用128,只有
一个是陆地;
被解密。
为什么我只剪切那个大小的位串?它不应该限制字符串长度。 是否有一些使用的方法限制了字符串数组的总数?