纯文本到C数组测试向量



我正在按照FIPS_197的描述实现AES,并且我希望实现附录C(C1-C3(中描述的测试用例。我已经将测试用例复制到一个文本文件FIPS_197_tests.txt中,它看起来像这样:

#FIPS_192附录C中的测试用例
#Plaintext
#密钥
#输出
>#C.1 AES-128(Nk=4,Nr=10(
00112233445566778899aabbccddeeff
000102030405060708090a0b0c0d0e0f
69c4e0d86a7b0430d8cdb78070b4c55a
#C.2 AES-192(Nk=6,Nr=12(30405060708090a0b0c0d0e0f1011121314151617
dda97ca4864cdfe06eaf70a0ec0d7191
#C.3 AES-256(Nk=8,Nr=14(
00112233445566778899aabbccddeeff
000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
8ea2b7ca516745bfeafc49904b496089

我想创建一个头文件FIPS_197_tests.h,它定义了一些在C中很容易使用的测试向量。例如,第一个测试向量:

// C.1  AES-128 (Nk=4, Nr=10)
unsigned char Key_1[4][4] = {
{0x00, 0x11, 0x22, 0x33},
{0x44, 0x55, 0x66, 0x77},
{0x88, 0x99, 0xaa, 0xbb},
{0xcc, 0xdd, 0xee, 0xff} };
unsigned char PlainText_1[4][4]  = {
{0x00, 0x01, 0x02, 0x03},
{0x04, 0x05, 0x06, 0x07},
{0x08, 0x09, 0x0a, 0x0b},
{0x0c, 0x0d, 0x0e, 0x0f} };
unsigned char CipherText_1[4][4]  = {
{0x69, 0xc4, 0xe0, 0xd8},
{0x6a, 0x7b, 0x04, 0x30},
{0xd8, 0xcd, 0xb7, 0x80},
{0x70, 0xb4, 0xc5, 0x5a} };

只有3组测试向量,我可以手工完成,但我发现自己经常在C中制作十六进制测试向量,并且希望有一个比手工键入十六进制数组更聪明的解决方案。

需要解决的关键问题:

  1. 命名:矢量分为三组
    • 第一个是Key_n数组
    • 第二个是PlainText_n数组
    • 第三个是CipherText_n数组
  2. 调整大小:矢量中的值都是十六进制的,但并不总是填充大小为[4][4]的数组。数组的大小应该正确

到目前为止,我有这个脚本可以让事情变得更容易,但没有什么能完成整个工作:

cat FIPS_192_tests.txt | sed '/^#/ d; s/../0x&, /g' | xargs -n4 | rev | sed 's/,//' | rev | sed 's|^|{|; s|$|},|'

总结

我希望有一种方法可以从包含长文本字符串的文本文件中轻松地在C中创建十六进制测试向量。每个测试用例的测试向量以3个为一组,并且应该相应地命名(A_1、B_1、C_1、A_2、B_2…等(。测试向量的大小各不相同,因此一些数组应声明为type [4][4],而另一些数组应宣布为type [4][5]

理想的解决方案是允许文本文件的以下元素是可变的:

  1. 定义测试用例的连续行数
  2. 每行(Key_n、Ciphertext_n、Apple_n、Banana_n(的基本名称
  3. 每个基本名称的数据类型
  4. 每个数组的大小
  5. 正在读取的数据的格式(十六进制、十进制、二进制…(

它可能被称为:
./solution -i FIPS_197_tests.txt -n 3 -b "Key, PlainText, CipherText" -d "unsigned char, unsigned char, unsigned char" -f HEX -o FIPS_197_tests.h

这不像@TheRockSays提供的漂亮程序那样是一个完整的解决方案,但这与您的catsedxargsrevsed。。。方法,尽管用对awk的单个调用替换所有实用程序,例如

awk '
BEGIN {
a[1]="unsigned char Key_1[4][4] = "
a[2]="unsigned char PlainText_1[4][4]  = "
a[3]="unsigned char CipherText_1[4][4]  = "
}
/^#/ { if(n) exit; next }
{
for (i=1; i<length($1); i+=2)
if ((i % 8) == 1) {
if (i == 1)
printf "n%s{n%8s{0x%s", a[++n], " ", substr($1,i,2)
else
printf "},n%8s{0x%s", " ", substr($1,i,2)
}
else
printf ", 0x%s", substr($1,i,2)
print "}};"
}
' FIPS_197_tests.txt

(要进行测试,您可以简单地选择复制鼠标中键将上述内容粘贴到xterm中,当前工作目录包含FIPS_197_tests.txt(

当然,在愿望列表中,您必须手动提供数组名称,并且必须将printf格式字符串更改为十进制、十六进制等。但是,对于FIPS_197_tests.txt文件的初始解析的快速shell解决方案,它肯定比手动输入所有数组要好。

示例输出

unsigned char Key_1[4][4] = {
{0x00, 0x11, 0x22, 0x33},
{0x44, 0x55, 0x66, 0x77},
{0x88, 0x99, 0xaa, 0xbb},
{0xcc, 0xdd, 0xee, 0xff}};
unsigned char PlainText_1[4][4]  = {
{0x00, 0x01, 0x02, 0x03},
{0x04, 0x05, 0x06, 0x07},
{0x08, 0x09, 0x0a, 0x0b},
{0x0c, 0x0d, 0x0e, 0x0f}};
unsigned char CipherText_1[4][4]  = {
{0x69, 0xc4, 0xe0, 0xd8},
{0x6a, 0x7b, 0x04, 0x30},
{0xd8, 0xcd, 0xb7, 0x80},
{0x70, 0xb4, 0xc5, 0x5a}};

更新:

现在它起作用了。以下代码有以下假设:

  • 每个测试用例有3行,每行分别用于Key_1PlainText_1CipherText_1

  • Key_1PlainText_1CipherText_1中的每一个恰好具有32位并且存储在[4][4]矩阵中。

看看这段代码。尝试放置一个文件并查看输出。您应该看到对于每个测试用例,Key_1PlainText_1CipherText_1的更新值。

using namespace std;
void readFile(std::string fileName) {
unsigned char Key_1[4][4];
unsigned char PlainText_1[4][4];
unsigned char CipherText_1[4][4];
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
Key_1[i][j] = 0x00 ; PlainText_1[i][j] = 0x00 ; CipherText_1[i][j] = 0x00;
}
}
std::ifstream reader;
reader.open(fileName);
bool commentBlock = true;
int line_flag = 0;
int str2int = 0;
int line_idx = 0;
if (reader.is_open()) {
std::string line;
while (getline(reader, line)) {
if (line.substr(0, 1) != "#")
commentBlock = false;
else{
printf("n");
printf("Key_1 Contents:n");
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
printf("%xt",Key_1[i][j]);
}
printf("n");
}
printf("n");
printf("PlainText_1 Contents:n");
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
printf("%xt",PlainText_1[i][j]);
}
printf("n");
}
printf("n");
printf("CipherText_1 Contents:n");
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
printf("%xt",CipherText_1[i][j]);
}
printf("n");
}
printf("n");
commentBlock = true;
while (commentBlock) {
getline(reader, line);
if (line.substr(0, 1) != "#")
commentBlock = false;
}
}
std::cout << "Read line:" << std::endl;
printf("%sn", line.c_str());
line_idx = 0;
if (line_flag > 2){
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
Key_1[i][j] = 0x00 ; PlainText_1[i][j] = 0x00 ; CipherText_1[i][j] = 0x00;
}
}
line_flag = 0;
}
switch (line_flag){
case 0:
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
switch(line.at(line_idx)){
case 'a':
str2int = 10;
Key_1[i][j] += str2int * 16;
break;
case 'b':
str2int = 11;
Key_1[i][j] += str2int * 16;
break;
case 'c':
str2int = 12;
Key_1[i][j] += str2int * 16;
break;
case 'd':
str2int = 13;
Key_1[i][j] += str2int * 16;
break;
case 'e':
str2int = 14;
Key_1[i][j] += str2int * 16;
break;
case 'f':
str2int = 15;
Key_1[i][j] += str2int * 16;
break;
default:
str2int = stoi(line.substr(line_idx, 1));
Key_1[i][j] += str2int * 16;
break;
}
line_idx ++;
switch(line.at(line_idx)){
case 'a':
str2int = 10;
Key_1[i][j] += str2int;
break;
case 'b':
str2int = 11;
Key_1[i][j] += str2int;
break;
case 'c':
str2int = 12;
Key_1[i][j] += str2int;
break;
case 'd':
str2int = 13;
Key_1[i][j] += str2int;
break;
case 'e':
str2int = 14;
Key_1[i][j] += str2int;
break;
case 'f':
str2int = 15;
Key_1[i][j] += str2int;
break;
default:
str2int = stoi(line.substr(line_idx, 1));
Key_1[i][j] += str2int;
break;
}
line_idx ++;
}
}
line_flag++;
break;
case 1:
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
switch(line.at(line_idx)){
case 'a':
str2int = 10;
PlainText_1[i][j] += str2int * 16;
break;
case 'b':
str2int = 11;
PlainText_1[i][j] += str2int * 16;
break;
case 'c':
str2int = 12;
PlainText_1[i][j] += str2int * 16;
break;
case 'd':
str2int = 13;
PlainText_1[i][j] += str2int * 16;
break;
case 'e':
str2int = 14;
PlainText_1[i][j] += str2int * 16;
break;
case 'f':
str2int = 15;
PlainText_1[i][j] += str2int * 16;
break;
default:
str2int = stoi(line.substr(line_idx, 1));
PlainText_1[i][j] += str2int * 16;
break;
}
line_idx ++;
switch(line.at(line_idx)){
case 'a':
str2int = 10;
PlainText_1[i][j] += str2int;
break;
case 'b':
str2int = 11;
PlainText_1[i][j] += str2int;
break;
case 'c':
str2int = 12;
PlainText_1[i][j] += str2int;
break;
case 'd':
str2int = 13;
PlainText_1[i][j] += str2int;
break;
case 'e':
str2int = 14;
PlainText_1[i][j] += str2int;
break;
case 'f':
str2int = 15;
PlainText_1[i][j] += str2int;
break;
default:
str2int = stoi(line.substr(line_idx, 1));
PlainText_1[i][j] += str2int;
break;
}
line_idx ++;
}
}
line_flag++;
break;
case 2:
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
switch(line.at(line_idx)){
case 'a':
str2int = 10;
CipherText_1[i][j] += str2int * 16;
break;
case 'b':
str2int = 11;
CipherText_1[i][j] += str2int * 16;
break;
case 'c':
str2int = 12;
CipherText_1[i][j] += str2int * 16;
break;
case 'd':
str2int = 13;
CipherText_1[i][j] += str2int * 16;
break;
case 'e':
str2int = 14;
CipherText_1[i][j] += str2int * 16;
break;
case 'f':
str2int = 15;
CipherText_1[i][j] += str2int * 16;
break;
default:
str2int = stoi(line.substr(line_idx, 1));
CipherText_1[i][j] += str2int * 16;
break;
}
line_idx ++;
switch(line.at(line_idx)){
case 'a':
str2int = 10;
CipherText_1[i][j] += str2int;
break;
case 'b':
str2int = 11;
CipherText_1[i][j] += str2int;
break;
case 'c':
str2int = 12;
CipherText_1[i][j] += str2int;
break;
case 'd':
str2int = 13;
CipherText_1[i][j] += str2int;
break;
case 'e':
str2int = 14;
CipherText_1[i][j] += str2int;
break;
case 'f':
str2int = 15;
CipherText_1[i][j] += str2int;
break;
default:
str2int = stoi(line.substr(line_idx, 1));
CipherText_1[i][j] += str2int;
break;
}
line_idx ++;
}
}
line_flag++;
break;
}
}
printf("n");
printf("Key_1 Contents:n");
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
printf("%xt",Key_1[i][j]);
}
printf("n");
}
printf("n");
printf("PlainText_1 Contents:n");
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
printf("%xt",PlainText_1[i][j]);
}
printf("n");
}
printf("n");
printf("CipherText_1 Contents:n");
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
printf("%xt",CipherText_1[i][j]);
}
printf("n");
}
printf("n");
}
else {
cerr << "Can't open file " + fileName;
}
}

最新更新