NIST Special Publication 800-38A のテストベクトルを確認した

NIST Special Publication 800-38A の付録 F に記載されているテストベクトルを入力した.testNISTAESCBC256() に記述している.

実行結果

main.cpp

// AES-CBC テストベクトル確認
// http://www.ipa.go.jp/security/rfc/RFC3602JA.html#4

#include <iostream>
#include <vector>
#include <string>
#include "../bytePrinter/bytePrinter.h"
#include "../hexstring2bin/hexstring2bin.h"
#include <aes.h>
#include <cmath>

using std::cout;
using std::endl;

void printInputData(
	const std::string &keyString,
	const std::string &ivString,
	const std::string &planetextString,
	const std::string &ciphertextString)
{
	std::cout << "key       : " << keyString << std::endl;
	std::cout << "iv        : " << ivString << std::endl;
	std::cout << "planetext : " << planetextString << std::endl;
	std::cout << "ciphertext: " << ciphertextString << std::endl;
}

// 差の絶対値和を返す.負の数のときは何かおかしい
int diff(const std::vector<unsigned char>&a, const unsigned char* b, size_t bLength )
{
	if ( a.size() != bLength )
		return -1;

	int diff = 0;
	for ( size_t i = 0; i < bLength; i++ )
	{
		diff += ::abs( a[i] - b[i] );
	}

	return diff;
}

