c 中的字符数组被意外修改并删除未使用的变量会破坏算法

问题描述 投票:0回答:1

所以我为我的大学作业制作了一个简单的 AES 算法。它本身工作正常的算法我没有收到任何错误,密文和解密文本都很好,但是当我尝试访问解密文本时,它会被更改。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <conio.h>

typedef struct {
    int bits[4][4][8];
}Block;

int SBox[16][16] = {
    {  99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215, 171, 118 },
    { 202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175, 156, 164, 114, 192 },
    { 183, 253, 147,  38,  54,  63, 247, 204,  52, 165, 229, 241, 113, 216,  49,  21 },
    {   4, 199,  35, 195,  24, 150,   5, 154,   7,  18, 128, 226, 235,  39, 178, 117 },
    {   9, 131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 179,  41, 227,  47, 132 },
    {  83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 190,  57,  74,  76,  88, 207 },
    { 208, 239, 170, 251,  67,  77,  51, 133,  69, 249,   2, 127,  80,  60, 159, 168 },
    {  81, 163,  64, 143, 146, 157,  56, 245, 188, 182, 218,  33,  16, 255, 243, 210 },
    { 205,  12,  19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 100,  93,  25, 115 },
    {  96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 184,  20, 222,  94,  11, 219 },
    { 224,  50,  58,  10,  73,   6,  36,  92, 194, 211, 172,  98, 145, 149, 228, 121 },
    { 231, 200,  55, 109, 141, 213,  78, 169, 108,  86, 244, 234, 101, 122, 174,   8 },
    { 186, 120,  37,  46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138 },
    { 112,  62, 181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158 },
    { 225, 248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85,  40, 223 },
    { 140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15, 176,  84, 187,  22 }
};

int SBoxInverse[16][16] = {
    {  82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129, 243, 215, 251},
    { 124, 227,  57, 130, 155,  47, 255, 135,  52, 142,  67,  68, 196, 222, 233, 203},
    {  84, 123, 148,  50, 166, 194,  35,  61, 238,  76, 149,  11,  66, 250, 195,  78},
    {   8,  46, 161, 102,  40, 217,  36, 178, 118,  91, 162,  73, 109, 139, 209,  37},
    { 114, 248, 246, 100, 134, 104, 152,  22, 212, 164,  92, 204,  93, 101, 182, 146},
    { 108, 112,  72,  80, 253, 237, 185, 218,  94,  21,  70,  87, 167, 141, 157, 132},
    { 144, 216, 171,   0, 140, 188, 211,  10, 247, 228,  88,   5, 184, 179,  69,   6},
    { 208,  44,  30, 143, 202,  63,  15,   2, 193, 175, 189,   3,   1,  19, 138, 107},
    {  58, 145,  17,  65,  79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115},
    { 150, 172, 116,  34, 231, 173,  53, 133, 226, 249,  55, 232,  28, 117, 223, 110},
    {  71, 241,  26, 113,  29,  41, 197, 137, 111, 183,  98,  14, 170,  24, 190,  27},
    { 252,  86,  62,  75, 198, 210, 121,  32, 154, 219, 192, 254, 120, 205,  90, 244},
    {  31, 221, 168,  51, 136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95},
    {  96,  81, 127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147, 201, 156, 239},
    { 160, 224,  59,  77, 174,  42, 245, 176, 200, 235, 187,  60, 131,  83, 153,  97},
    {  23,  43,   4, 126, 186, 119, 214,  38, 225, 105,  20,  99,  85,  33,  12, 125}
};

Block getBlock(char pt[],int nthBlock) {
    Block block;
    char HexToBinary[16][4] = {"0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111"};
    int index = nthBlock * 32,i,j,h = -1,k;

    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            for (k = 0; k < 8; k++) {
                if(k % 4 == 0) h++;
                char currentChar = index+h < (int)strlen(pt) ? pt[index+h] : '0';
                int hex = currentChar - ((currentChar >= '0' && currentChar <= '9') ? '0' : ('A' - 10));
                block.bits[j][i][k] = HexToBinary[hex][k % 4] - '0';
            }
        }
    }

    return block;
}

Block getKeyBlock(int key[]){
    char HexToBinary[16][4] = {"0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111"};
    Block block;
    int i,j,h = 0,k;

    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++,h++) {
            int v1 = (key[h] >> 4) & 0x0F;
            int v2 = key[h] & 0x0F;
            for (k = 0; k < 8; k++) block.bits[j][i][k] = HexToBinary[k < 4 ? v1 : v2][k % 4] - '0';
        }
    }

    return block;
}

