@gertvdijk によると、AES_CTR はパディングを必要としないストリーム暗号です。そのため、関連するコードを削除しました。
ここに私が知っていることがあります。
AES.new(...)
暗号化と復号化で同じキー ( の最初のパラメーター) を使用し、キーを非公開にする必要があります。
暗号化/復号化の方法はステートフルです。つまり、常に真であるとcrypto.en(de)crypt("abcd")==crypto.en(de)crypt("abcd")
は限りません。CTR では、カウンター コールバックは常に同じものを返すため、暗号化するとステートレスになります (それが理由であるとは 100% 確信していません) が、復号化ではややステートフルであることがわかります。結論として、それらを行うには常に新しいオブジェクトを使用する必要があります。
counter callback
暗号化と復号化の両方の関数は同じように動作する必要があります。あなたの場合、両方が同じシークレットを返すようにすることです。secret
しかし、私はそれが「秘密」だとは思いません。生成された乱数を使用して、暗号化せずに通信ピア間で渡すことができるため、予測できない"secret"
限り、反対側がそれを直接使用secret
できます。
だから私はこのように私の暗号を書くでしょう、それが助けになることを願っています.
import os
import hashlib
import Crypto.Cipher.AES as AES
class Cipher:
@staticmethod
def md5sum( raw ):
m = hashlib.md5()
m.update(raw)
return m.hexdigest()
BS = AES.block_size
@staticmethod
def pad( s ):
"""note that the padding is no necessary"""
"""return s + (Cipher.BS - len(s) % Cipher.BS) * chr(Cipher.BS - len(s) % Cipher.BS)"""
return s
@staticmethod
def unpad( s ):
"""return s[0:-ord(s[-1])]"""
return s
def __init__(self, key):
self.key = Cipher.md5sum(key)
#the state of the counter callback
self.cnter_cb_called = 0
self.secret = None
def _reset_counter_callback_state( self, secret ):
self.cnter_cb_called = 0
self.secret = secret
def _counter_callback( self ):
"""
this function should be stateful
"""
self.cnter_cb_called += 1
return self.secret[self.cnter_cb_called % Cipher.BS] * Cipher.BS
def encrypt(self, raw):
secret = os.urandom( Cipher.BS ) #random choose a "secret" which is not secret
self._reset_counter_callback_state( secret )
cipher = AES.new( self.key, AES.MODE_CTR, counter = self._counter_callback )
raw_padded = Cipher.pad( raw )
enc_padded = cipher.encrypt( raw_padded )
return secret+enc_padded #yes, it is not secret
def decrypt(self, enc):
secret = enc[:Cipher.BS]
self._reset_counter_callback_state( secret )
cipher = AES.new( self.key, AES.MODE_CTR, counter = self._counter_callback )
enc_padded = enc[Cipher.BS:] #we didn't encrypt the secret, so don't decrypt it
raw_padded = cipher.decrypt( enc_padded )
return Cipher.unpad( raw_padded )
いくつかのテスト:
>>> from Cipher import Cipher
>>> x = Cipher("this is key")
>>> "a"==x.decrypt(x.encrypt("a"))
True
>>> "b"==x.decrypt(x.encrypt("b"))
True
>>> "c"==x.decrypt(x.encrypt("c"))
True
>>> x.encrypt("a")==x.encrypt("a")
False #though the input is same, the outputs are different
参照: http://packages.python.org/pycrypto/Crypto.Cipher.blockalgo-module.html#MODE_CTR