void testcase2()
{
	cout << "AES-CBC-128 のテスト.RFC3602のテストベクトル" << endl;
	cout << "http://www.ipa.go.jp/security/rfc/RFC3602JA.html#4" << endl;

	const int TextLength = 32;
	std::string keyString("0xc286696d887c9aa0611bbb3e2025a45a");
	std::string ivString("0x562e17996d093d28ddb3ba695a2e6f58");
	std::string aString("0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
	std::string bString("0xd296cd94c2cccf8a3a863028b5e1dc0a7586602d253cfff91b8266bea6d61ab1");
	printInputData(keyString,ivString,aString,bString);
	std::vector<unsigned char> key;
	std::vector<unsigned char> iv;
	std::vector<unsigned char> a;
	hexstring2bin::convert( keyString, key );
	hexstring2bin::convert( ivString, iv );
	hexstring2bin::convert( aString, a );
	unsigned char b[TextLength];
	unsigned char c[TextLength];
	unsigned char workIv[TextLength];
	::memcpy_s (workIv, TextLength, iv.data(), iv.size() );

	int result;
	aes_encrypt_ctx cxEnc;
	result = aes_encrypt_key128 ( key.data(), &cxEnc );
	::memcpy_s (workIv, TextLength, iv.data(), iv.size() );
	result = aes_cbc_encrypt( a.data(), b, TextLength, workIv, &cxEnc);
	cout << "encrypted :   "; bytePrinter::print( b, TextLength);

	aes_decrypt_ctx cxDec;
	result = aes_decrypt_key128 ( key.data(), &cxDec );
	::memcpy_s (workIv, TextLength, iv.data(), iv.size() );
	result = aes_cbc_decrypt( b, c, TextLength, workIv, &cxDec);
	cout << "decrypted :   "; bytePrinter::print( c, TextLength);
	cout << "平文一致  : " << diff ( a, c, TextLength ) << "(0 なら一致)" << endl;
	cout << "暗号文一致: " << diff ( a, c, TextLength ) << "(0 なら一致)" << endl;
	cout << endl;
}

void testaescbc256()
{
	cout << "AES-CBC-256 のテスト.テストベクトル非準拠" << endl;
	const int TextLength = 32;

	std::string keyString("0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
	std::string ivString ("0x562e17996d093d28ddb3ba695a2e6f58");
	std::string aString  ("0x4596e435252346526ea0343434845758d47589375983a45983c5d83759374552");
	std::string bString  ("テストベクトルではないため未知");
	// 49e4b393026fb9ea90b5fcfcdc413dd6bac5083becc7b5e693c0ea8156eef1c4
	printInputData(keyString,ivString,aString,bString);
	std::vector<unsigned char> key;
	std::vector<unsigned char> iv;
	std::vector<unsigned char> a;
	hexstring2bin::convert( keyString, key );
	hexstring2bin::convert( ivString, iv );
	hexstring2bin::convert( aString, a );
	unsigned char b[TextLength];
	unsigned char c[TextLength];
	unsigned char workIv[TextLength];
	::memcpy_s (workIv, TextLength, iv.data(), iv.size() );

	int result;
	aes_encrypt_ctx cxEnc;
	result = aes_encrypt_key256 ( key.data(), &cxEnc );
	::memcpy_s (workIv, TextLength, iv.data(), iv.size() );
	result = aes_cbc_encrypt( a.data(), b, TextLength, workIv, &cxEnc);
	cout << "encrypted :   "; bytePrinter::print( b, TextLength);

	aes_decrypt_ctx cxDec;
	result = aes_decrypt_key256 ( key.data(), &cxDec );
	::memcpy_s (workIv, TextLength, iv.data(), iv.size() );
	result = aes_cbc_decrypt( b, c, TextLength, workIv, &cxDec);
	cout << "decrypted :   "; bytePrinter::print( c, TextLength);
	cout << "平文一致  : " << diff ( a, c, TextLength ) << "(0 なら一致)" << endl;
	cout << "暗号文一致: " << diff ( a, c, TextLength ) << "(0 なら一致)" << endl;
	cout << endl;
}

void testNISTAESCBC256()
{
	// http://d.hatena.ne.jp/Guernsey/20091013/1255415857
	// NIST Special Publication 800-38A の付録に記載されているテストベクトルを使用する
	// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
	// 対象は 付録 F2.5 CBC-AES256.Encrypt および同 F2.6 CBC-AES256.Decrypt
	cout << "NIST Special Publication 800-38A 付録 F2.5 CBC-AES256.Encrypt および同 F2.6 CBC-AES256.Decrypt のテスト" << endl;
	cout << "http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf" << endl;
	const int TextLength = 64;

	std::string keyString("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
	std::string ivString ("000102030405060708090a0b0c0d0e0f");
	std::string aString  ("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710");
	std::string bString  ("f58c4c04d6e5f1ba779eabfb5f7bfbd69cfc4e967edb808d679f777bc6702c7d39f23369a9d9bacfa530e26304231461b2eb05e2c39be9fcda6c19078c6a9d1b");
	printInputData(keyString,ivString,aString,bString);
	std::vector<unsigned char> key;
	std::vector<unsigned char> iv;
	std::vector<unsigned char> a;
	hexstring2bin::convert( keyString, key );
	hexstring2bin::convert( ivString, iv );
	hexstring2bin::convert( aString, a );
	unsigned char b[TextLength];
	unsigned char c[TextLength];
	unsigned char workIv[TextLength];
	::memcpy_s (workIv, TextLength, iv.data(), iv.size() );

	int result;
	aes_encrypt_ctx cxEnc;
	result = aes_encrypt_key256 ( key.data(), &cxEnc );
	::memcpy_s (workIv, TextLength, iv.data(), iv.size() );
	result = aes_cbc_encrypt( a.data(), b, TextLength, workIv, &cxEnc);
	cout << "encrypted : "; bytePrinter::print( b, TextLength);

	aes_decrypt_ctx cxDec;
	result = aes_decrypt_key256 ( key.data(), &cxDec );
	::memcpy_s (workIv, TextLength, iv.data(), iv.size() );
	result = aes_cbc_decrypt( b, c, TextLength, workIv, &cxDec);
	cout << "decrypted : "; bytePrinter::print( c, TextLength);
	cout << "平文一致  : " << diff ( a, c, TextLength ) << "(0 なら一致)" << endl;
	cout << "暗号文一致: " << diff ( a, c, TextLength ) << "(0 なら一致)" << endl;
	cout << endl;
}

int main () 
{
	aes_init();
	testcase2();
	testaescbc256();
	testNISTAESCBC256();

	return 0;
}