如何解密使用 cbc_encrypt (Linux GCC) 加密的内容

How do I decrypt something encrypted with cbc_encrypt (Linux GCC)

我想基于我在 perl 中所做的事情,在 C 中编写一个加密/解密程序。编译后的 perl 程序是 2MB,所以我想如果我用 C 编写它,它的可执行文件大小会更小。

我的问题是,当我对其进行加密时,我无法对其进行解密。自从我上次使用 C 以来已经过去了很多年,所以我忘记了很多东西。有人请告诉我我在这里做错了什么?谢谢

/*
    ============================================================================
    Name        : test-c.c
    Description : Testing Project
                  Trying to do a C version of this perl code:
                    my $cipher = Crypt::CBC->new( -key => $salt_key, -cipher => 'DES' -header => 'none');
                    my $enc_text = $cipher->encrypt_hex($text);
    Requires    : -lcrypt
    References  :
      Function: cbc_crypt (char *key, char *blocks, unsigned len, unsigned mode, char *ivec)
      GNU C Library: DES Encryption (http://www.gnu.org/software/libc/manual/html_node/DES-Encryption.html#DES-Encryption)
      cbc_crypt (http://unix.derkeiler.com/Newsgroups/comp.unix.programmer/2012-10/msg00023.html)
    ============================================================================
    */

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <rpc/des_crypt.h>

    int main(void) {
        char key[]     = "aBcDeFg1";
        char pass[]    = "mypass1234test";
        char encbuff[] = "87654321";
        char decbuff[] = "87645321";
        int buffsize;
        int result;

        des_setparity(key);

        /* Encrypt pass, result is in encbuff */
        buffsize = sizeof(pass);
        /* Add to pass to ensure size is divisable by 8. */
        while (buffsize % 8) {
            pass[buffsize++] = '[=12=]';
        }

        printf("Encrypted: ");
        result = cbc_crypt(key, pass, buffsize, DES_ENCRYPT | DES_SW, encbuff);
        if (DES_FAILED(result) || strcmp(encbuff, "") == 0) {
            if(strcmp(encbuff, "") == 0) {
                printf("*** Null Output ***\n");
            } else {
                printf("*** Encryption Error ***\n");
            }
        } else {
            printf("%s\n", encbuff);
        }

        /* Decrypt encbuff, result is in decbuff */

        /* FIXME: Decryption doesn't work:
            Encrypted: ,�7&���8
            Decrypted: *** Decryption Error ***
        */
        buffsize = sizeof(encbuff);
        /* Add to pass to ensure size is divisable by 8. */
        while (buffsize % 8) {
            encbuff[buffsize++] = '[=12=]';
        }

        printf("Decrypted: ");
        result = cbc_crypt(key, encbuff, buffsize, DES_DECRYPT | DES_SW, decbuff);
        if(DES_FAILED(result) || strcmp(decbuff, "") == 0) {
            if(strcmp(encbuff, "") == 0) {
                printf("*** Null Output ***\n");
            } else {
                printf("*** Decryption Error ***\n");
            }
        } else {
            printf("%s\n", decbuff);
        }

        return 0;
    }

正如@Brian_Sidebotham 所注意到的,在 c 语言中使用 char str[10];buffsize=sizeof(str);...str[buffsize++]='[=12=]' 并不是一件好事。超出数组末尾的写入可能会触发未定义的行为。它可能会工作或提供错误的结果或由于分段错误而停止。所以首先要做的是使用更大的缓冲区。例如:

char key[9];
sprintf(key,"12345678");

char password[420];
sprintf(password,"i am not going to write my password here.");

请注意,它是 9,而不是 8,为 sprintf() 自动添加的空终止字符 [=13=] 留出一些位置,以构建有效的 c 字符串。

另外,cbc_crypt()的最后一个参数不是输出。它不是加密字符串,而是用于链接的 8 字节初始化向量。这样,如果您需要加密多个字符串,它可以防止明文中的规律性出现在密文中。由于要解密密文,因此必须提供相同的初始化向量。加密就地执行:输入字符串 pass 将被加密文本覆盖。

