2016-03-06 91 views
0

我想用不同的密鑰大小使用openssl的AES_decrypt函數解密密文。我能夠成功與關鍵尺寸解密消息= 128 這裏是我的代碼AES 192,AES-256,不適用於AES-128位的分段錯誤

mydecrypt.c

#include <stdio.h> 
#include "AES.h" 
#include "string.h" 
#include "stdlib.h" 

#define NO_OF_DECRYPTION 50 

static const unsigned char key[]={ 
0x8E,0xa1,0xeE,0xce,0x5F,0xEB,0x1E,0x8d,0xa5,0xdA,0x95,0x57,0xD0,0x77,0xee,0xd8,0x49,0xfc,0xBd,0x2d,0x0D,0xF0,0x40,0x35,0xd3,0xd8,0x07,0x8f,0xce,0xFD,0x24,0xaF 
};  

int main(int argc, char *argv[]) 
{ 
    unsigned char *text = (unsigned char *)malloc(16*sizeof(char));; 
    unsigned char out[20]; 
    unsigned char * input = (unsigned char *)malloc(NO_OF_DECRYPTION*16*sizeof(char)); 

    FILE *myfile; 
    myfile = fopen("encrypted.bin", "r"); 
    fread(input, sizeof(char), NO_OF_DECRYPTION*16, myfile); 

    AES_KEY wctx; 
    int aes_counter=0; 
    private_AES_set_decrypt_key(key, 128, &wctx); // keysize = 192, 256 causes segmentation fault 
    printf("AES Decryption started\n");  

    while(aes_counter<NO_OF_DECRYPTION) 
    { 
     text = &input[aes_counter*16]; 
     AES_decrypt(text, out, &wctx); 
     aes_counter++; 
    } 
    printf("AES Decryption finished\n");   
    fclose(myfile); 

return 0; 
} 

我抄aes_core.c(更名爲AES.c),aes.h(重命名爲AES.h)的openssl文件,並創建了我自己的共享庫來運行上面的代碼。

//AES.h

#include <stdint.h> 

#ifndef AES_h__ 
#define AES_h__ 

typedef uint8_t  u8; 
typedef uint16_t u16; 
typedef uint32_t u32; 

struct aes_key_st { 
    unsigned int rd_key[4 *(10 + 1)]; 
    int rounds; 
}; 
typedef struct aes_key_st AES_KEY; 

extern int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key); 
extern void AES_decrypt(const unsigned char *in, unsigned char *out,const AES_KEY *key); 

#endif // foo_h__ 

下面是我編我的代碼,以成功爲密鑰長度= 128位運行。

gcc -c -Wall -Werror -fPIC -O0 AES.c 
gcc -shared -o libAES.so AES.o 
var=`pwd` 
gcc -std=gnu89 -g -L$var -O0 -Wall -o dec mydecrypt.c -lAES -fPIC 
LD_LIBRARY_PATH=$var:$LD_LIBRARY_PATH 
export LD_LIBRARY_PATH=$var:$LD_LIBRARY_PATH 
#run 
./dec 

雖然我能爲其他密鑰大小192和256明文加密,並使用與AES_KEY = key_size 128密文進行解密,但是我得到段錯誤。

private_AES_set_decrypt_key(key, 192, &wctx);部未產生分段故障

然而,private_AES_set_decrypt_key(key, 256, &wctx);正生成段故障

對於這兩種關鍵尺寸= 192和密鑰大小= 256, AES_decrypt()正在生成分割故障

分段故障的原因是什麼,大小192和256?

我在哪裏犯錯誤?

任何建議/線索運行代碼解密使用key-size = 192/256將是很大的幫助。

我在Debian 8中使用gcc-4.9.2。提前致謝。

注: 對於加密,與關鍵尺寸= 128

AES_set_encrypt_key((const unsigned char *)key, 128, &enc_key); 

不會引起任何段錯誤,然而

AES_set_encrypt_key((const unsigned char *)key, 192, &enc_key); 
AES_set_encrypt_key((const unsigned char *)key, 256, &enc_key); 

既導致段故障。 AES.c的

部分其中private_AES_set_decrypt_key和private_AES_set_encrypt_key定義

