我使用openssl API替换下面的命令行。但是解密的文件头是错误的。有人可以帮帮我吗?
#openssl enc -d -aes192 -pass "pass:3eDc#9ujN" -p -in hfb1062.enc -out a.cpio
salt=28C7761EE45FFB06
key=00297EE7F640FB3545C9466583B9D008A4EB3CF24A4EFF65
iv =F4F137201648930D6BA620806691EF71
salf,key和iv与openssl命令行输出相同。 以下是实现about openssl命令行的代码:
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>
#include <stdio.h>
#include <openssl/bio.h>
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");
return 0;
}
int do_crypt(FILE *in, FILE *out)
{
#define BSIZE (8*1024)
char inbuf[BSIZE]={0}, outbuf[BSIZE + EVP_MAX_BLOCK_LENGTH]={0};
const char magic[]="Salted__";
char mbuf[sizeof magic-1];
int inlen, outlen;
char * needle =NULL;
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
if(fread(mbuf,1,sizeof mbuf,in) != sizeof mbuf)//If I skip the magic size or remove this code line, the decryped data is also wrong.
printf("bad magic number\n");
printf("Magic number %s\n",mbuf);
//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;
}
答案 0 :(得分:0)
我有类似的问题,对我来说,我必须在perl脚本中解决它,你可以很容易地将它变成Java。
注意我正在使用DES,因此盐的大小和位置与您的不同。我还使用DES_EDE
,您需要使用AES
my $salt = substr($data, 8, 8);
my $ct = substr($data, 16);
my $rounds = 3;
my $data00 = $Key.$salt;
my @md5_hash;
$md5_hash[0] = md5($data00);
my $result = $md5_hash[0];
for (my $i = 1; $i < $rounds; $i++) {
$md5_hash[$i] = md5($md5_hash[$i - 1].$data00);
$result .= $md5_hash[$i];
}
my $key = substr($result, 0, 24);
my $iv = substr($result, 24, 8);
my $m = Crypt::Mode::CFB->new('DES_EDE');
my $plaintext = $m->decrypt($ct, $key, $iv);
return $plaintext;
对于AES
,我认为盐的长度为16
,因此ct
(密文)将从位置24
开始。我还认为AES使用的是SHA
而不是MD5
,但我对此并不是100%肯定。
答案 1 :(得分:0)
这是我的解决方案:我认为我们应该跳过一个块大小,这是加密时的默认填充。
#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;
}