13

PyCryptoがプロジェクトでどのように機能するかを理解しようとしていますが、初期化ベクトル(IV)の重要性を完全には理解していません。文字列をデコードするときに間違ったIVを使用できることがわかりましたが、最初の16バイト(ブロックサイズ)を除いて、メッセージが返されるようです。単にそれを間違って使用しているのですか、それとも何かを理解していないのですか?

デモ用のサンプルコードは次のとおりです。

import Crypto
import Crypto.Random
from Crypto.Cipher import AES

def pad_data(data):
    if len(data) % 16 == 0:
        return data
    databytes = bytearray(data)
    padding_required = 15 - (len(databytes) % 16)
    databytes.extend(b'\x80')
    databytes.extend(b'\x00' * padding_required)
    return bytes(databytes)

def unpad_data(data):
    if not data:
        return data

    data = data.rstrip(b'\x00')
    if data[-1] == 128: # b'\x80'[0]:
        return data[:-1]
    else:
        return data


def generate_aes_key():
    rnd = Crypto.Random.OSRNG.posix.new().read(AES.block_size)
    return rnd

def encrypt(key, iv, data):
    aes = AES.new(key, AES.MODE_CBC, iv)
    data = pad_data(data)
    return aes.encrypt(data)

def decrypt(key, iv, data):
    aes = AES.new(key, AES.MODE_CBC, iv)
    data = aes.decrypt(data)
    return unpad_data(data)

def test_crypto ():
    key = generate_aes_key()
    iv = generate_aes_key() # get some random value for IV
    msg = b"This is some super secret message.  Please don't tell anyone about it or I'll have to shoot you."
    code = encrypt(key, iv, msg)

    iv = generate_aes_key() # change the IV to something random

    decoded = decrypt(key, iv, code)

    print(decoded)

if __name__ == '__main__':
    test_crypto()

Python3.3を使用しています。

出力は実行によって異なりますが、次のようになります。b"1^,Kp}Vl\x85\x8426M\xd2b\x1aer secret message. Please don't tell anyone about it or I'll have to shoot you."

4

2 に答える 2

21

表示される動作は、CBCモードに固有のものです。CBCを使用すると、復号化を次の方法で視覚化できます(ウィキペディアから)。

CBC復号化

IVが平文の最初の16バイトにのみ寄与することがわかります。受信機への転送中にIVが破損した場合でも、CBCは最初のブロックを除くすべてのブロックを正しく復号化します。CBCでは、IVの目的は、同じメッセージを同じキーで暗号化し、毎回まったく異なる暗号文を取得できるようにすることです(メッセージの長さが何かを与える可能性がある場合でも)。

他のモードはそれほど寛容ではありません。IVを間違えると、メッセージ全体が復号化時に文字化けします。たとえば、CTRモードを考えてみましょう。ここで、nonceIVとほぼ同じ意味を持ちます。

CTRモード

于 2013-02-06T07:52:10.973 に答える
3

PyCryptoの開発者は、NISTからAESCBCモードの仕様を引き出しました。

AES Mode_CBC- > NIST 800-38aの参照(暗号モード操作の推奨事項)

それから、8ページ:

5.3初期化ベクトル

CBC、CFB、およびOFBモードの暗号化プロセスへの入力には、平文に加えて、IVで示される初期化ベクトル(IV)と呼ばれるデータブロックが含まれます。IVは、メッセージの暗号化および対応するメッセージの復号化の最初のステップで使用されます。IVは秘密である必要はありません。ただし、CBCおよびCFBモードの場合、暗号化プロセスの特定の実行のIVは予測不可能である必要があり、OFBモードの場合、暗号化プロセスの実行ごとに一意のIVを使用する必要があります。IVの生成については、付録Cで説明します。


覚えておくべきことは、メッセージを作成するたびにランダムなIVを使用する必要があることです。これにより、メッセージに「ソルト」が追加されるため、メッセージが一意になります。'salt'が公開されていても、AES暗号化キーが不明な場合は暗号化を解除するのに役立ちません。ランダム化されたIVを使用しない場合、たとえば、各メッセージで同じ16バイトを使用する場合、メッセージを繰り返すと、ネットワーク全体で同じように見え、頻度攻撃やリプレイ攻撃を受ける可能性があります。

ランダムIVと静的の結果のテスト:

def test_crypto ():
    print("Same IVs same key:")
    key = generate_aes_key()
    iv = b"1234567890123456"
    msg = b"This is some super secret message.  Please don't tell anyone about it or I'll have to shoot you."
    code = encrypt(key, iv, msg)
    print(code.encode('hex'))
    decoded = decrypt(key, iv, code)
    print(decoded)

    code = encrypt(key, iv, msg)
    print(code.encode('hex'))
    decoded = decrypt(key, iv, code)
    print(decoded)

    print("Different IVs same key:")
    iv = generate_aes_key()
    code = encrypt(key, iv, msg)
    print(code.encode('hex'))
    decoded = decrypt(key, iv, code)
    print(decoded)

    iv = generate_aes_key()
    code = encrypt(key, iv, msg)
    print(code.encode('hex'))
    decoded = decrypt(key, iv, code)
    print(decoded)

お役に立てれば!

于 2013-02-06T04:34:03.667 に答える