AES 128 CBC的蒙特卡罗测试

时间:2017-04-24 10:45:09

标签: c unit-testing openssl aes

我正按照http://csrc.nist.gov/groups/STM/cavp/documents/aes/AESAVS.pdf

中的描述在AES 128 CBC上执行MCT

第一次迭代的预期矢量结果是

KEY = 9dc2c84a37850c11699818605f47958c

IV = 256953b2feab2a04ae0180d8335bbed6

PLAINTEXT = 2e586692e647f5028ec6fa47a55a2aab

CIPHERTEXT = 1b1ebd1fc45ec43037fd4844241a437f

下面的函数用于生成第一次迭代输出,

void
do_mct()
{
    EVP_CIPHER_CTX *ctx = NULL;
    unsigned char key[16] =
    { 0x9d, 0xc2, 0xc8, 0x4a, 0x37, 0x85, 0x0c, 0x11, 0x69, 0x98, 0x18, 0x60, 0x5f, 0x47, 0x95, 0x8c };
    unsigned char iv[16] =
    { 0x25, 0x69, 0x53, 0xb2, 0xfe, 0xab, 0x2a, 0x04, 0xae, 0x01, 0x80, 0xd8, 0x33, 0x5b, 0xbe, 0xd6 };
    unsigned char pt[16] =
    { 0x2e, 0x58, 0x66, 0x92, 0xe6, 0x47, 0xf5, 0x02, 0x8e, 0xc6, 0xfa, 0x47, 0xa5, 0x5a, 0x2a, 0xab };
    unsigned char ct_current[16] = { };
    unsigned char ct_previous[16] = { };
    int ptlen = 16, ctlen = 0;

    ctx = EVP_CIPHER_CTX_new();

    if ( ctx )
    {
        for ( int i = 0; i < 999 ; i++ )
        {
            if ( 0 == i )
            {
                if ( 1 == EVP_EncryptInit(ctx, EVP_aes_128_cbc(), &key[0], &iv[0] ) )
                {
                    EVP_CIPHER_CTX_set_padding(ctx, 0);

                    if ( 1 ==  EVP_EncryptUpdate(ctx, &ct_current[0] , &ctlen, &pt[0], ptlen) )
                    {
                        printf("\nctlen= %d\n", ctlen);
                        memcpy(&pt[0],&iv[0],16);
                    }
                    else
                    {
                        printf( " error");
                    }
                }
                else
                {
                    printf( " error");
                }
            }
            else
            {
                memcpy(&ct_previous[0],&ct_current[0],ctlen);

                if ( 1 ==  EVP_EncryptUpdate(ctx, &ct_current[0] , &ctlen, &pt[0], ptlen) )
                {
                    memcpy(&pt[0],&ct_previous[0],ctlen);
                }
                else
                {
                    printf( " error");
                }
            }
        }

        printf("\nCT :- ");
        for(int i=0;i<ctlen;i++)
        {
            printf("%02x ", ct_current[i]);
        }

        EVP_CIPHER_CTX_free(ctx);
    }
}

打印结果为, CT: - c1 b7 7e d5 25 21 52 5f 0a 4b a3 41 bd af 51 d9

与预期结果不符。 我怀疑在上面的函数中有些东西是不对的,但AESAVS pdf中给出的伪代码也有点令人困惑。 请告诉我们出错的地方..

2 个答案:

答案 0 :(得分:0)

请注意,NIST文档中有一个三个和两个参数版本的AES。您正确使用CBC模式作为三参数版本,但您需要将ECB模式用于两个参数版本。

If ( j=0 ) 
    CT[j] = AES(Key[i], IV[i], PT[j])
    PT[j+1] = IV[i]
Else
    CT[j] = AES(Key[i], PT[j])
    PT[j+1] = CT[j-1]

没有填充的单个完整块的ECB模式本质上是ELSE - 块所需的普通AES分组密码。您可能遇到问题,因为IV是ctx中的有状态值,并且在您无法控制它的情况下会自行前进。您必须将CBC用于第一个块,将ECB用于所有其他块。

答案 1 :(得分:0)

哎呀..我的坏,它需要1000次迭代才能生成一个输出..我只做了999 ..将循环更改为for(int i = 0; i&lt; 1000; i ++)并且它工作了