Assistance with openssl blowfish simple example inserting garbage characters

心已入冬 提交于 2019-11-29 00:38:07
rsarro

The error is in the way the EVP_DecryptFinal and EVP_EncryptFinal are called. These functions should be called in the end of the for cycle, also the final part where to olen is added tlen and written again was duplicating output. Below is the final working version:

#include <openssl/blowfish.h>
#include <openssl/evp.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#define IP_SIZE 1024
#define OP_SIZE 1024 + EVP_MAX_BLOCK_LENGTH
unsigned char   key[16];
unsigned char   iv[8];

int
generate_key()
{
    int             i, fd;
    if ((fd = open("/dev/random", O_RDONLY)) == -1)
        perror("open error");

    if ((read(fd, key, 16)) == -1)
        perror("read key error");

    if ((read(fd, iv, 8)) == -1)
        perror("read iv error");

    printf("128 bit key:\n");
    for (i = 0; i < 16; i++)
        printf("%4d ", key[i]);

    printf("\nInitialization vector\n");
    for (i = 0; i < 8; i++)
        printf("%4d ", iv[i]);
    printf("\n");


    close(fd);
    return 0;
}

int
do_decrypt(int infd, int outfd)
{
    unsigned char           *inbuff, *outbuf;
    int             olen=0, tlen=0, n=0;
    EVP_CIPHER_CTX  ctx;
    EVP_CIPHER_CTX_init(&ctx);
    EVP_DecryptInit(&ctx, EVP_bf_cbc(), key, iv);

    outbuf = (unsigned char *) malloc(sizeof(unsigned char) * OP_SIZE);
    inbuff = (unsigned char *) malloc(sizeof(unsigned char) * IP_SIZE);

    /* keep reading until a break */
    for (;;) {
        memset(inbuff, 0, IP_SIZE);
        if ((n = read(infd, inbuff, IP_SIZE)) == -1) {
            perror("read error");
            break;
        } else if (n == 0)
            break;

        memset(outbuf, 0, OP_SIZE);

        if (EVP_DecryptUpdate(&ctx, outbuf, &olen, inbuff, n) != 1) {
            printf("error in decrypt update\n");
            return 0;
        }
        if ((n = write(outfd, outbuf, olen)) == -1)
            perror("write error");
    }

    tlen=0;
    if (EVP_DecryptFinal(&ctx, outbuf + olen, &tlen) != 1) {
        perror("error in decrypt final");
        return 0;
    }

    if ((n = write(outfd, outbuf+olen, tlen)) == -1)
        perror("write error");

    EVP_CIPHER_CTX_cleanup(&ctx);
    return 1;
}

int
do_encrypt(int infd, int outfd)
{
    unsigned char           *inbuff, *outbuf;

    int             olen=0, tlen=0, n=0;
    EVP_CIPHER_CTX  ctx;
    EVP_CIPHER_CTX_init(&ctx);
    EVP_EncryptInit(&ctx, EVP_bf_cbc(), key, iv);

    outbuf = (unsigned char *) malloc(sizeof(unsigned char) * OP_SIZE);
    inbuff = (unsigned char *) malloc(sizeof(unsigned char) * IP_SIZE);

    for (;;) {
        memset(inbuff, 0, IP_SIZE);

        if ((n = read(infd, inbuff, IP_SIZE)) == -1) {
            perror("read error");
            break;
        } else if (n == 0)
            break;

        if (EVP_EncryptUpdate(&ctx, outbuf, &olen, inbuff, n) != 1) {
            printf("error in encrypt update\n");
            return 0;
        }

        if ((n = write(outfd, outbuf, olen)) == -1)
            perror("write error");
    }
    tlen=0;
    if (EVP_EncryptFinal(&ctx, outbuf + olen, &tlen) != 1) {
        printf("error in encrypt final\n");
        return 0;
    }

    if ((n = write(outfd, outbuf+olen, tlen)) == -1)
        perror("write error");

    EVP_CIPHER_CTX_cleanup(&ctx);
    return 1;
}

int
main(int argc, char *argv[])
{
    int             flags1 = 0, flags2 = 0, outfd, infd;
    mode_t          mode;

    memset(key, 0, 16);
    memset(iv, 0, 8);
    memset(&mode, 0, sizeof(mode));

    flags1 = flags1 | O_RDONLY;
    flags2 = flags2 | O_RDONLY;
    flags2 = flags2 | O_WRONLY;
    flags2 = flags2 | O_CREAT;

    mode = mode | S_IRUSR;
    mode = mode | S_IWUSR;


    generate_key();


    if ((infd = open(argv[1], flags1, mode)) == -1)
        perror("open input file error");

    if ((outfd = open(argv[2], flags2, mode)) == -1)
        perror("open output file error");

    do_encrypt(infd, outfd);

    close(infd);
    fsync(outfd);
    close(outfd);

    if ((infd = open(argv[2], flags1, mode)) == -1)
        perror("open output file error");

    if ((outfd = open(argv[3], flags2, mode)) == -1)
        perror("open output file error");

    do_decrypt(infd, outfd);

    close(infd);
    fsync(infd);
    close(outfd);

    return 0;
}

Since you say the error seems to be coming at the decryption stage, I would look with suspicion on these lines:

if (EVP_DecryptUpdate (&ctx, outbuf, &olen, inbuff, n) != 1)
...

if (EVP_DecryptFinal (&ctx, outbuf + olen, &tlen) != 1)
...

How big is the memory allocated for outbuf in relation to what the decryption functions will be putting in them? Are you sure outbuf + olen is not going to take you past the end of the buffer?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!