我在使用openssl获取两个加密和解密邮件的程序时遇到了一些麻烦。这两个程序编译运行正常,但解密似乎只解密了我的plaintext.txt文件的前7个字符。
在进行文件加密和解密之后从命令行调用...
./ enc -i plaintext.txt -o cipher.txt -p password
./ dec i- cipher.txt -o decrypt.txt -p password
plaintext.txt输入是...... 这是保守秘密的事情
decrypt.txt输出是...... 这是}?w,
这是enc.c(加密)
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
/* AES-GCM test data from NIST public test vectors */
static const unsigned char gcm_iv[] = {
0x99, 0xaa, 0x3e, 0x68, 0xed, 0x81, 0x73, 0xa0, 0xee, 0xd0, 0x66, 0x84
};
unsigned char * aes_gcm_encrypt(unsigned char *pt, long size, unsigned char *myCipher, unsigned char *out)
{
EVP_CIPHER_CTX *ctx;
int outlen, tmplen;
unsigned char outbuf[1024];
// printf("AES GCM Encrypt:\n");
// printf("Plaintext:\n");
// BIO_dump_fp(stdout, pt, size);
ctx = EVP_CIPHER_CTX_new();
/* Set cipher type and mode */
EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
/* Set IV length if default 96 bits is not appropriate */
// EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, sizeof(out), NULL);
/* Initialise key and IV */
EVP_EncryptInit_ex(ctx, NULL, NULL, out, gcm_iv);
/* Encrypt plaintext */
EVP_EncryptUpdate(ctx, outbuf, &outlen, pt, sizeof(pt));
/* Output encrypted block */
// printf("Ciphertext:\n");
// BIO_dump_fp(stdout, outbuf, size);
/* Finalise: note get no output for GCM */
EVP_EncryptFinal_ex(ctx, outbuf, &outlen);
EVP_CIPHER_CTX_free(ctx);
return myCipher = outbuf;
}
extern int errno;
int main(int argc, char **argv)
{
int ITERATION = 10000;
FILE * fp;
int errnum;
long size;
unsigned char *pass;
int len;
pass = argv[6];
fp = fopen(argv[2], "a+");
if (fp == NULL)
{
errnum = errno;
fprintf(stderr, "Value of errno: %d\n", errno);
perror("error printed by perror");
fprintf(stderr, "Error opening the file: %s\n", strerror(errnum));
}
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
unsigned char * buff;
buff = (unsigned char*) malloc(sizeof(unsigned char)*size + 1);
memset(buff, '\0', sizeof(unsigned char)*size + 1);
fread(buff, 1, size, fp);
int SHA1_LEN = 30;
unsigned char* out = (unsigned char*)calloc(SHA1_LEN, sizeof(unsigned char));
//int SALT_LEN = 5;
//RAND_bytes(salt, SALT_LEN);
pass = argv[6];
printf("Test print of pass: %s\n", pass);
PKCS5_PBKDF2_HMAC_SHA1(pass, strlen(pass), NULL, 0, ITERATION, SHA1_LEN, out);
printf("PASSWORD ENCRYPT: ");
printf("%s\n", out);
unsigned char *myCipher;
myCipher = aes_gcm_encrypt(buff, size, myCipher, out);
//printf("%s\n", myCipher);
fclose(fp);
fp = fopen(argv[4], "w+");
if (fp == NULL)
{
errnum = errno;
fprintf(stderr, "Value of errno: %d\n", errno);
perror("error printed by perror");
fprintf(stderr, "Error opening the file: %s\n", strerror(errnum));
}
fputs(myCipher, fp);
printf("CIPHER TEXT: %s\n", myCipher);
printf("\n");
fclose(fp);
return 0;
}
这是dec.c(解密)
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
static const unsigned char gcm_iv[] = {
0x99, 0xaa, 0x3e, 0x68, 0xed, 0x81, 0x73, 0xa0, 0xee, 0xd0, 0x66, 0x84
};
unsigned char * aes_gcm_decrypt(unsigned char *pt, long size, unsigned char *myPlainText, unsigned char *out)
{
EVP_CIPHER_CTX *ctx;
int outlen, tmplen, rv;
unsigned char outbuf[1024];
//printf("AES GCM Derypt:\n");
//printf("Ciphertext:\n");
//BIO_dump_fp(stdout, pt, size);
ctx = EVP_CIPHER_CTX_new();
/* Select cipher */
EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
/* Set IV length, omit for 96 bits */
// EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, sizeof(gcm_iv), NULL);
/* Specify key and IV */
EVP_DecryptInit_ex(ctx, NULL, NULL, out, gcm_iv);
/* Decrypt plaintext */
EVP_DecryptUpdate(ctx, outbuf, &outlen, pt, sizeof(pt));
/* Output decrypted block */
// printf("Plaintext:\n");
//BIO_dump_fp(stdout, outbuf, size);
rv = EVP_DecryptFinal_ex(ctx, outbuf, &outlen);
EVP_CIPHER_CTX_free(ctx);
return myPlainText = outbuf;
}
extern int errno;
int main(int argc, char **argv)
{
int ITERATION = 10000;
FILE * fp;
int errnum;
long size;
unsigned char *pass;
int len;
pass = argv[6];
fp = fopen(argv[2], "a+");
if (fp == NULL)
{
errnum = errno;
fprintf(stderr, "Value of errno: %d\n", errno);
perror("error printed by perror");
fprintf(stderr, "Error opening the file: %s\n", strerror(errnum));
}
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
unsigned char * buff;
buff = (unsigned char*) malloc(sizeof(unsigned char)*size + 1);
memset(buff, '\0', sizeof(unsigned char)*size + 1);
fread(buff, 1, size, fp);
int SHA1_LEN = 30;
unsigned char* out = (unsigned char*)calloc(SHA1_LEN, sizeof(unsigned char));
pass = argv[6];
printf("Test print of pass: %s\n", pass);
PKCS5_PBKDF2_HMAC_SHA1(pass, strlen(pass), NULL, 0, ITERATION, SHA1_LEN, out);
printf("PASSWORD ENCRYPT: ");
printf("%s\n", out);
unsigned char *myPlainText;
myPlainText = aes_gcm_decrypt(buff, size, myPlainText, out);
fclose(fp);
fp = fopen(argv[4], "w+");
if (fp == NULL)
{
errnum = errno;
fprintf(stderr, "Value of errno: %d\n", errno);
perror("error printed by perror");
fprintf(stderr, "Error opening the file: %s\n", strerror(errnum));
}
fputs(myPlainText, fp);
printf("PLAINTEXT: %s\n", myPlainText);
printf("\n");
fclose(fp);
return 0;
}
答案 0 :(得分:1)
如果没有ssl的详细知识,我的猜测是这些调用
EVP_EncryptUpdate(ctx, outbuf, &outlen, pt, sizeof(pt));
EVP_DecryptUpdate(ctx, outbuf, &outlen, pt, sizeof(pt));
应该具有pt指向的大小而不是指针的大小。
EVP_EncryptUpdate(ctx, outbuf, &outlen, pt, ptlen);
EVP_DecryptUpdate(ctx, outbuf, &outlen, pt, ptlen);
其中ptlen是缓冲区pt指向的大小。
看openssl manual证实了我的猜测:
EVP_EncryptUpdate()从缓冲区加密inl字节,并将加密版本写入out。可以多次调用此函数来加密连续的数据块。写入的数据量取决于加密数据的块对齐:因此写入的数据量可以是从零字节到(inl + cipher_block_size - 1)的任何值,因此out应包含足够的空间。写入的实际字节数放在outl。
中EVP_DecryptInit_ex(),EVP_DecryptUpdate()和EVP_DecryptFinal_ex()是相应的解密操作。如果启用填充并且最终块未正确格式化,则EVP_DecryptFinal()将返回错误代码。参数和限制与加密操作相同,除了如果启用填充,传递给EVP_DecryptUpdate()的解密数据缓冲区应该有足够的空间用于(inl + cipher_block_size)字节,除非密码块大小为1,在这种情况下inl字节是sufficien