我使用openssl API替换该命令,但解密的数据头是错误的。为什么?
我使用openssl API替换下面的命令行。但是取消键入的文件头是错误的。有人能帮我吗我使用openssl API替换该命令,但解密的数据头是错误的。为什么?,api,openssl,command,Api,Openssl,Command,我使用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和i
#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;
}
#包括
#包括
#包括
#包括
#包括
无符号字符键[EVP_MAX_key_LENGTH],iv[EVP_MAX_iv_LENGTH];
const EVP_CIPHER*CIPHER=NULL;
int pass2keyiv(字符*填充)
{
const char magic[]=“盐渍”;
char mbuf[sizeof magic-1];
const EVP_MD*dgst=NULL;
未签名的半焦盐[PKCS5_salt_LEN];
const char*password=“3eDc#9ujN”;
int i;
BIO*in=NULL;
in=BIO_new(BIO_s_file());
printf(“请在arg[文件]\n中指定openssl enc-in”);
{
//argv[1]openssl enc-in
如果(BIO_read_filename(in,infle)我有一个类似的问题,我必须用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;
my$salt=substr($data,8,8);
my$ct=substr($data,16);
我的$rounds=3;
我的$data00=$Key.$salt;
我的@md5_散列;
$md5_hash[0]=md5($data00);
我的$result=$md5_散列[0];
对于(我的$i=1;$i<$rounds;$i++){
$md5_散列[$i]=md5($md5_散列[$i-1].$data00);
$result.=$md5_散列[$i];
}
my$key=substr($result,0,24);
my$iv=substr($result,24,8);
我的$m=Crypt::Mode::CFB->new('DES_EDE');
my$plaintext=$m->decrypt($ct,$key,$iv);
返回$plaintext;
对于您的AES
,我相信盐的长度将是16
,因此ct
(密文)将从位置24
开始。我还认为AES使用SHA
而不是MD5
,但我不是100%确定。以下是我的解决方案:我认为我们应该跳过块大小,这是加密时的默认填充
#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 enc-d-aes192-pass“pass:3eDc#9ujN”-p-in-hfb1062.enc-out a.cpio
盐=28C7761EE45FFB06
键=00297EE7F640FB3545C9466583B9D008A4EB3CF24A4EFF65
iv=F4F137201648930D6BA620806691EF71
*/
无符号字符键[EVP_MAX_key_LENGTH],iv[EVP_MAX_iv_LENGTH];
const EVP_CIPHER*CIPHER=NULL;
int pass2keyiv(字符*填充)
{
const char magic[]=“盐渍”;
char mbuf[sizeof magic-1];
const EVP_MD*dgst=NULL;
未签名的半焦盐[PKCS5_salt_LEN];
const char*password=“3eDc#9ujN”;
int i;
BIO*in=NULL;
in=BIO_new(BIO_s_file());
printf(“请在arg[文件]\n中指定openssl enc-in”);
{
//argv[1]openssl enc-in
如果(BIO_read_filename,in,infle)OpenSSL封装数据,而您不这样做,即直接调用函数不会为您封装。如果您查看OpenSSL生成的内容,您会注意到如果我尝试跳过“Salted_”,它的标题为\u Slated
输入文件的大小,但它也是错误的。你不能跳过它,它是一个重要的部分,你需要处理它,在\u Slated
,文件头之后,我想,是16字节的salt,后面是加密的数据。从salt你可以访问IV,然后它将被用来解密数据。你能更详细地描述它吗在解密输入数据时,我跳过了神奇的大小,但也出现了错误。我怀疑您使用了“my$ct=substr($data,16);”跳过盐的大小。我试过你的方法,它成功了。谢谢。块大小是16。所以跳过块大小,而不是盐的大小。听到它起作用很好,贴一个答案和你的解决方案,这样其他人就可以使用它了