void printBlockH(Block block,char title[],int n){
    int i,j,k;
    printf("\n\t%s [%02d] : ",title,n);
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            for (k = 0; k < 8; k++) printf("%d",block.bits[i][j][k]);
            printf("  ");
        }
    }
}

void printBlock(Block block,char title[],int n){
    int i,j;
    printf("\n%s [%02d] : \n",title,n);
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            int val = block.bits[i][j][0] * 128 + block.bits[i][j][1] * 64 + block.bits[i][j][2] * 32 + block.bits[i][j][3] * 16 + block.bits[i][j][4] * 8 + block.bits[i][j][5] * 4 + block.bits[i][j][6] * 2 + block.bits[i][j][7];
            printf("%02x ",val);
        }
        printf("\n");
    }
}

void printColumn(int col[4][8],char title[],int n){
    int i;
    printf("\n%s [%02d] : \n",title,n);
    for (i = 0; i < 4; i++) {
        int val = col[i][0] * 128 + col[i][1] * 64 + col[i][2] * 32 + col[i][3] * 16 + col[i][4] * 8 + col[i][5] * 4 + col[i][6] * 2 + col[i][7];
        printf("%02x\n",val);
    }
}

Block SBoxBlock(Block block){
    int i,j,h,k;
    Block newBlock = {};
    for (i = 0; i < 4; i++){
        for (j = 0; j < 4; j++){
            k = block.bits[i][j][0] * 8 + block.bits[i][j][1] * 4 + block.bits[i][j][2] * 2 + block.bits[i][j][3];
            h = block.bits[i][j][4] * 8 + block.bits[i][j][5] * 4 + block.bits[i][j][6] * 2 + block.bits[i][j][7];
            int sBoxResult = SBox[k][h];
            for (k = 7; k >= 0; k--) {
                newBlock.bits[i][j][k] = sBoxResult & 1;
                sBoxResult >>= 1;
            }
        }
    }

    return newBlock;
}

Block SBoxBlockInverse(Block block){

    int i,j,h,k;
    Block newBlock = {};
    for (i = 0; i < 4; i++){
        for (j = 0; j < 4; j++){
            k = block.bits[i][j][0] * 8 + block.bits[i][j][1] * 4 + block.bits[i][j][2] * 2 + block.bits[i][j][3];
            h = block.bits[i][j][4] * 8 + block.bits[i][j][5] * 4 + block.bits[i][j][6] * 2 + block.bits[i][j][7];
            int sBoxResult = SBoxInverse[k][h];
            for (k = 7; k >= 0; k--) {
                newBlock.bits[i][j][k] = sBoxResult & 1;
                sBoxResult >>= 1;
            }
        }
    }

    return newBlock;
}

void SBoxColumn(int c1[4][8],int c2[][8]){
    int i,h,k;
    for (i = 0; i < 4; i++){
        k = c1[i][0] * 8 + c1[i][1] * 4 + c1[i][2] * 2 + c1[i][3];
        h = c1[i][4] * 8 + c1[i][5] * 4 + c1[i][6] * 2 + c1[i][7];
        int sBoxResult = SBox[k][h];
        for (k = 7; k >= 0; k--) {
            c2[i][k] = sBoxResult & 1;
            sBoxResult >>= 1;
        }
    }
}

void SBoxColumnInverse(int c1[4][8],int c2[][8]){

    int i,h,k;
    for (i = 0; i < 4; i++){
        k = c1[i][0] * 8 + c1[i][1] * 4 + c1[i][2] * 2 + c1[i][3];
        h = c1[i][4] * 8 + c1[i][5] * 4 + c1[i][6] * 2 + c1[i][7];
        int sBoxResult = SBoxInverse[k][h];
        for (k = 7; k >= 0; k--) {
            c2[i][k] = sBoxResult & 1;
            sBoxResult >>= 1;
        }
    }
}

Block ShiftRows(Block block){
    Block newBlock = {};
    int i,j,k,n = 0;
    for (i = 0; i < 4; i++,n++) for (j = 0; j < 4; j++) for (k = 0; k < 8; k++) newBlock.bits[i][j][k] = block.bits[i][(j+n) % 4][k];
    return newBlock;
}

