在前面的兩篇文章,已經(jīng)對EVP_Encrypt*...*系列函數做了詳細的介紹,本章將說(shuō)明該系列函數通用的應用架構,并舉幾個(gè)函數應用例子。
【應用架構】
一般來(lái)說(shuō),EVP_Encrypt*...*系列函數的應用架構如下所描述(假設加密算法為3DES):1.定義一些必須的變量
char key[EVP_MAX_KEY_LENGTH];
char iv[EVP_MAX_IV_LENGTH];
EVP_CIPHER_CTX ctx;
unsigned char out[512+8];
int outl;
2.給變量key和iv賦值,這里使用了函數EVP_BytesToKey,該函數從輸入密碼產(chǎn)生了密鑰key和初始化向量iv,該函數將在后面做介紹。如果可以有別的辦法設定key和iv,該函數的調用不是必須的EVP_BytesToKey(EVP_des_ede3_cbc,EVP_md5,NULL,passwd,strlen(passwd),key,iv);
3.初始加密算法結構EVP_CIPHER_CTXEVP_EncryptInit_ex(&ctx,EVP_des_ede3_cbc(),NULL,key,iv);
4.進(jìn)行數據的加密操作
while(....)
{
EVP_EncryptUpdate(ctx,out,&outl,in,512);
}
一般來(lái)說(shuō)采用了循環(huán)的結構進(jìn)行處理,每次循環(huán)加密數據為512字節,密文輸出到out,out和int應該是指向不相同的內存的。
5.結束加密,輸出最后的一段512字節的數據EVP_EncryptFinal_ex(&ctx,out,&outl)該函數會(huì )進(jìn)行加密的檢測,如果加密過(guò)程有誤,一般會(huì )檢查出來(lái)。說(shuō)明:加密跟上述過(guò)程是一樣的,只不過(guò)要使用EVP_Decrypt*...*系列函數。
【例子】
1.取得算法RC5使用的循環(huán)次數(round)
int nrounds;
EVP_CIPHER_CTX_ctrl(ctx,EVP_CTRL_GET_RC5_ROUNDS,0,&nrounds);
2.取得算法RC2的有效密鑰長(cháng)度
int key_bits;
EVP_CIPHER_CTX_ctrl(ctx,EVP_CTRL_GET_RC2_KEY_BITS,0,&key_bits);
3.設置算法RC5使用的循環(huán)次數(round)
int nrounds;
EVP_CIPHER_CTX_ctrl(ctx,EVP_CTRL_SET_RC5_ROUNDS,nrounds,NULL);
4.設置算法RC2的有效密鑰長(cháng)度
int key_bits;
EVP_CIPHER_CTX_ctrl(ctx,EVP_CTRL_SET_RC2_KEY_BITS,key_bits,NULL);
5.使用Blowfish算法加密一個(gè)字符串
int do_crypt(char*outfile)
{
unsigned char outbuf[1024];
int outlen,tmplen;
//其實(shí)key和iv一般應該從別的地方得到,這里固定了至少作為演示使用的
unsigned char key[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
unsigned char iv[]={1,2,3,4,5,6,7,8};
char int ext[]="SomeCryptoText";
EVP_CIPHER_CTX ctx;
FILE* out;
EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit_ex(&ctx,EVP_bf_cbc(),NULL,key,iv);
if(!EVP_EncryptUpdate(&ctx,outbuf,&outlen,intext,strlen(intext)))
{
/*出錯處理*/
return0;
}
//注意,傳入給下面函數的輸出緩存參數必須注意不能覆蓋了原來(lái)的加密輸出的數據
if(!EVP_EncryptFinal_ex(&ctx,outbuf+outlen,&tmplen))
{
/*出錯處理*/
return0;
}
outlen+=tmplen;
EVP_CIPHER_CTX_cleanup(&ctx);
//注意,保存到文件的時(shí)候要使用二進(jìn)制模式打開(kāi)文件,因為密文數據是二進(jìn)制的,而且,不能采用strlen函數,因為密文字符串不是以NULL(0)為結束的字符串
out=fopen(outfile,"wb");
fwrite(outbuf,1,outlen,out);
fclose(out);
return1;
}
上面舉的例子加密的密文可以使用openssl提供的應用程序cipher.exe來(lái)解密,命令如下:opensslbf-incipher.bin-K000102030405060708090A0B0C0D0E0F-iv0102030405060708-d
6.使用文件I/O和80位密鑰RC2算法的通用加密解密函數實(shí)例,該函數可以進(jìn)行加密,也可以進(jìn)行解密,由參數do_encrypt決定,該參數為1時(shí)則執行加密,為0時(shí)則執行解密。
int do_crypt(FILE*in,FILE*out,intdo_encrypt)
{
/*為輸出緩沖設置足夠的附加空間*/
inbuf[1024],outbuf[1024+EVP_MAX_BLOCK_LENGTH];
int inlen,outlen;
//其實(shí)key和iv一般應該從別的地方得到,這里固定了至少作為演示使用的
unsigned char key[]="0123456789";
unsigned char iv[]="12345678";
//這時(shí)候不進(jìn)行key和IV的設置,因為我們還要修改參數
EVP_CIPHER_CTX_init(&ctx);
EVP_CipherInit_ex(&ctx,EVP_rc2(),NULL,NULL,NULL,do_encrypt);
EVP_CIPHER_CTX_set_key_length(&ctx,10);
//完成參數設置,進(jìn)行key和IV的設置
EVP_CipherInit_ex(&ctx,NULL,NULL,key,iv,do_encrypt);
for(;;)
{
inlen=fread(inbuf,1,1024,in);
if(inlen<=0)break;
if(!EVP_CipherUpdate(&ctx,outbuf,&outlen,inbuf,inlen))
{
/*出錯處理*/
return0;
}
fwrite(outbuf,1,outlen,out);
}
if(!EVP_CipherFinal_ex(&ctx,outbuf,&outlen))
{
/*出錯處理*/
return0;
}
fwrite(outbuf,1,outlen,out);
EVP_CIPHER_CTX_cleanup(&ctx);
return1;
}
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請
點(diǎn)擊舉報。