1、首先openssl命令行如下
#openssl enc -d -aes192 -pass "pass:3eDc#9ujN" -p -in hfb1062.enc -out a.cpio
salt=28C7761EE45FFB06
key=00297EE7F640FB3545C9466583B9D008A4EB3CF24A4EFF65
iv =F4F137201648930D6BA620806691EF71
2、passwor转化成key和iv
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
//openssl enc -d -aes192 -pass "pass:3eDc#9ujN" -p -in hfb1062.enc -out a.cpio
//openssl password to key,iv
int main(int argc, char *argv[])
{
const EVP_CIPHER *cipher;
static const char magic[]="Salted__";
char mbuf[sizeof magic-1];
const EVP_MD *dgst = NULL;
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
unsigned char salt[PKCS5_SALT_LEN];
const char *password = "3eDc#9ujN";
int i;
BIO *in=NULL;
in=BIO_new(BIO_s_file());
printf("Please specify openssl enc -in arg [file]\n");
{
//argv[1] openssl enc -in
if (BIO_read_filename(in,argv[1]) <= 0)
{
perror(argv[1]);
return;
}
printf("her BIO_read_filename argv[1]=%s \n",argv[1]);
}
printf("her in %p \n",in);
if((BIO_read(in,mbuf,sizeof mbuf) != sizeof mbuf
|| BIO_read(in,
(unsigned char *)salt,
sizeof salt) != sizeof salt)){
perror("read salt error");
return;
}
OpenSSL_add_all_algorithms();
cipher = EVP_get_cipherbyname("aes192");//"aes-192-cbc");
if(!cipher) { fprintf(stderr, "no such cipher\n"); return 1; }
dgst=EVP_get_digestbyname("md5");
if(!dgst) { fprintf(stderr, "no such digest\n"); return 1; }
if(!EVP_BytesToKey(cipher, dgst, salt,
(unsigned char *) password,
strlen(password), 1, key, iv))
{
fprintf(stderr, "EVP_BytesToKey failed\n");
return 1;
}
printf("salt: "); for(i=0; i<PKCS5_SALT_LEN; ++i) { printf("%02x", salt[i]); } printf("\n");
printf("Key: "); for(i=0; i<cipher->key_len; ++i) { printf("%02x", key[i]); } printf("\n");
printf("IV: "); for(i=0; i<cipher->iv_len; ++i) { printf("%02x", iv[i]); } printf("\n");
if (in != NULL) BIO_free(in);
return 0;
}
3,利用key和iv转化openssl命令行成API
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>
#include <stdio.h>
/*
#openssl enc -d -aes192 -pass "pass:3eDc#9ujN" -p -in hfb1062.enc -out a.cpio
salt=28C7761EE45FFB06
key=00297EE7F640FB3545C9466583B9D008A4EB3CF24A4EFF65
iv =F4F137201648930D6BA620806691EF71
*/
int set_hex(char *in, unsigned char *out, int size)
{
int i,n;
unsigned char j;
n=strlen(in);
if (n > (size*2))
{
printf("hex string is too long\n");
return(0);
}
memset(out,0,size);
for (i=0; i<n; i++)
{
j=(unsigned char)*in;
*(in++)='\0';
if (j == 0) break;
if ((j >= '0') && (j <= '9'))
j-='0';
else if ((j >= 'A') && (j <= 'F'))
j=j-'A'+10;
else if ((j >= 'a') && (j <= 'f'))
j=j-'a'+10;
else
{
printf("non-hex digit\n");
return(0);
}
if (i&1)
out[i/2]|=j;
else
out[i/2]=(j<<4);
}
return(1);
}
int do_crypt(FILE *in, FILE *out, int do_encrypt)
{
//do_encrypt:1 for encryption,0 for decryption
char inbuf[1024]={0}, outbuf[1024 + EVP_MAX_BLOCK_LENGTH]={0};
int inlen, outlen;
const char password[] ="3eDc#9ujN";
unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH];
unsigned char salt[PKCS5_SALT_LEN];
char hkey[]="00297EE7F640FB3545C9466583B9D008A4EB3CF24A4EFF65",hiv[]="F4F137201648930D6BA620806691EF71";
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
set_hex(hkey,key,sizeof(key));
set_hex(hiv,iv,sizeof(iv));
/* if (!EVP_BytesToKey(cipher,dgst,salt,(unsigned char *)password,strlen(password),1,key,iv)){
printf("EVP_BytesToKey\n");
}
printf("%s\n",EVP_CIPHER_name(cipher));
printf("%s\n",EVP_MD_name(dgst));
printf("is pass? %s %d\n",password,strlen(password));
int iii=0;
printf("Key: "); for(iii=0; iii<EVP_MAX_KEY_LENGTH; ++iii) { printf(",%d", key[iii]); } printf("\n");
printf("IV: "); for(iii=0; iii<EVP_MAX_IV_LENGTH; ++iii) { printf(",%d", iv[iii]); } printf("\n");
printf("%s\n",EVP_CIPHER_name(cipher));
printf("%s\n",EVP_MD_name(dgst));*/
EVP_CipherInit_ex(&ctx, EVP_aes_192_cbc(), NULL, key, iv, do_encrypt);
for(;;)
{
inlen = fread(inbuf, 1, 1024, in);
if(inlen <= 0) break;
if(!EVP_CipherUpdate(&ctx, outbuf, &outlen, inbuf, inlen))
{
/* Error */
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
fwrite(outbuf, 1, outlen, out);
}
if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen))
{
/* Error */
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
fwrite(outbuf, 1, outlen, out);
EVP_CIPHER_CTX_cleanup(&ctx);
return 1;
}
int main(int argc,char**argv)
{
FILE *in=fopen(argv[1],"r");
FILE *out=fopen(argv[2],"w");
if (NULL ==in){
printf("error fopen\n");
return 0;
}
do_crypt(in,out,atoi(argv[3]));
fclose(in);
fclose(out);
return 0;
}
4,Openssl源码加入debug信息
首先安装:efence
修改openssl-1.0.0的Makefile66行:66 EX_LIBS= -lefence -ldl -lpthread
编译: ./config -d
调试:#gdb openssl
编译: ./config -d
(gdb) r enc -d -aes192 -pass "pass:3eDc#9ujN" -p -in /pub/hf/patch1.enc -out a.cpio
5,完整的code,记得要去掉默认的padding data:
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>
#include <stdio.h>
#include <openssl/bio.h>
/*
#openssl enc -d -aes192 -pass "pass:3eDc#9ujN" -p -in hfb1062.enc -out a.cpio
salt=28C7761EE45FFB06
key=00297EE7F640FB3545C9466583B9D008A4EB3CF24A4EFF65
iv =F4F137201648930D6BA620806691EF71
*/
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
const EVP_CIPHER *cipher=NULL;
int pass2keyiv(char *infile)
{
const char magic[]="Salted__";
char mbuf[sizeof magic-1];
const EVP_MD *dgst = NULL;
unsigned char salt[PKCS5_SALT_LEN];
const char *password = "3eDc#9ujN";
int i;
BIO *in=NULL;
in=BIO_new(BIO_s_file());
printf("Please specify openssl enc -in arg [file]\n");
{
//argv[1] openssl enc -in
if (BIO_read_filename(in,infile) <= 0)
{
perror(infile);
return;
}
printf("her BIO_read_filename argv[1]=%s \n",infile);
}
printf("her in %p \n",in);
if((BIO_read(in,mbuf,sizeof mbuf) != sizeof mbuf
|| BIO_read(in,
(unsigned char *)salt,
sizeof salt) != sizeof salt)){
perror("read salt error");
return;
}
OpenSSL_add_all_algorithms();
cipher = EVP_get_cipherbyname("aes192");//"aes-192-cbc");
if(!cipher) { fprintf(stderr, "no such cipher\n"); return 1; }
dgst=EVP_get_digestbyname("md5");
if(!dgst) { fprintf(stderr, "no such digest\n"); return 1; }
if(!EVP_BytesToKey(cipher, dgst, salt,
(unsigned char *) password,
strlen(password), 1, key, iv))
{
fprintf(stderr, "EVP_BytesToKey failed\n");
return 1;
}
printf("salt: "); for(i=0; i<PKCS5_SALT_LEN; ++i) { printf("%02x", salt[i]); } printf("\n");
printf("Key: "); for(i=0; i<cipher->key_len; ++i) { printf("%02x", key[i]); } printf("\n");
printf("IV: "); for(i=0; i<cipher->iv_len; ++i) { printf("%02x", iv[i]); } printf("\n");
if (in != NULL) BIO_free(in);
return 0;
}
int do_crypt(FILE *in, FILE *out)
{
#define BSIZE (8*1024)
char inbuf[BSIZE]={0}, outbuf[BSIZE + EVP_MAX_BLOCK_LENGTH]={0};
int inlen, outlen;
char * needle =NULL;
char mblock[1024];
int blocksize=0;
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
blocksize = EVP_CIPHER_block_size(cipher);
printf("block size %d\n",blocksize);
fread(mblock,1,blocksize,in);//skip the magic size
//EVP_CIPHER_CTX_set_padding(&ctx, 1);
//do_encrypt:1 for encryption,0 for decryption
EVP_CipherInit_ex(&ctx,cipher, NULL, key, iv, 0);
for(;;)
{
bzero(inbuf,sizeof inbuf);
inlen = fread(inbuf, 1, BSIZE, in);
if(inlen <= 0) break;
bzero(outbuf,sizeof outbuf);
if(!EVP_CipherUpdate(&ctx, outbuf, &outlen, inbuf, inlen))
{
/* Error */
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
fwrite(outbuf, 1, outlen, out);
}
if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen))
{
/* Error */
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
fwrite(outbuf, 1, outlen, out);
EVP_CIPHER_CTX_cleanup(&ctx);
return 1;
}
int main(int argc,char**argv)
{
FILE *in=fopen(argv[1],"rb");
FILE *out=fopen(argv[2],"wb");
if ( argc != 3){
printf("Usage: in_file_to_be_decryped out_file%d\n",argc);
return;
}
if (NULL ==in){
printf("error fopen\n");
return 0;
}
pass2keyiv(argv[1]);
do_crypt(in,out);
fclose(in);
fclose(out);
return 0;
}
参考:
openssl源码openssl-1.0.0/apps/enc.c
linux efence内存调试工具使用:http://blog.sina.com.cn/s/blog_9151e7300101krxh.html
efence下载: http://perens.com/FreeSoftware/ElectricFence/