Block ShiftRowsInverse(Block block){
    Block newBlock = {};
    int i,j,k,n = 0;
    int indexes[4][4] = {
        {0,1,2,3},
        {3,0,1,2},
        {2,3,0,1},
        {1,2,3,0}
    };
    for (i = 0; i < 4; i++,n++) for (j = 0; j < 4; j++) for (k = 0; k < 8; k++) newBlock.bits[i][j][k] = block.bits[i][indexes[n][j]][k];
    return newBlock;
}

void Xor(int a[9],int b[8],int *r){
    int i;
    for (i = 0; i < 8; i++) r[i] = a[i+1] ^ b[i];
}

void XorColumn(int a[4][8],int b[4][8],int c[][8]){
    int i,j;
    for(i = 0; i < 4; i++) for(j = 0; j < 8; j++) c[i][j] = a[i][j] ^ b[i][j];
}

int GaloisMult(int a, int b){
    int i,j=0,h=0,k,abits[8],bbits[8],rbits[8];
    for (i = 0; i < 8; i++){
        if(((a >> i) & 1) != 0) abits[j++] = i;
        if(((b >> i) & 1) != 0) bbits[h++] = i;
    }
    int dbits[] = {0,0,0,0,0,0,0,0,0,0,0};
    for (k = 0; k < h; k++) for (i = 0; i < j; i++) dbits[10 - abits[i] + bbits[k]] = (dbits[10 - abits[i] + bbits[k]] + 1) % 2;

    int val = 0;
    for (i = 0; i < 11; i++) val = (val << 1) | dbits[i];
    while(val > 0xff) val ^= 0x11b;
    return val;
}

Block MixColumn(Block block){

    int i,j,k;
    int m1[4][4] = {
        {2,3,1,1},
        {1,2,3,1},
        {1,1,2,3},
        {3,1,1,2}
    };

    int m2[4][4];
    int result[4][4] = {
        {0,0,0,0},
        {0,0,0,0},
        {0,0,0,0},
        {0,0,0,0}
    };

    for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) m2[i][j] = block.bits[i][j][0] * 128 + block.bits[i][j][1] * 64 + block.bits[i][j][2] * 32 + block.bits[i][j][3] * 16 + block.bits[i][j][4] * 8 + block.bits[i][j][5] * 4 + block.bits[i][j][6] * 2 + block.bits[i][j][7];

    for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) result[j][i] ^= GaloisMult(m2[k][i],m1[j][k]);

    Block newBlock = {};
    for (i = 0; i < 4; i++){
        for (j = 0; j < 4; j++){
            int val = result[i][j];
            for (k = 7; k >= 0; k--) {
                newBlock.bits[i][j][k] = val & 1;
                val >>= 1;
            }
        }
    }
    return newBlock;
}

Block MixColumnInverse(Block block){

    int i,j,k;
    int m1[4][4] = {
        {14,11,13,9},
        {9,14,11,13},
        {13,9,14,11},
        {11,13,9,14},
    };

    int m2[4][4];
    int result[4][4] = {
        {0,0,0,0},
        {0,0,0,0},
        {0,0,0,0},
        {0,0,0,0}
    };

    for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) m2[i][j] = block.bits[i][j][0] * 128 + block.bits[i][j][1] * 64 + block.bits[i][j][2] * 32 + block.bits[i][j][3] * 16 + block.bits[i][j][4] * 8 + block.bits[i][j][5] * 4 + block.bits[i][j][6] * 2 + block.bits[i][j][7];

    for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) for (k = 0; k < 4; k++) result[j][i] ^= GaloisMult(m2[k][i],m1[j][k]);

    Block newBlock = {};
    for (i = 0; i < 4; i++){
        for (j = 0; j < 4; j++){
            int val = result[i][j];
            for (k = 7; k >= 0; k--) {
                newBlock.bits[i][j][k] = val & 1;
                val >>= 1;
            }
        }
    }
    return newBlock;
}

Block AddRoundKey(Block block,Block key){
    Block newBlock = {};
    int i,j,k;
    for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) for (k = 0; k < 8; k++) newBlock.bits[i][j][k] = block.bits[i][j][k] ^ key.bits[i][j][k];
    return newBlock;
}

void GetColumn(Block b,int col[][8],int x,int n){
    int i,j;
    for(i = 0; i < 4; i++) for(j = 0; j < 8; j++) col[i][j] = b.bits[(i+n) % 4][x][j];
}

int ConvertToASCII(int bits[8],int start) {
    int i = bits[start] * 8 + bits[start + 1] * 4 + bits[start + 2] * 2 + bits[start + 3];
    return i;
}