/** 
* Expand the cipher key into the encryption key schedule. 
*/ 
int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits, 
           AES_KEY *key) 
{ 
    u32 *rk; 
    int i = 0; 
    u32 temp; 

    if (!userKey || !key) 
     return -1; 
    if (bits != 128 && bits != 192 && bits != 256) 
     return -2; 

    rk = key->rd_key; 

    if (bits==128) 
     key->rounds = 10; 
    else if (bits==192) 
     key->rounds = 12; 
    else 
     key->rounds = 14; 

    rk[0] = GETU32(userKey ); 
    rk[1] = GETU32(userKey + 4); 
    rk[2] = GETU32(userKey + 8); 
    rk[3] = GETU32(userKey + 12); 
    if (bits == 128) { 
     while (1) { 
      temp = rk[3]; 
      rk[4] = rk[0]^
       ((u32)Te4[(temp >> 16) & 0xff] << 24)^
       ((u32)Te4[(temp >> 8) & 0xff] << 16)^
       ((u32)Te4[(temp  ) & 0xff] << 8)^
       ((u32)Te4[(temp >> 24)  ])^
       rcon[i]; 
      rk[5] = rk[1]^rk[4]; 
      rk[6] = rk[2]^rk[5]; 
      rk[7] = rk[3]^rk[6]; 
      if (++i == 10) { 
       return 0; 
      } 
      rk += 4; 
     } 
    } 
    rk[4] = GETU32(userKey + 16); 
    rk[5] = GETU32(userKey + 20); 
    if (bits == 192) { 
     while (1) { 
      temp = rk[ 5]; 
      rk[ 6] = rk[ 0]^
       ((u32)Te4[(temp >> 16) & 0xff] << 24)^
       ((u32)Te4[(temp >> 8) & 0xff] << 16)^
       ((u32)Te4[(temp  ) & 0xff] << 8)^
       ((u32)Te4[(temp >> 24)  ])^
       rcon[i]; 
      rk[ 7] = rk[ 1]^rk[ 6]; 
      rk[ 8] = rk[ 2]^rk[ 7]; 
      rk[ 9] = rk[ 3]^rk[ 8]; 
      if (++i == 8) { 
       return 0; 
      } 
      rk[10] = rk[ 4]^rk[ 9]; 
      rk[11] = rk[ 5]^rk[10]; 
      rk += 6; 
     } 
    } 
    rk[6] = GETU32(userKey + 24); 
    rk[7] = GETU32(userKey + 28); 
    if (bits == 256) { 
     while (1) { 
      temp = rk[ 7]; 
      rk[ 8] = rk[ 0]^
       ((u32)Te4[(temp >> 16) & 0xff] << 24)^
       ((u32)Te4[(temp >> 8) & 0xff] << 16)^
       ((u32)Te4[(temp  ) & 0xff] << 8)^
       ((u32)Te4[(temp >> 24)  ])^
       rcon[i]; 
      rk[ 9] = rk[ 1]^rk[ 8]; 
      rk[10] = rk[ 2]^rk[ 9]; 
      rk[11] = rk[ 3]^rk[10]; 
      if (++i == 7) { 
       return 0; 
      } 
      temp = rk[11]; 
      rk[12] = rk[ 4]^
       ((u32)Te4[(temp >> 24)  ] << 24)^
       ((u32)Te4[(temp >> 16) & 0xff] << 16)^
       ((u32)Te4[(temp >> 8) & 0xff] << 8)^
       ((u32)Te4[(temp  ) & 0xff]); 
      rk[13] = rk[ 5]^rk[12]; 
      rk[14] = rk[ 6]^rk[13]; 
      rk[15] = rk[ 7]^rk[14]; 

      rk += 8; 
     } 
    } 
    return 0; 
} 

