我正在为 Karl Malbrain 的 AES 实现编写一个包装器,以处理大于 16 字节的输入文件。因此,我编写了一个函数aes_encrypt_block
它将输入缓冲区(message
)拆分为16字节(chunk
/chunk_cipher
)的块,调用加密/解密函数并将加密/解密的16字节放回结果缓冲区。
这行得通。但是,我需要在加密之前填充消息。因此,我加密的最后 16 个字节(在 for 循环之外)是填充字节。将这些字节复制到输出缓冲区(cipher
)时,我得到一个段错误。我真的看不出出了什么问题。
你看到错误了吗?
问候
#include "aes.h"
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#define DEBUG 1
void aes_encrypt_block(uint8_t **message, uint8_t **cipher, uint8_t blocks, uint8_t pad_bytes);
void aes_decrypt_block(uint8_t **msg_decrypted, uint8_t **cipher, uint8_t blocks, uint8_t pad_bytes);
unsigned long readFile(char *fileName, uint8_t **buffer);
//unsigned long readFile1(char *fileName, uint8_t *buffer);
uint8_t secret[16] = {0x44, 0x43, 0x45, 0x33, 0x44, 0x03, 0x34, 0x44, 0x43, 0x45, 0x33, 0x44, 0x03, 0x34, 0x03, 0x34};
uint8_t *chunk = NULL;
uint8_t *chunk_cipher = NULL;
uint8_t expanded[176] = {0x00};
uint8_t *buffer = NULL;
uint8_t *cipher = NULL;
uint8_t *msg_decrypted = NULL;
uint8_t mode = -1;
int main(int argc, char *argv[]) {
uint32_t i = 0;
uint8_t blocks = -1, pad_bytes = -1;
unsigned long fileLen;
char* ch = NULL;
if(argc<3) {
printf("Wrong arguments supplied.nn%s {0/1} OUTnnt0 - encryptnt1 - decryptntOUT - file to read from / to write to.nn", argv[0]);
return 0;
} else {
mode = atoi(argv[1]);
if(mode<0 || mode>1) {
printf("Wrong arguments supplied.nn%s {0/1} OUTnnt0 - encryptnt1 - decryptntOUT - file to read from / to write to.nn", argv[0]);
return 0;
}
}
puts("");
// Read file
fileLen = readFile(argv[2], &buffer);
// Setting up parameters and memory
if(fileLen%16!=0) {
printf("- ");
blocks = fileLen/16+1;
pad_bytes = (blocks*16)-fileLen;
} else {
printf("+ ");
blocks = fileLen/16+1;
pad_bytes = 16;
}
cipher = malloc((blocks*16)*sizeof(int));
if(cipher==NULL) printf("malloc() error!n");
aes_expand_key(secret, expanded);
if(DEBUG) printf("size: %u, size/16: %d, blocks: %d, padding: %dnn", fileLen, fileLen/16, blocks, pad_bytes);
if(!mode) { // We will encrypt
aes_encrypt_block(&buffer, &cipher, blocks, pad_bytes);
free(buffer);
FILE *file_enc;
file_enc = fopen("bla.enc", "wb");
fileLen = fwrite(&cipher, sizeof(uint8_t), 32, file_enc);
printf("nWrote %ld bytes to %sn", fileLen, argv[2]);
fclose(file_enc);
} else { // We will decrypt
msg_decrypted = malloc((16*blocks)*sizeof(uint8_t));
// Decrypting blocks
aes_decrypt_block(msg_decrypted, cipher, blocks, pad_bytes);
puts("nDecrypted message:");
printf("%sn", msg_decrypted);
puts("");
free(msg_decrypted);
}
return 0;
}
unsigned long readFile(char *fileName, uint8_t **buffer) {
unsigned long fileLen = 0;
uint8_t i;
char* ch = NULL;
FILE *file;
file = fopen (fileName, "rb"); /* open the file for reading */
if(file==NULL) {
perror(fileName);
return 0;
}
fseek(file, 0, SEEK_END);
fileLen=ftell(file);
fseek(file, 0, SEEK_SET);
*buffer=malloc(fileLen+1);
if (!buffer) {
fprintf(stderr, "Memory error!");
fclose(file);
return;
}
fread(*buffer, 1, fileLen, file);
printf( "Source message in hex(%s, %ld bytes):n", fileName, fileLen );
for (ch = *buffer ; ch < *buffer + fileLen; ++ch) {
printf( "%02X", *ch );
}
puts("nASCII:n---------");
for (ch = *buffer ; ch < *buffer + fileLen; ++ch) {
printf( "%c", *ch );
}
puts("");
fclose(file);
return fileLen;
}
void aes_encrypt_block(uint8_t **message, uint8_t **cipher, uint8_t blocks, uint8_t pad_bytes) {
uint8_t i;
chunk = malloc(16*sizeof(uint8_t));
if(chunk==NULL) printf("malloc() error!n");
chunk_cipher = malloc(16*sizeof(uint8_t));
if(chunk_cipher == NULL) printf("malloc() error!n");
for(i=0; i<(blocks-1); i++) {
memcpy(chunk, message[i*16], 16*sizeof(uint8_t));
aes_encrypt(chunk, expanded, chunk_cipher);
memcpy(cipher[i*16], chunk_cipher, 16*sizeof(uint8_t));
}
// Padding
memcpy(chunk, message[(blocks-1)*16], (16-pad_bytes)*sizeof(uint8_t));
uint8_t j;
for(j=0; j<=pad_bytes; j++) {
chunk[15-j] = pad_bytes;
}
aes_encrypt(chunk, expanded, chunk_cipher);
memcpy(cipher[i*16], chunk, 16*sizeof(uint8_t));
}
编辑:
瓦尔格林德输出(test.c 中的第 149 行对应于:memcpy(cipher[i*16], chunk, 16*sizeof(uint8_t));
Valgrind outputs:
InvalidWrite: Invalid write of size 4
Call stack:
/usr/lib/valgrind/vgpreload_memcheck-x86-linux.so 0x402E08A: memcpy
/home/dev/aes/test.c|149|0x804A604: aes_encrypt_block
/home/dev/aes/test.c|59|0x8049AFE: main
Address 0x0 is not stack'd, malloc'd or (recently) free'd
Valgrind found 1 errors!
如果pad_bytes == 16
则此循环:
for(j=0; j<=pad_bytes; j++) {
chunk[15-j] = pad_bytes;
}
将在chunk
开始之前写入无效位置,可能会损坏您的堆。
它可能应该是:
for(j=0; j<pad_bytes; j++) {
chunk[15-j] = pad_bytes;
}
另请注意,您似乎也有许多内存泄漏,其中通过malloc
分配的内存没有free
d,例如 chunk
和chunk_cipher
aes_encrypt_block()
.
我会说这一行
memcpy(cipher[i*16], chunk_cipher, 16*sizeof(uint8_t));
应该是
memcpy((*cipher) + i*16, chunk_cipher, 16*sizeof(uint8_t));
(对于memcpy()
的第二个第二个调用,请同样应用于第一个参数)
甚至更好的是将aes_encrypt_block()
的签名从
void aes_encrypt_block(uint8_t **message, uint8_t **cipher, uint8_t blocks, uint8_t pad_bytes)
自
void aes_encrypt_block(uint8_t **message, uint8_t (*cipher)[16], uint8_t blocks, uint8_t pad_bytes)
并做
memcpy(cipher + i, chunk_cipher, sizeof(*cipher));
(对于memcpy()
的第二个第二个调用,请同样应用于第一个参数)