OpenSSL加密/解密只解密前7个左右的字符?

时间:2016-04-30 06:14:31

标签: c openssl passwords

我在使用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;
}

1 个答案:

答案 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