2012-07-17 115 views
2

我已经写了一些Crypto.Cipher.AES.encrypt/decrypt的抽象,我想为它编写单元测试。编写decrypt的单元测试很简单,但是有没有合理的方法来测试加密本身是否发生?例如,是否有一些方法可以查看一个字节串,并知道是的,那是一大块AES加密数据?如果没有(可能会提供太多的信息),我有什么选择来测试我的encrypt函数是否具有合理的输出?如何编写加密单元测试?

def encrypt(plaintext): 
    """Return 'plaintext' AES encrypted.""" 
    initialization_vector = Random.new().read(AES.block_size) 
    cipher = AES.new(settings.secret, AES.MODE_CFB, initialization_vector) 
    return initialization_vector + cipher.encrypt(bytes(plaintext.encode('utf-8'))) 

def decrypt(crypt): 
    """Return 'crypt' AES decrypted.""" 
    initialization_vector, crypt = crypt[:AES.block_size], crypt[AES.block_size:] 
    cipher = AES.new(settings.secret, AES.MODE_CFB, initialization_vector) 
    return cipher.decrypt(crypt) 

# … this is a method of a unittest.TestCase subclass: 
def test_decrypt(self): 
    """Test that a message can be decrypted.""" 
    crypt = utils.encrypt("abcdefg") 
    decrypt = utils.decrypt(crypt) 
    self.assertEqual("abcdefg", decrypt) 

def test_encrypt(self): 
    """Test that a message can be encrypted. … if you can""" 
    crypt = utils.encrypt("abcdefg") 
    self.assertSomethingmumblemumble(crypt) 
+5

你可以通过已知好的外部解密器运行'encrypt()'的结果并验证出来对方符合你的意见?这似乎是唯一的方法来做到这一点。编辑:你的解密测试不是很好。如果可能的话,您不应该使用模块本身来创建您正在测试的数据。仅仅因为操作是对称的,并不意味着这些步骤是正确的。 – 2012-07-17 22:35:40

+0

您对我的'test_decrypt'的批评正是我为什么要问这个问题的原因......说,如果您将您的评论发布为答案,我可能会接受它。 – kojiro 2012-07-18 03:13:34

回答

6

伪随机置换的全部概念 - 和分组密码就是这样 - 它看起来是随机的。您可以运行测试来检查随机性,但是我非常确定这对于JUnit测试来说有点太过分了。所以我会选择sr2222的建议,并简单地通过解密来测试。

您可以通过使用原始块解密并测试其中的内容来测试模式和填充。您也可以测试加密后的情况是否相同(块加密本身与纯文本和密文有1:1的关系),或者加密是不同的。您也可以测试加密数据的大小是否正确。

然而,加密自我不能在没有解密的情况下进行测试,这是背后的想法:你不能得到有关明文或密钥的信息 - 任何看起来不随机的东西都会违背这些概念。测试加密的最好方法是对official test vectors进行测试,如果这些测试不够或者不可用,请根据已知良好实现(输出)(例如经过验证的实现,如openssl)或参考实现。

+0

只接受这个答案。它具有特定于我无法提供的加密的信息。奖励+1,如果我可以为测试向量链接。 – 2012-07-18 13:14:43

+0

测试向量不再可用于该URL。 [NIST有一些,但](http://csrc.nist.gov/groups/STM/cavp/)。 – Raphael 2017-01-24 16:58:15

0

不测试结果。嘲笑你的密码和随机提供商,并测试它们是否被调用了正确的参数,并且如果中间结果在它们之间正确传递