void BlockToASCII(char *text,Block b) {
    char HexToChar[] = "0123456789ABCDEF";
    int i,j,h = 0;
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            int c = ConvertToASCII(b.bits[j][i],0);
            int c2 = ConvertToASCII(b.bits[j][i],4);
            text[h++] = HexToChar[c];
            text[h++] = HexToChar[c2];
        }
    }
    text[h] = '\0';
}

char getHexFromChar(unsigned char c,int n){
    char HexToChar[] = "0123456789ABCDEF";
    return HexToChar[(n == 0) ? c / 16 : (c % 16)];
}

int indexOf(char c){
    char HexToChar[] = "0123456789ABCDEF";
    int i = 0;
    for (i = 0; i < 16; i++) if(c == HexToChar[i]) return i;
    return -1;
}

char getCharFromHex(char a,char b){
    int s = indexOf(a) * 16 + indexOf(b);
    return (char)s;
}

void Encrypt(char* OutText,char InText[],Block key0,Block Ki[10]){

    float PlainTextInBlocks = strlen(InText)*4 / 128;
    float extraBlock = fmod(strlen(InText)*4 / 128.0f,1.0f) > 0.0f ? 1 : 0;
    
    int BlocksRequired = (int)PlainTextInBlocks + extraBlock;

    int i,j;
    Block blocks[BlocksRequired];
    for(i = 0; i < BlocksRequired; i++) blocks[i] = getBlock(InText,i);
    for(i = 0; i < BlocksRequired; i++) printBlock(blocks[i],"Block",i);
    
    for (i = 0; i < BlocksRequired; i++){
        Block block = blocks[i];
        
        Block inp = AddRoundKey(block,key0);
        // printBlock(inp,"inp",i);
        for (j = 0; j < 10; j++){
            Block sb = SBoxBlock(inp);
            // printBlock(sb,"sb",j);
            Block sft = ShiftRows(sb);
            // printBlock(sft,"sft",j);
            Block mc = MixColumn(sft);
            // printBlock(mc,"mx",j);
            inp = AddRoundKey((j != 9) ? mc : sft,Ki[j]);
            // printBlock(inp,"inp",j);
        }
        // printBlock(inp,"inp",i);
        char text[33];
        BlockToASCII(text,inp);
        strcat(OutText,text);
    }
}

void Decrypt(char* OutText,char InText[],Block key0,Block Ki[10]){

    float PlainTextInBlocks = strlen(InText)*4 / 128;
    float extraBlock = fmod(strlen(InText)*4 / 128.0f,1.0f) > 0.0f ? 1 : 0;
    
    int BlocksRequired = (int)PlainTextInBlocks + extraBlock;

    int i,j;
    Block blocks[BlocksRequired];
    for(i = 0; i < BlocksRequired; i++) blocks[i] = getBlock(InText,i);
    for(i = 0; i < BlocksRequired; i++) printBlock(blocks[i],"Block",i);
    
    for (i = 0; i < BlocksRequired; i++){
        Block block = blocks[i];
        Block inp = AddRoundKey(block,Ki[9]);
        // printBlock(inp,"inp",i);
        for (j = 0; j < 10; j++){
            Block sft = ShiftRowsInverse(inp);
            // printBlock(sft,"sft",j);
            Block sb = SBoxBlockInverse(sft);
            // printBlock(sb,"sb",j);
            // printBlock((j == 9) ? key0 : Ki[8-j],"Ki",j);
            Block add = AddRoundKey(sb,(j == 9) ? key0 : Ki[8-j]);
            // printBlock(add,"add",j);
            inp = (j == 9) ? add : MixColumnInverse(add);
            // printBlock(inp,"inp",j);
        }
        // printBlock(inp,"inp",i);
        char text[33];
        BlockToASCII(text,inp);
        strcat(OutText,text);
    }
}