/** 
* Expand the cipher key into the decryption key schedule. 
*/ 
int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits, 
           AES_KEY *key) 
{ 

    u32 *rk; 
    int i, j, status; 
    u32 temp; 

    /* first, start with an encryption schedule */ 
    status = private_AES_set_encrypt_key(userKey, bits, key); 
    if (status < 0) 
     return status; 

    rk = key->rd_key; 

    /* invert the order of the round keys: */ 
    for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) { 
     temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; 
     temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; 
     temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; 
     temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; 
    } 
    /* apply the inverse MixColumn transform to all round keys but the first and the last: */ 
    for (i = 1; i < (key->rounds); i++) { 
     rk += 4; 
     for (j = 0; j < 4; j++) { 
      u32 tp1, tp2, tp4, tp8, tp9, tpb, tpd, tpe, m; 

      tp1 = rk[j]; 
      m = tp1 & 0x80808080; 
      tp2 = ((tp1 & 0x7f7f7f7f) << 1)^
       ((m - (m >> 7)) & 0x1b1b1b1b); 
      m = tp2 & 0x80808080; 
      tp4 = ((tp2 & 0x7f7f7f7f) << 1)^
       ((m - (m >> 7)) & 0x1b1b1b1b); 
      m = tp4 & 0x80808080; 
      tp8 = ((tp4 & 0x7f7f7f7f) << 1)^
       ((m - (m >> 7)) & 0x1b1b1b1b); 
      tp9 = tp8^tp1; 
      tpb = tp9^tp2; 
      tpd = tp9^tp4; 
      tpe = tp8^tp4^tp2; 
#if defined(ROTATE) 
      rk[j] = tpe^ROTATE(tpd,16)^
       ROTATE(tp9,24)^ROTATE(tpb,8); 
#else 
      rk[j] = tpe^(tpd >> 16)^(tpd << 16)^
       (tp9 >> 8)^(tp9 << 24)^
       (tpb >> 24)^(tpb << 8); 
#endif 
     } 
    } 
    return 0; 
} 

#endif /* AES_ASM */ 

分割而調用這種兩個功能與關鍵尺寸= 192和256雖然這兩個函數中可以清楚地分配沒有發生關鍵尺寸(鍵尺寸= 128,total_round = 10,鍵尺寸= 192,total_round = 12,鍵尺寸= 256,total_round = 14)的輪迴發生,在這兩個功能處仍出現分段錯誤。

+0

你爲什麼循環使用'NO_OF_DECRYPTION'? – zaph

+0

@zaph我需要執行50個解密。 – bholanath

+0

@zaph我已經使用AES_set_encrypt_key((const const unsigned char *)key,128,&enc_key);對於key-size = 128和AES_encrypt(text,enc_out和enc_key);加密文本。但是,AES_set_encrypt_key((const const unsigned char *)鍵,192,&enc_key);和AES_set_encrypt_key((const const unsigned char *)鍵,256,&enc_key);都會導致分段錯誤。 – bholanath

回答

0

忽略我以前的錯誤的答案嘗試。

rd_key字段AES_KEY是一個帶有44個元素的unsigned int數組。

rounds字段可以用12(對於192位密鑰)或14(對於256位密鑰)的值進行初始化。

rounds字段然後用作rd_key數組索引的限制(通過rk指針),並且索引可以超出數組的末尾。在private_AES_set_decrypt_key()有此代碼段的代碼:

/* invert the order of the round keys: */ 
for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) { 
    temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; 
    temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; 
    temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; 
    temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; 
} 

rounds是12,j將在48開始,因此,所有使用j變量中的前兩個循環迭代的訪問的上述超出了陣列的端部。 256位密鑰使用14輪時會更糟糕。由於其中一些訪問是寫入,所以rounds字段也會被覆蓋,那時誰知道rd-key陣列會發生什麼,因爲rounds在以下循環中被用作限制?

其他循環移動rk指針超出rd_key陣列的開始,所以很難知道他們訪問超出了數組的結尾,但應該能夠驗證是否目前正使用調試器發生。

也許你需要做的是改變的struct aes_key_st的定義:

struct aes_key_st { 
    unsigned int rd_key[4 *(14 + 1)]; 
    int rounds; 
}; 

,最多可容納14 rounds 256位密鑰。

+0

非常感謝你。上述解決方案解決了我的問題。 – bholanath

0

不要使用塊級別的加密代碼,您需要使用支持輸入較大的一個塊,循環不需要的水平,模式如CBC和填充,如PKCS#7

+0

任何示例或示例代碼? – bholanath

+1

SO上有一些基於「C」的例子。使用塊級加密是非常罕見的。使用塊級別,您將不得不爲自己的填充填充非塊大小的輸入。該模式基本上是ECB模式,這是不安全的,請參閱[ECB模式](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29),向下滾動到企鵝。 – zaph

+0

我同意你的看法,我需要填充的情況下輸入不是塊大小的倍數。截至目前,我正在傳遞塊大小(硬編碼)倍數的長度輸入,並試圖使用塊級加密。我認爲默認情況下CBC已經實現,在這種情況下如何解決key-size = 192和256的這種分段錯誤? – bholanath