2012-08-31 39 views
1

我一直在玩python的加密庫,並且我構建了一個簡單的線程服務器來加密和解密。我遇到的問題是3個解密中有大約1個錯誤地返回。下面的代碼:與pycrypto混淆間歇性故障

class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler): 

    def handle(self): 
     global KEY 
     request_text = '' 
     while request_text.rfind("\n") == -1: 
      sock_data=''; 
      recv_size=8192 
      sock_data=self.request.recv(recv_size) 
      if sock_data == '': 
       print "hangup" 
       break 
      request_text = request_text + sock_data 

     args = json.loads(request_text) 
     print request_text 
     print "\n" 
     if args['command'] == 'encrypt': 
      iv = Random.new().read(AES.block_size) 
      cipher = AES.new(KEY, AES.MODE_CFB, iv) 
      crypted_message = iv + b'|' + cipher.encrypt(unquote_plus(args['message'])) 
      response = {'encrypted_message': binascii.hexlify(crypted_message)} 

     if args['command'] == 'decrypt': 
      unhexed = binascii.unhexlify(args['message']) 
      components = unhexed.split('|') 
      iv = components[0] 
      cipher = AES.new(KEY, AES.MODE_CFB, iv) 
      decrypted_message = cipher.decrypt(components[1]) 
      response = {'decrypted_message': decrypted_message} 

     self.request.sendall(json.dumps(response) + "\n") 

通常情況下,我從蟒蛇得到這個錯誤:

Traceback (most recent call last): 
    File "/usr/local/lib/python2.7/SocketServer.py", line 582, in process_request_thread 
    self.finish_request(request, client_address) 
    File "/usr/local/lib/python2.7/SocketServer.py", line 323, in finish_request 
    self.RequestHandlerClass(request, client_address, self) 
    File "/usr/local/lib/python2.7/SocketServer.py", line 639, in __init__ 
    self.handle() 
    File "cryptoserver.py", line 40, in handle 
    cipher = AES.new(KEY, AES.MODE_CFB, iv) 
    File "build/bdist.macosx-10.4-x86_64/egg/Crypto/Cipher/AES.py", line 95, in new 
    return AESCipher(key, *args, **kwargs) 
    File "build/bdist.macosx-10.4-x86_64/egg/Crypto/Cipher/AES.py", line 59, in __init__ 
    blockalgo.BlockAlgo.__init__(self, _AES, key, *args, **kwargs) 
    File "build/bdist.macosx-10.4-x86_64/egg/Crypto/Cipher/blockalgo.py", line 141, in __init__ 
    self._cipher = factory.new(key, *args, **kwargs) 
ValueError: IV must be 16 bytes long 
---------------------------------------- 

但正如經常,我沒有錯誤,但解密無法正常工作。我使用這個PHP來測試它:

<?php 
include_once("config.php"); 

function encrypt($text) { 
    $package = array("command" => "encrypt", 
        "message" => base64_encode($text)); 
    $package_json = json_encode($package); 
    $serverSays = transmit($package_json); 
    $serverSaysArray = json_decode($serverSays); 
    return $serverSaysArray->encrypted_message; 
} 

function decrypt($text) { 
    $package = array("command" => "decrypt", 
        "message" => $text); 

    $package_json = json_encode($package); 
    $serverSays = transmit($package_json); 
    $serverSaysArray = json_decode($serverSays); 
    return base64_decode($serverSaysArray->decrypted_message); 
} 

function transmit($package) { 
    global $CRYPTO_PORT; 
    global $CRYPTO_HOST; 

    $serverLink = fsockopen($CRYPTO_HOST, $CRYPTO_PORT); 
    if ($serverLink === FALSE) { 
     error_log("Could not connect to encryption server"); 
     return FALSE; 
    } 
    fwrite($serverLink, $package . "\n"); 

    $response = ''; 
    while (!feof($serverLink)) { 
     $response .= fgets($serverLink, 128); 
    } 
    fclose($serverLink); 
    return $response; 
} 

while (TRUE) { 
    $enc = encrypt('totsadaddywoopxxx'); 
    print "$enc\n"; 
    $dec = decrypt($enc); 
    print "$dec\n"; 
    $enc = encrypt('totsadaddywoopxxx'); 
    print "$enc\n"; 
    $dec = decrypt($enc); 
    print "$dec\n"; 
    $enc = encrypt('totsadaddywoopxxx'); 
    print "$enc\n"; 
    $dec = decrypt($enc); 
    print "$dec\n"; 
    #print decrypt('1c6dee677126551fa4b3f0732986dc3b7c985c64c07075e3651213d7a69435bcd87083e729e8de860c'); 
    #print "\n"; 
    #print decrypt('550cbec7498371dc01bcd6b88fc623b47cb2efd1881da6e07ee992229308305992bbc7ccc374f00c91d56d10a68d6110e2'); 
    print "===========================\n"; 

    sleep(1); 
} 

回答

1

在你解密日常使用:

unhexed.split('|') 

找到IV和密文之間的邊界。但是,IV由發件人隨機生成。有時,其16個字節中的一個將是124,即邊界字符'|'。

當發生這種情況(在的情況下,約6%),解密例程將初始化密碼或者與

  • 具有1首15個字節之間的長度的IV,這導致異常,或
  • 長度爲0的IV,從而導致不正確的解密,因爲在PyCrypto版本< 2.6全零的16字節的IV將被默認

使用在解密程序,你應該改爲:

components = [ unhexed[:AES.block_size], unhexed[AES.block_size+1:] ] 

或者你可以擺脫'|'分離器。

+0

謝謝。我認爲這是類似的東西,但我是這個東西的新手,這是從pycrypto的例子中剪切和粘貼。真棒! –

+0

@ ernst-schoen-rene歡迎!如果您對答案滿意,請您接受嗎? – SquareRootOfTwentyThree