簡體   English   中英

我該如何解碼(Perl cbc-crypt到C cbc_crypt的轉換)

[英]How do I get this to decode (Perl cbc-crypt to C cbc_crypt conversion)

我試圖能夠解碼使用perl腳本編碼的編碼字符串。 我不能僅僅更改perl腳本的原因是因為已經存在許多重要的數據,這些數據是通過perl腳本保存的,因此在perl中進行解碼並以另一種方式重新編碼將非常繁瑣。 僅將內容保留在適當位置(現在)更容易。 但是,編譯后的perl代碼為2MB。 我想用C編寫它,因此可執行文件的大小會更小。

到目前為止,我所擁有的如下。 它不會工作。 它基本上給了我垃圾輸出。 我認為問題是perl腳本使用了基於十六進制的加密。 我該如何解碼呢? 有人可以指出我出問題的地方嗎?

/*
Test to decode perl-encrypted string.
NOTE: Not all code written by me. Function code is either written by or derived
      from code from other people in response to similar questions found on the
      internet.

Required Lib: crypt (-lcrypt)

Perl Code from existing script (that is being converted to C):

    use Crypt::CBC;
    use Crypt::DES;
    my $text = "thisisalongtest";
    my $salt_key = "fOagmJOKu2SF";
    my $cipher = Crypt::CBC->new( -key => $salt_key, -cipher => 'DES' -header => 'none');
    my $enc_text = $cipher->encrypt_hex($text);
Perl crypt functions require libcrypt-cbc-perl & libcrypt-des-perl

Data:

Original Text: thisisalongtest
Salt Key: fOagmJOKu2SF
Resulting Encrypted String: 53616c7465645f5f167ebac84042fe7ceac836e1d3e7d3aa1dfc27e0e8cad0f1

Resulting output:

Decrypted: (unprintable junk characters)
*/

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

#define BUFFSIZE 420

int encrypt(char key[9], char salt[9], char pass[BUFFSIZE], int mode);
void enc_from_hex(const char* st, char ret_result[BUFFSIZE]);
int hex_to_int(char c);
int hex_to_ascii(char c, char d);

int main (int argc, char *argv[]) {

    int err;
    char passwd[BUFFSIZE];
    char result[BUFFSIZE];
    char key[13];

    sprintf(key,"fOagmJOKu2SF");

    /* Change this from hex pairs to ASCII */
    sprintf(passwd, "53616c7465645f5f167ebac84042fe7ceac836e1d3e7d3aa1dfc27e0e8cad0f1");
    enc_from_hex(passwd, result);

    /* Decrypt */
    err = encrypt(key, "", result, 1); /* DO NOT use 'NULL' for 2nd parameter! */
    if(err != 0) {
        printf("Error.\n");
    } else {
        printf("Decrypted: %s\n", result);
    }

    return 0;
}

/* Encryption */
int encrypt(char key[13], char salt[13], char pass[BUFFSIZE], int mode){
    char temp[13];
    strcpy(temp, salt);
    int buffsize;
    int errcode;

    des_setparity(key);
    buffsize = strlen(pass);

    /* Pad pass to ensure size is divisable by 8.*/
    while (buffsize % 8 && buffsize<BUFFSIZE) {
        pass[buffsize++] = '\0';
    }

    /* Determine Function */
    if(mode == 1) {
        errcode = cbc_crypt(key, pass, buffsize, DES_DECRYPT | DES_SW, temp);
    } else {
        errcode = cbc_crypt(key, pass, buffsize, DES_ENCRYPT | DES_SW, temp);
    }

    if (DES_FAILED(errcode) || strcmp(pass, "") == 0) {
        return errcode;
    }

    return errcode;
}

/* Hex conversion functions */
void enc_from_hex(const char* st, char ret_result[BUFFSIZE]) {
    char temp[2];

    int length = strlen(st);
    int i;
    char buf = 0;
    for(i = 0; i < length; i++) {
        if(i % 2 != 0) {
            sprintf(temp, "%c", hex_to_ascii(buf, st[i]));
            strcat(ret_result, temp);
        } else {
            buf = st[i];
        }
    }

}

int hex_to_int(char c) {
    int first = c / 16 - 3;
    int second = c % 16;
    int result = first*10 + second;
    if(result > 9) result--;
    return result;
}

int hex_to_ascii(char c, char d) {
    int high = hex_to_int(c) * 16;
    int low = hex_to_int(d);
    return high+low;
}

正如@ikegami在評論中指出的那樣,傳遞給密鑰Crypt :: CBC的值並不是真正的密鑰。 該值傳遞給另一個函數,該函數將其與隨機鹽組合,然后對其進行哈希處理以生成實鍵和初始化向量。 隨機鹽會與密文一起保存,其想法是,如果使用相同的密鑰多次加密相同的數據,則每次輸出都會有所不同。

如果將加密的字符串轉換為ascii,您會注意到前8個字符拼寫為Salted__ ,這與OpenSSL使用的格式相對應。

請參閱以下使用OpenSSL的EVP API的粗略示例:

//
// compile with: gcc -o crypt crypt.c -lssl -lcrypto
//
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>

int main(int argc, char *argv[]){
  char pass[]="fOagmJOKu2SF";
  char text[]="53616c7465645f5f167ebac84042fe7ceac836e1d3e7d3aa1dfc27e0e8cad0f1";

  int i = 0;
  char *pos=text;
  while(*pos){ // converts hex string to binary in place
    sscanf(pos, "%2hhx", &text[i++]);
    pos += 2;
  } text[i]=0;

  EVP_CIPHER_CTX ctx;
  unsigned char key[8] = {0};
  unsigned char  iv[8] = {0};

  int len;
  char *clear = malloc(strlen(text)); 

  //                                             v-> First Charicter after 'Salted__' 
  EVP_BytesToKey(EVP_des_cbc(), EVP_md5(), &text[8], pass, strlen(pass), 1, key, iv);

  EVP_DecryptInit(&ctx, EVP_des_cbc(), key, iv);
  //                                          v-> Cypertext starts after salt
  EVP_DecryptUpdate(&ctx, clear, &len, &text[16], strlen(text)-15);
  EVP_DecryptFinal(&ctx, clear, &len);

  printf("%s\n", clear);
  return 0;
}

http://www.ict.griffith.edu.au/anthony/info/crypto/openssl.hints https://www.openssl.org/docs/manmaster/crypto/EVP_BytesToKey.html https://www.openssl。組織/文檔/ manmaster /密碼/ EVP_EncryptInit.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM