6.1.2
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#define ITERATIVE_ROUND_FOR_KEY 6
#define CHARS_PER_LINE_BASE64 65
void print(const char* promptStr,unsigned char * data,int len)
{
int i;
printf("=================%s[长度=%d]============\n",promptStr,len);
for(i=0;i<len;i++) printf("%02x",data[i]);
printf("\n===========================================\n");
}
//base64 编码
void encode(
unsigned char* outData,
int * outlen,
const unsigned char * data,
int datalen
)
{
int tmp=0;
EVP_ENCODE_CTX base64;
EVP_EncodeInit(&base64);
EVP_EncodeUpdate(
&base64,
outData,
outlen,
data,
datalen
);
tmp=*outlen;
EVP_EncodeFinal(
&base64,
outData+*outlen,
outlen
);
*outlen+=tmp;
outData[*outlen]=0;
print(
"base64 编码后:",
outData,
*outlen
);
}
//base64 解码
bool decode(
unsigned char * outData,
int *outlen,
const unsigned char * data,
int datalen
)
{
int i=0,tmp=0,currpos=0,lines=0;
EVP_ENCODE_CTX base64;
EVP_DecodeInit(&base64);
for(;;)
{
currpos+=CHARS_PER_LINE_BASE64*lines++;
i= EVP_DecodeUpdate(
&base64,
outData+tmp,
outlen,
data+currpos,
datalen-currpos
);
if(i<0)
{
printf("解码错误!\n");
return false;
}
tmp+=*outlen;
if(i==0) break;
}
EVP_DecodeFinal(&base64,outData+tmp,outlen);
*outlen+=tmp;
outData[*outlen]=0;
print("base 64 解码后:",outData,*outlen);
return true;
}
void main()
{
OpenSSL_add_all_ciphers();
OpenSSL_add_all_digests();
//加密
const EVP_CIPHER * type;
type=EVP_des_ede3_cbc();
printf("密钥长度=%d,向量长度=%d\n",type->key_len,type->iv_len);
const char * password="renhl252";//用口令生成密钥
printf("密码是:%s\n",password);
unsigned char key[EVP_MAX_KEY_LENGTH];
unsigned char iv[EVP_MAX_IV_LENGTH];
EVP_BytesToKey(
type,//密钥类型
EVP_md5(),//摘要计算类型
NULL,
(const unsigned char *)password,
(int)strlen(password),
ITERATIVE_ROUND_FOR_KEY,//迭代轮数
key,
iv
);
EVP_CIPHER_CTX ctx;
EVP_EncryptInit(&ctx,type,key,iv);
char SimpleText[]="Let's pray for peace of our lovely world.";
unsigned char out[512+8];
int outl;
int temp=(int)strlen(SimpleText);
EVP_EncryptUpdate(
&ctx,
out,
&outl,
(const unsigned char *)SimpleText,
(int)strlen(SimpleText)
);
temp=outl;
EVP_EncryptFinal(&ctx,out+outl,&outl);
outl+=temp;
EVP_CIPHER_CTX_cleanup(&ctx);
print("加密之后结果:",out,outl);
unsigned char txtAfterBase64[sizeof(SimpleText)*3];
//进行base64编码
encode(
txtAfterBase64,
&temp,
out,
outl
);
memset(
out,
0,
sizeof(out)
);
//解码
decode(
out,
&outl,
txtAfterBase64,
temp
);
//解密
unsigned char txAfterDecrypt[512];
int txLenAfterDecrypt;
EVP_DecryptInit(&ctx,type,key,iv);
EVP_DecryptUpdate(
&ctx,
txAfterDecrypt,
&txLenAfterDecrypt,
out,
outl
);
temp=txLenAfterDecrypt;
EVP_DecryptFinal(&ctx,
txAfterDecrypt+txLenAfterDecrypt,
&txLenAfterDecrypt);
txLenAfterDecrypt+=temp;
EVP_CIPHER_CTX_cleanup(&ctx);
txAfterDecrypt[txLenAfterDecrypt]=0;
printf("解密之后结果(长度=%d):\n[%s]\n",txLenAfterDecrypt,txAfterDecrypt);
printf("\n===========================================\n");
printf("\nclick any key continue.");
getchar();
}
6.2.2
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
void print(const char* promptStr,unsigned char * data,int len)
{
int i;
printf("=================%s[长度=%d]============\n",promptStr,len);
for(i=0;i<len;i++) printf("%02x",data[i]);
printf("\n===========================================\n");
}
//如果成功返回包装了RSA参数的EVP_PKEY,否则返回NULL
EVP_PKEY *getRSA()
{
EVP_PKEY *pkey=NULL;
RSA *rsa=RSA_generate_key(
1024,
RSA_3,
NULL,
NULL
);
if(NULL==rsa)
{
printf("生成RSA密钥对失败!\n");
return NULL;
}
//隐藏RSA密钥抵御定时攻击
RSA_blinding_on(rsa,NULL);
printf("\n成功生成RSA密钥对!\n");
pkey=EVP_PKEY_new();
if(NULL==pkey)
{
printf("EVP_PKEY_new failed\n");
RSA_free(rsa);
return NULL;
}
//将rsa对象赋给EVP_PKEY结构
EVP_PKEY_assign_RSA(pkey,rsa);
return pkey;
}
void main()
{
OpenSSL_add_all_ciphers();
EVP_PKEY *pkey=NULL;
int len=-1;
char plainText[]="[For test to public/private key encryption/decryption]";
unsigned char encData[512];
unsigned char decData[512];
pkey=getRSA();
if(pkey==NULL)
{
exit(-1);
}
len=EVP_PKEY_encrypt(
encData,
(unsigned char *)plainText,
sizeof(plainText),
pkey
);
if(len==-1)
{
printf("EVP_PKEY_encrypt加密失败\n");
exit(-1);
}
print("加密后的数据",encData,len);
len=EVP_PKEY_decrypt(
decData,
encData,
len,
pkey
);
if(len==-1)
{
printf("EVP_PKEY_decrypt解密失败\n");
exit(-1);
}
print("解密后的数据",decData,len);
printf("\n明文是:[长度=%d字节]:%s\n",len,decData);
EVP_PKEY_free(pkey);
printf("\nclick any key continue.");
getchar();
}
6.3.2
//哈希摘要算法
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
void main()
{
OpenSSL_add_all_digests();
//初始化上下文对象的初始函数
EVP_MD_CTX mdctx;
EVP_MD_CTX_init(&mdctx);
//初始化摘要算法
const char *digestName="sha1";//"md5";
const EVP_MD *md;
md=EVP_get_digestbyname(digestName);
if(!md)
{
printf("错误的摘要算法名称:%s\n",digestName);
exit(1);
}
EVP_DigestInit(&mdctx,md);
//要被计算的消息数组
char msgs[][64]={
"It's just for test","Author:Jian Shen",
"HelloWord from openssl"
};
//循环加入技术摘要的数据
for(int i=0;i<sizeof(msgs)/sizeof(msgs[0]);i++)
{
EVP_DigestUpdate(
&mdctx,
msgs[i],
strlen(msgs[i])
);
}
//结束摘要计算
unsigned int md_len;
unsigned char md_value[EVP_MAX_MD_SIZE];
EVP_DigestFinal(&mdctx,md_value,&md_len);
EVP_MD_CTX_cleanup(&mdctx);
printf("摘要值是:(类型=%s;长度=%d 字节):",digestName,md_len);
for(unsigned int j=0;j<md_len;j++) printf("%02x",md_value[j]);
printf("\n");
}
6.4.2.txt
//哈希摘要算法
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
void print(const char* promptStr,unsigned char * data,int len)
{
int i;
printf("=================%s[长度=%d]============\n",promptStr,len);
for(i=0;i<len;i++) printf("%02x",data[i]);
printf("\n===========================================\n");
}
void main()
{
OpenSSL_add_all_digests();
HMAC_CTX mac_ctx;
//初始化摘要算法
const char *digestName="sha1";//"md5";
const EVP_MD *md;
md=EVP_get_digestbyname(digestName);
if(!md)
{
printf("错误的摘要算法名称:%s\n",digestName);
exit(1);
}
char key[]="simple_key";
HMAC_Init(&mac_ctx,key,sizeof(key),md);
unsigned char buffer[2048]="yasiuiasdasdooasdjidajiodjajiaiadjioioadidjjdjdjjdjjakkajajgewyeygedbdbbdbdb";
HMAC_Update(&mac_ctx,buffer,sizeof("yasiuiasdasdooasdjidajiodjajiaiadjioioadidjjdjdjjdjjakkajajgewyeygedbdbbdbdb"));
unsigned char mac_value[EVP_MAX_MD_SIZE];
unsigned int mac_len=0;
HMAC_Final(&mac_ctx,mac_value,&mac_len);
HMAC_cleanup(&mac_ctx);
printf("HMAC(%s,%s)\n",buffer,key);
print(NULL,mac_value,mac_len);
}
6.5.2.txt
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
void print(const char* promptStr,unsigned char * data,int len)
{
int i;
printf("=================%s[长度=%d]============\n",promptStr,len);
for(i=0;i<len;i++) printf("%02x",data[i]);
printf("\n===========================================\n");
}
//如果成功返回EVP_KEY,否则返回NULL
EVP_PKEY *getDSA()
{
EVP_PKEY *pkey=NULL;
DSA * dsa=DSA_generate_parameters(1024,NULL,0,NULL,NULL,NULL,NULL);
if(NULL==dsa)
{
printf("生成DSA参数失败\n");
return NULL;
}
printf("\nDSA参数成功产生!\n");
int ret=0;
ret=DSA_generate_key(dsa);
if(ret==0)
{
printf("\nDSA_generate_key 调用失败\n");
goto err;
}
printf("\nDSA密钥对生成成功\n");
pkey=EVP_PKEY_new();
if(NULL==pkey)
{
printf("\nEVP_PKEY_new 失败\n");
goto err;
}
EVP_PKEY_assign_DSA(pkey,dsa);
return pkey;
err:
DSA_free(dsa);
return NULL;
}
void main()
{
OpenSSL_add_all_ciphers();
OpenSSL_add_all_digests();
EVP_MD_CTX mdctx;
EVP_MD_CTX_init(&mdctx);
const EVP_MD *md;
char mdName[]="dss1";
md=EVP_get_digestbyname(mdName);
if(!md)
{
printf("错误的摘要算法名称:%s\n",mdName);
exit(1);
}
EVP_SignInit(&mdctx,md);
//依次加入所要签名的数据
char msgs[][64]={
"It's just for test.",
"Author:Jian Shen",
"Hello World from openssl"
};
int i;
for(i=0;i<sizeof(msgs)/sizeof(msgs[0]);i++)
{
EVP_SignUpdate(&mdctx,msgs[i],strlen(msgs[i]));
}
//计算签名;实际上该步先计算摘要值,然后对该值用私钥签名
unsigned char sig_value[1024];
unsigned int sig_len;
EVP_PKEY * pkey=NULL;
pkey=getDSA();
if(pkey==NULL)
{
exit(1);
}
i=EVP_SignFinal(
&mdctx,
sig_value,
&sig_len,
pkey
);
if(i==0)
{
printf("计算签名失败");
exit(1);
}
EVP_MD_CTX_cleanup(&mdctx);
EVP_PKEY_free(pkey);
print("签名值是:",sig_value,sig_len);
}