最后,确保您的字符串足够大,因为加密文本似乎比明文稍大。

下面的代码应该可以工作。它由 gcc main.c -o main

编译
/*
    ============================================================================
    Name        : test-c.c
    Description : Testing Project
                  Trying to do a C version of this perl code:
                    my $cipher = Crypt::CBC->new( -key => $salt_key, -cipher => 'DES' -header => 'none');
                    my $enc_text = $cipher->encrypt_hex($text);
    Requires    : -lcrypt
    References  :
      Function: cbc_crypt (char *key, char *blocks, unsigned len, unsigned mode, char *ivec)
      GNU C Library: DES Encryption (http://www.gnu.org/software/libc/manual/html_node/DES-Encryption.html#DES-Encryption)
      cbc_crypt (http://unix.derkeiler.com/Newsgroups/comp.unix.programmer/2012-10/msg00023.html)
    ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/des_crypt.h>

#define BUFFSIZE 420
int main(void) {
    //  char key[]     = "aBcDeFg1";
    char key[9];
    sprintf(key,"aBcDeFg1");
    //char pass[]    = "mypass1234test";
    char pass[BUFFSIZE];
    sprintf(pass,"mypass1234test");

    //  char encbuff[] = "87654321";
    char ivec[9];
    sprintf(ivec,"87654321");
    //  char decbuff[] = "87645321";
    char ivectemp[9];
    strcpy(ivectemp,ivec);
    int buffsize;
    int result;

    des_setparity(key);

    /* Encrypt pass, result is in encbuff */
    buffsize = strlen(pass);
    printf("buffsize is %d\n",buffsize);
    /* Add to pass to ensure size is divisable by 8. */
    while (buffsize % 8 && buffsize<BUFFSIZE) {
        pass[buffsize++] = '[=11=]';
    }
    printf("pass is %s\n",pass);
    printf("buffsize is %d\n",buffsize);
    printf("Encrypted: ");
    result = cbc_crypt(key, pass, buffsize, DES_ENCRYPT | DES_SW, ivectemp);
    if (DES_FAILED(result) || strcmp(pass, "") == 0) {
        if(strcmp(pass, "") == 0) {
            printf("*** Null Output ***\n");
        } else {
            printf("*** Encryption Error ***\n");
        }
    } else {
        printf("%s\n", pass);
    }

    /* Decrypt encbuff, result is in decbuff */

    /* FIXME: Decryption doesn't work:
            Encrypted: ,�7&���8
            Decrypted: *** Decryption Error ***
     */
    buffsize = strlen(pass);
    printf("buffsize is %d\n",buffsize);
    /* Add to pass to ensure size is divisable by 8. */
    while (buffsize % 8 && buffsize<BUFFSIZE) {
        pass[buffsize++] = '[=11=]';
    }
    printf("buffsize is %d\n",buffsize);
    printf("Decrypted: ");
    //keeping the same initialization vector for decrypting, encrypt has altered ivectemp
    strcpy(ivectemp,ivec);
    result = cbc_crypt(key, pass, buffsize, DES_DECRYPT | DES_SW, ivectemp);
    if(DES_FAILED(result) || strcmp(pass, "") == 0) {
        if(strcmp(pass, "") == 0) {
            printf("*** Null Output ***\n");
        } else {
            printf("*** Decryption Error ***\n");
        }
    } else {
        printf("%s\n",pass);
    }

    return 0;
}

现在......关于安全的几句话......根据wikipedia page about the Data Encryption Standard NBS DES

DES is now considered to be insecure for many applications. This is mainly due to the 56-bit key size being too small; in January, 1999, distributed.net and the Electronic Frontier Foundation collaborated to publicly break a DES key in 22 hours and 15 minutes

例如,您可以切换到 AES by the openssl library for instance. See How to do encryption using AES in Openssl or Simple AES encryption decryption with openssl library in C or AES (aes-cbc-128, aes-cbc-192, aes-cbc-256) encryption/decryption with openssl C 的实现。