int main() {
    srand(time(NULL));

    int i = 0,j = 0,n = 0,k = 0,l = 0;
    char cipherText[] = "";
    char DecryptedText[] = "";
    char rawInput[1024];
    // int key[16] = {43,126,21,22,40,174,210,166,171,247,21,136,9,207,79,60};
    int key[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

    puts("Enter Plain Text : ");
    gets(rawInput);
    n = strlen(rawInput);
    // char plaintext[] = "3243F6A8885A308D313198A2E0370734";
    // while(n % 16 != 0) n++;
    char plaintext[(n * 2) + 1];

    for (i = 0; i < n; i++){
        plaintext[j++] = getHexFromChar(i < (int)strlen(rawInput) ? rawInput[i] : ' ',0);
        plaintext[j++] = getHexFromChar(i < (int)strlen(rawInput) ? rawInput[i] : ' ',1);
    }
    plaintext[j] = '\0';

    // for (i = 0; i < 16; i++) key[i] = rand() % 16;
    Block OriginalKey = getKeyBlock(key);
    printf("\nRandom Key              : ");
    for(i = 0; i < 16; i++) printf("%X", key[i]);
    printf("\n");

    int rtemp[10] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36};
    int RCon[10][4][8];
    for (i = 0; i < 10; i++) for (j = 0; j < 4; j++) for (k = 0; k < 8; k++) RCon[i][j][k] = (((j == 0) ? rtemp[i] : 0) >> (7-k)) & 1;
    Block Ki[10];
    Block temp = OriginalKey;
    for (i = 0; i < 10; i++){
        int c1[4][8],c2[4][8],c3[4][8],out[4][8];
        for (l = 0; l < 4; l++){
            GetColumn(temp,c1,(l == 0) ? 3 : l-1,(l == 0) ? 1 : 0);
            GetColumn(temp,c2,l,0);
            if(l == 0){
                SBoxColumn(c1,c3);
                XorColumn(c2,c3,c1);
                for (j = 0; j < 4; j++) for (k = 0; k < 8; k++) c2[j][k] = RCon[i][j][k];
            }
            XorColumn(c1,c2,out);
            for (j = 0; j < 4; j++) for (k = 0; k < 8; k++) temp.bits[j][l][k] = out[j][k];
        }
        Ki[i] = temp;
    }

    printBlock(OriginalKey,"KeyInitial",0);

    printf("Plain Text In Hex       : %s",plaintext);
    
    printf("\n\nEncryption      ->");
    Encrypt(cipherText,plaintext,OriginalKey,Ki);
    printf("\n\nCipher Text In Hex      : %s\n",cipherText);

    printf("\nDecryption      ->");
    Decrypt(DecryptedText,cipherText,OriginalKey,Ki);
    printf("\n\nDecrypted Text In Hex   : %s\n",DecryptedText);
//this is line 473
    int len = (int)strlen(DecryptedText);
    printf("len size  : %d\n",len);
    printf("aften len msg  : %s\n",DecryptedText);
    printf("aften len msg Size  : %d\n",(int)strlen(DecryptedText));
    char rawOutput[len / 2 + 1];
    printf("after raw output msg  : %s\n",DecryptedText);
    printf("after raw output msg Size   : %d\n",(int)strlen(DecryptedText));
    for (i = 0,j = 0; i < len / 2; i++){
        rawOutput[i] = getCharFromHex(DecryptedText[j],DecryptedText[j+1]);
        j += 2;
    }
    rawOutput[i] = '\0';
    printf("\nOriginal Text   : %s\n",rawOutput);

    return 0;
}

该算法工作正常,直到第 473 行,就在第 472 行之前,我打印了解密的文本,它是十六进制格式的正确文本,但现在从第 473 行开始,我将其转换为 ascii 输出。

问题是在第 473 行之后,解密的文本变得越来越短,并且 ascii 输出出现错误。 输出:

...other outputs
Decrypted Text In Hex   : 4A696D6D790000000000000000000000
len size  : 32
aften len   : 4A696D6D79 
aften len Size  : 11
after raw output   : 4A∟█a
after raw output Size   : 5

Original Text   : J∩∩∩∩∩∩

第二个问题是在第 212 行,我有一个未使用的 int

rbits[8]
如果我删除该未使用的变量,算法就会中断,并且我会得到所有错误的结果。

arrays c string memory-leaks
1个回答
0
投票

您的代码中至少存在以下问题:

  • GaloisMult
    中,
    dbits
    数组有 11 个条目,但索引
    [10 - abits[i] + bbits[k]
    可以达到 13(甚至更多),因此缓冲区溢出会触发未定义的行为。事实上,删除未使用的数组
    rbits
    会改变代码的行为,这是数组溢出的强烈迹象。
  • cipherText
    DecryptedText
    数组的长度为1,因此它们可以容纳最大长度为0的字符串,这是毫无意义的。它们的长度应与
    rawInput
    数组的长度相同。

可能还有更多问题,我没有检查。

© www.soinside.com 2019 - 2024. All rights reserved.