【问题标题】:Encrypted string is not the same as test vector加密字符串与测试向量不同
【发布时间】:2013-01-07 00:25:12
【问题描述】:

所以我正在尝试使用来自 OpenSSL 的 EVP-API 加密一些数据。但我没有收到与测试向量相同的结果。

这是主要功能

#include <stdio.h>
#include <windows.h>
#include <openssl\aes.h>
#include <openssl\evp.h>

int main()
{

    unsigned char *to = (unsigned char*)malloc(2056);
    ZeroMemory(to,2056);
    int *tosize;
    unsigned char* key = (unsigned char*)"0000000000000000000000000000000000000000000000000000000000000000";
    unsigned char* iv = (unsigned char*)"00000000000000000000000000000000";
    unsigned char* plain = (unsigned char*)"00000000000000000000000000000000";
    to = AESEncrypt(key,iv,plain,strlen((const char*)plain));
    if (to != 0)
    {
        for (int i = 0; i < strlen((const char*)to);i++)
        {
            printf("%x02", (int*)UCHAR(to[i]));
        }

    }
}

这就是我要调用的函数。没有收到错误。每个电话都是真的(没有错误)。

 unsigned char* AESEncrypt(unsigned char* key, unsigned char*iv, unsigned char*plain, size_t plainsize)
{

EVP_CIPHER_CTX *x = (EVP_CIPHER_CTX*) malloc(sizeof(EVP_CIPHER_CTX));
EVP_CIPHER_CTX_init(x);
if (EVP_EncryptInit(x,EVP_aes_256_cbc(),key,iv))
{
    unsigned char* to = (unsigned char*) malloc(plainsize + EVP_CIPHER_CTX_block_size(x));
int tosize = 0;

if(EVP_EncryptUpdate(x,to,&tosize,plain,plainsize))
{
    if (EVP_EncryptFinal(x,to,&tosize))
    {
        return to;
    }   
  }
}

return 0;
}

这是测试向量:

KEY = 0000000000000000000000000000000000000000000000000000000000000000
IV = 00000000000000000000000000000000
PLAINTEXT = 80000000000000000000000000000000
CIPHERTEXT = ddc6bf790c15760d8d9aeb6f9a75fd4e

这是我收到的: CIPHERTEXT = 5a0215028e .... 它继续。如您所见,这是不正确的。

我做错了什么?

【问题讨论】:

  • 你不能改变字符串文字。将您的指针变为指向常量的指针。
  • OT:to 是如何传递到您的加密函数中的?还是只是为了在内存泄漏的范围内进行测试?
  • to 是输出的位置。
  • 这是您第一次使用 CAVS 安全带的牛仔竞技表演吗?只是好奇,因为您的数据不正确。除非有人打败我,否则我会在答案中详细说明原因。
  • 是的,这是第一次。

标签: c openssl aes


【解决方案1】:

CAVS 测试向量遵循相当直接的模式。从测试到测试,它们在一定程度上有所不同,但有一件事是非常一致的:

十六进制字符串是字节表示;不是字符数据

因此你的“测试”是完全错误的。您正在使用一个键、iv 和用字符“0”填充的纯文本,而不是 byte0。所以显然难怪你会得到不同的结果。

对于特定测试你的数组应该是:

unsigned char key[64] = {0};
unsigned char iv[16] = {0};
unsigned char plain[16] = {0};

此外,发送到加密函数的大小应该是纯文本的字节数。最后,理想情况下,您的加密函数应该将目标缓冲区和可修改的大小作为输出参数。

int AESEncrypt256(
    unsigned char* key,      // key must be 64 bytes wide.
    unsigned char *iv,       // IV must be 16 bytes wide.
    unsigned char *src,      // source buffer to encryt
    unsigned int src_len,    // length of source buffer in bytes
    unsigned char *dst,      // target buffer to write to
    unsigned int *dst_len);  // in: size of dst, out: bytes written to dst

并对函数进行编码以匹配这些参数。你会很高兴你做到了。

CAVS 测试向量不是“文本”。它们是字节,应该这样对待。你现在需要处理好这个问题,因为如果你不这样做,蒙特卡洛测试可能会花费你一些头发。

帮自己一个巨大的忙,现在编写一些代码,将一串十六进制数字转换为unsigned char 字节数组。您将需要相同的内容来翻译结果字符串。并让这些例程solid,因为您将在编写这些测试时大量使用它们。


剧透警告

测试字符串的奇数个字符first。如果它是奇数,则翻译缓冲区中的第一个字节应基于0c,其中c 是输入字符串中的第一个char。从那时起(或者如果字符数是偶数,那么从一开始)在将字节字符串的其余部分转换为实际字节时一次抓取两个。这意味着这个

123456

产生一个字节数组

{ 0x12, 0x34, 0x56 }

此时:

89AB1

应该是:

{0x08, 0x9A, 0xB1 }

【讨论】:

  • @owlstead 我感觉到他的痛苦。编写所有这些细致的测试只是丑陋的繁重工作,我特别讨厌 TDES MC 测试。啊。想想看,我把整个东西抽象成一个plug-in-your-crypto-lib模板库。也许我应该推销那个东西...... LOL =P
  • 是的,我创建了一个在 UTF-8、UTF-16、UltraEdit 十六进制代码、Java 十六进制字节、Java 调试器字节、C++ 字节、字符数组等之间转换的工具。 .否则,在复制测试向量时会出现太多错误:)
  • @owlstead 你真的合并了你的向量?我们只是直接从磁盘上的源代码树中读取。您将它指向一个包含所有向量的根文件夹,运行它,它会生成所有 resp 文件夹和相同的每个测试的文件。是的,cavs_string(基于std::string)和cavs_bytes(基于std::vector&lt;uint8_t&gt;)以及一系列不错的函数和运算符,可以从一个切换到另一个。 该死的派上用场了。
  • 其他测试向量主要是ECC,因此复制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-02
  • 2014-01-30
  • 1970-01-01
  • 2011-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多