本文主要是介绍密码库LibTomCrypt学习记录——(2.3)分组密码算法的工作模式——ECB代码示例,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
以下代码实现了AES-ECB的正确性测试(标准测试数据),以及性能测试
说明:
1. 代码里面使用了一个Str2Num函数,它将测试向量中的字符串转为十六进制字节数据,可自行实现。
2. 测试向量出处为NIST SP 800-38A (Recommendation for Block Cipher Modes of Operation:Methods and Techniques)
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Test_ECB_AES.h
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#include <Windows.h>
#include "tomcrypt.h"
#include "TestMode.h"
typedef struct NistECBTestVector_st{
char * name;//test vetor name
int keylen;
int msglen;
BYTE * key[1]; // 密钥
BYTE * IV[1]; // 初始化向量
BYTE * pt[4]; // 明文,暂时最多支持四段明文
BYTE * ct[4]; // 密文,暂时最多支持四段明文
BYTE * nonce[1];
BYTE * associated_data[1];
BYTE * mac[1];
} NistECBTestVector;
// 数据来源
// NIST SP 800-38A (Recommendation for Block Cipher Modes of Operation:Methods and Techniques).pdf
NistECBTestVector ecb_vect[] = {
{//vect[0]
/*name*/ "F.1.1 key=128 Encrypt",
/*keylen*/ 16,
/*msglen*/ 16*4,
/*Key*/ "2b7e151628aed2a6abf7158809cf4f3c",
/*IV */ "",//ECB无初始化向量
{// pt
"6bc1bee22e409f96e93d7e117393172a",
"ae2d8a571e03ac9c9eb76fac45af8e51",
"30c81c46a35ce411e5fbc1191a0a52ef",
"f69f2445df4f9b17ad2b417be66c3710"
},
{//ct
"3ad77bb40d7a3660a89ecaf32466ef97",
"f5d3d58503b9699de785895a96fdbaaf",
"43b1cd7f598ece23881b00e3ed030688",
"7b0c785e27e8ad3f8223207104725dd4"
}
},
//
{//vect[1]
/*name*/ "F.1.2 key=128 Decrypt",
/*keylen*/ 16,
/*msglen*/ 16*4,
/*Key*/ "2b7e151628aed2a6abf7158809cf4f3c",
/*IV */ "",//ECB无初始化向量
{//ct //解密时明文密文相反而已
"3ad77bb40d7a3660a89ecaf32466ef97",
"f5d3d58503b9699de785895a96fdbaaf",
"43b1cd7f598ece23881b00e3ed030688",
"7b0c785e27e8ad3f8223207104725dd4"
},
{// pt //解密时明文密文相反而已
"6bc1bee22e409f96e93d7e117393172a",
"ae2d8a571e03ac9c9eb76fac45af8e51",
"30c81c46a35ce411e5fbc1191a0a52ef",
"f69f2445df4f9b17ad2b417be66c3710"
}
},
//
{//vect[2]
/*name*/ "F.1.3 key=192 Encrypt",
/*keylen*/ 24,
/*msglen*/ 16*4,
/*Key*/ "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
/*IV */ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
{// pt
"6bc1bee22e409f96e93d7e117393172a",
"ae2d8a571e03ac9c9eb76fac45af8e51",
"30c81c46a35ce411e5fbc1191a0a52ef",
"f69f2445df4f9b17ad2b417be66c3710"
},
{//ct
"bd334f1d6e45f25ff712a214571fa5cc",
"974104846d0ad3ad7734ecb3ecee4eef",
"ef7afd2270e2e60adce0ba2face6444e",
"9a4b41ba738d6c72fb16691603c18e0e"
}
},
//
{//vect[3]
/*name*/ "F.1.4 key=192 Decrypt",
/*keylen*/ 24,
/*msglen*/ 16*4,
/*Key*/ "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b",
/*IV */ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
{//ct //解密时明文密文相反而已
"bd334f1d6e45f25ff712a214571fa5cc",
"974104846d0ad3ad7734ecb3ecee4eef",
"ef7afd2270e2e60adce0ba2face6444e",
"9a4b41ba738d6c72fb16691603c18e0e"
},
{// pt //解密时明文密文相反而已
"6bc1bee22e409f96e93d7e117393172a",
"ae2d8a571e03ac9c9eb76fac45af8e51",
"30c81c46a35ce411e5fbc1191a0a52ef",
"f69f2445df4f9b17ad2b417be66c3710"
}
},
//
{//vect[4]
/*name*/ "F.1.5 key=256 Encrypt",
/*keylen*/ 32,
/*msglen*/ 16*4,
/*Key*/ "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
/*IV */ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
{// pt
"6bc1bee22e409f96e93d7e117393172a",
"ae2d8a571e03ac9c9eb76fac45af8e51",
"30c81c46a35ce411e5fbc1191a0a52ef",
"f69f2445df4f9b17ad2b417be66c3710"
},
{//ct
"f3eed1bdb5d2a03c064b5a7e3db181f8",
"591ccb10d410ed26dc5ba74a31362870",
"b6ed21b99ca6f4f9f153e7b1beafed1d",
"23304b7a39f9f3ff067d8d8f9e24ecc7"
}
},
//
{//vect[5]
/*name*/ "F.1.6 key=256 Decrypt",
/*keylen*/ 32,
/*msglen*/ 16*4,
/*Key*/ "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
/*IV */ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
{//ct //解密时明文密文相反而已
"f3eed1bdb5d2a03c064b5a7e3db181f8",
"591ccb10d410ed26dc5ba74a31362870",
"b6ed21b99ca6f4f9f153e7b1beafed1d",
"23304b7a39f9f3ff067d8d8f9e24ecc7"
},
{// pt //解密时明文密文相反而已
"6bc1bee22e409f96e93d7e117393172a",
"ae2d8a571e03ac9c9eb76fac45af8e51",
"30c81c46a35ce411e5fbc1191a0a52ef",
"f69f2445df4f9b17ad2b417be66c3710"
}
}
};
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Test_ECB_AES.cpp
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#include <Windows.h>
#include "tomcrypt.h"
#include "TestMode.h"
#include "Test_ECB_AES.h"
int Test_ECB_AES_Alg(void)
{
int idx, err, i, res;
BYTE buf[64];
symmetric_ECB ctr;
int keylen, msglen;
BYTE key[32], IV[16], pt[64], ct[64];
char *p_operate;
IV[0] = 0;
/* AES can be under rijndael or aes... try to find it */
if ( register_cipher (&aes_desc) != CRYPT_OK ) { return CRYPT_INVALID_CIPHER; }
if ((idx = find_cipher("aes")) == -1) { return CRYPT_NOP; }
printf("\nTest ECB AES Begin!\n" );
for ( i = 0; i < (int)(sizeof(ecb_vect)/sizeof(ecb_vect[0])); i++ )
{
keylen = ecb_vect[i].keylen;
msglen = ecb_vect[i].msglen;
Str2Num(ecb_vect[i].key, 1, key);
// ChangeText(vect[i].IV, 1, IV);
Str2Num(ecb_vect[i].pt, 4, pt);
Str2Num(ecb_vect[i].ct, 4, ct);
if ((err = ecb_start(idx, key, keylen, 0, &ctr)) != CRYPT_OK)
{
return err;
}
p_operate = ecb_vect[i].name + strlen(ecb_vect[i].name) - strlen("Encrypt");
if (strcmp( p_operate, "Encrypt") == 0 )
{
if ((err = ecb_encrypt( pt, buf, msglen, &ctr)) != CRYPT_OK)
{
return err;
}
}
else if (strcmp( p_operate, "Decrypt") == 0 )
{
if ((err = ecb_decrypt( pt, buf, msglen, &ctr)) != CRYPT_OK)
{
return err;
}
}
else
{
printf("Test Vetor : operate err! %s \n",ecb_vect[i].name );
}
ecb_done(&ctr);
res = XMEMCMP(buf, ct, msglen);
printf("Test Vetor : %s pass ? %s \n",ecb_vect[i].name, (res == 0)?"Yes":"No" );
}
unregister_cipher (&aes_desc);
printf("\nTest ECB AES Finish!\n" );
return CRYPT_OK;
}
//
int Test_ECB_AES_Speed(char *p_cipher_name )//test speed
{
int idx, err, i, res = 0,counter, counter_bound = 1000*1000*10;
BYTE buf[64];
symmetric_ECB ctr;
int keylen, msglen, len;
BYTE key[32], IV[16], pt[64], ct[64];
char *p_operate;
LARGE_INTEGER frequence, start_time, end_time, cost_time;
double use_time;
double speed;
// const struct ltc_cipher_descriptor *p_alg_desc = (&aes_desc);
QueryPerformanceFrequency( &frequence);
IV[0] = 0;
/* AES can be under rijndael or aes... try to find it */
// if ( register_cipher (p_alg_desc) != CRYPT_OK ) { return CRYPT_INVALID_CIPHER; }
// if ((idx = find_cipher(p_alg_desc->name)) == -1) { return CRYPT_NOP; }
if ((idx = find_cipher(p_cipher_name)) == -1)
{
printf("\nTest ECB Speed Err! Not Find Cipher %s\n", p_cipher_name );
return CRYPT_NOP;
}
printf("Test ECB Speed Begin ! Use Alg %s\n", p_cipher_name );
for ( i = 0; i < (int)(sizeof(ecb_vect)/sizeof(ecb_vect[0])); i++ )
{
keylen = ecb_vect[i].keylen;
msglen = ecb_vect[i].msglen;
len = cipher_descriptor[idx].block_length;
Str2Num(ecb_vect[i].key, 1, key);
// ChangeText(vect[i].IV, 1, IV);
Str2Num(ecb_vect[i].pt, 4, pt);
Str2Num(ecb_vect[i].ct, 4, ct);
if (keylen > cipher_descriptor[idx].max_key_length)
{
keylen = cipher_descriptor[idx].max_key_length;//
}
if (keylen < cipher_descriptor[idx].min_key_length)
{
keylen = cipher_descriptor[idx].min_key_length;//
}
if ((err = ecb_start(idx, key, keylen, 0, &ctr)) != CRYPT_OK)
{
break;//return err;
}
p_operate = ecb_vect[i].name + strlen(ecb_vect[i].name) - strlen("Encrypt");
if (strcmp( p_operate, "Encrypt") == 0 )
{
memcpy(buf, pt, 64);
QueryPerformanceCounter(&start_time); // cost time
for (counter = 0; counter < counter_bound; ++counter)
{
ecb_encrypt(buf, buf, /*16*/len, &ctr);
}
QueryPerformanceCounter(&end_time);// cost time
cost_time.QuadPart = end_time.QuadPart - start_time.QuadPart;
}
else if (strcmp( p_operate, "Decrypt") == 0 )
{
memcpy(buf, pt, 64);
QueryPerformanceCounter(&start_time); // cost time
for (counter = 0; counter < counter_bound; ++counter )
{
ecb_decrypt(buf, buf, /*16*/len, &ctr);
}
QueryPerformanceCounter(&end_time);// cost time
cost_time.QuadPart = end_time.QuadPart - start_time.QuadPart;
}
else
{
printf("Test Vector : operate err! %s \n",ecb_vect[i].name );
}
ecb_done(&ctr);
// res = XMEMCMP(buf, ct, msglen);
use_time = cost_time.QuadPart / (double)(frequence.QuadPart);
speed = ( counter_bound / 1000000 ) * len * 8 / use_time ;
printf("%s key = %d, cost %8.3f s, speed %8.3f mbps \n", p_operate, keylen, use_time, speed);
}
printf("Test ECB Speed Finish! Use Alg %s\n", p_cipher_name );
printf("\n###############################################\n\n", p_cipher_name );
return CRYPT_OK;
}
void register_algs(void)
{
register_cipher (&aes_desc);//
register_cipher (&blowfish_desc);//
register_cipher (&xtea_desc);
register_cipher (&rc5_desc);
register_cipher (&rc6_desc);
// register_cipher (&saferp_desc);//
register_cipher (&twofish_desc);//
// register_cipher (&safer_k64_desc);
// register_cipher (&safer_sk64_desc);
// register_cipher (&safer_k128_desc);
// register_cipher (&safer_sk128_desc);
register_cipher (&rc2_desc);
register_cipher (&des_desc);//
register_cipher (&des3_desc);//
register_cipher (&cast5_desc);//
register_cipher (&noekeon_desc);
register_cipher (&skipjack_desc);
register_cipher (&khazad_desc);//
register_cipher (&anubis_desc); //
register_cipher (&kseed_desc);//
register_cipher (&kasumi_desc); //
// register_cipher (&multi2_desc); //
}
int Test_ECB_AES(void)
{
// Test_ECB_AES_Alg( );
int i = 0;
register_algs( );
for ( i = 0;i<TAB_SIZE;i++)
{
if (cipher_descriptor[i].name != NULL )
{
Test_ECB_AES_Speed( cipher_descriptor[i].name );
}
}
return 1;
}
ecb\ecb_XXX.c
/**
Initialize a ECB context
@param cipher The index of the cipher desired
@param key The secret key
@param keylen The length of the secret key (octets)
@param num_rounds Number of rounds in the cipher desired (0 for default)
@param ecb The ECB state to initialize
@return CRYPT_OK if successful
*/
int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, symmetric_ECB *ecb)
{
int err;
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ecb != NULL);
if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
return err;
}
ecb->cipher = cipher;
ecb->blocklen = cipher_descriptor[cipher].block_length;
return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ecb->key);
}
/**
ECB encrypt
@param pt Plaintext
@param ct [out] Ciphertext
@param len The number of octets to process (must be multiple of the cipher block size)
@param ecb ECB state
@return CRYPT_OK if successful
*/
int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb)
{
int err;
LTC_ARGCHK(pt != NULL);
LTC_ARGCHK(ct != NULL);
LTC_ARGCHK(ecb != NULL);
if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
return err;
}
if (len % cipher_descriptor[ecb->cipher].block_length) {
return CRYPT_INVALID_ARG;
}
/* check for accel */
if (cipher_descriptor[ecb->cipher].accel_ecb_encrypt != NULL) {
return cipher_descriptor[ecb->cipher].accel_ecb_encrypt(pt, ct, len / cipher_descriptor[ecb->cipher].block_length, &ecb->key);
} else {
while (len) {
if ((err = cipher_descriptor[ecb->cipher].ecb_encrypt(pt, ct, &ecb->key)) != CRYPT_OK) {
return err;
}
pt += cipher_descriptor[ecb->cipher].block_length;
ct += cipher_descriptor[ecb->cipher].block_length;
len -= cipher_descriptor[ecb->cipher].block_length;
}
}
return CRYPT_OK;
}
/**
ECB decrypt
@param ct Ciphertext
@param pt [out] Plaintext
@param len The number of octets to process (must be multiple of the cipher block size)
@param ecb ECB state
@return CRYPT_OK if successful
*/
int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb)
{
int err;
LTC_ARGCHK(pt != NULL);
LTC_ARGCHK(ct != NULL);
LTC_ARGCHK(ecb != NULL);
if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
return err;
}
if (len % cipher_descriptor[ecb->cipher].block_length) {
return CRYPT_INVALID_ARG;
}
/* check for accel */
if (cipher_descriptor[ecb->cipher].accel_ecb_decrypt != NULL) {
return cipher_descriptor[ecb->cipher].accel_ecb_decrypt(ct, pt, len / cipher_descriptor[ecb->cipher].block_length, &ecb->key);
} else {
while (len) {
if ((err = cipher_descriptor[ecb->cipher].ecb_decrypt(ct, pt, &ecb->key)) != CRYPT_OK) {
return err;
}
pt += cipher_descriptor[ecb->cipher].block_length;
ct += cipher_descriptor[ecb->cipher].block_length;
len -= cipher_descriptor[ecb->cipher].block_length;
}
}
return CRYPT_OK;
}
/** Terminate the chain
@param ecb The ECB chain to terminate
@return CRYPT_OK on success
*/
int ecb_done(symmetric_ECB *ecb)
{
int err;
LTC_ARGCHK(ecb != NULL);
if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
return err;
}
cipher_descriptor[ecb->cipher].done(&ecb->key);
return CRYPT_OK;
}
这篇关于密码库LibTomCrypt学习记录——(2.3)分组密码算法的工作模式——ECB代码示例的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!