解密和加密代码(包括在下面)可能是错误的。他们正在编译无错误,但解密文件与纯文本文件不同。这是乱码。
我试图找出它为什么会出现乱码。我怀疑我的代码没问题。
我做了很多可以解决问题的事情,但都没有奏效。我有一种使用AES-CTR的特定方式,即我不直接包括OpenSSL。我依赖于 / dev / urandom / dev / random 的随机性(IV等等)。
这些事情包括我处理我的加密和解密函数的方式(比如:使用*(ptr)
而不是ptr[]
和其他几个等效替换,这通常是不必要的),我的论点是什么在最终保存加密或解密的文本之前,我正在通过并检查某些验证。
我没有增加(或改变)初始化的IV。 IV是16个字节。
早些时候,我这样做是为了增加IV的最后一个字节:
size_t blocksize = CCA_STRENGTH; /* CCA_STRENGTH is "#define CCA_STRENGTH 16" */
char *iv = (char *) malloc(16 * sizeof(char));
ri(); /* PRNG initialized.*/
prng_getbytes(iv, blocksize);
*
*
*
*
size_t iv_counter = 0;
while loop starts here...
*
*
*(iv +(block_size - 1)) += iv_counter;
*
*
while loop ends here...
此加密和解密发生的while循环如下所示(此部分暂时删除,因为它是安全要求而不是编码标准或加密或解密功能的要求)。
这是我的解密代码:
#include "pv.h"
void decrypt_file (const char *ptxt_fname, void *raw_sk, size_t raw_len, int fin)
{
int fd;
if((fd = open(ptxt_fname, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0)
{
/*fd will become -1 on failure.*/
perror("plaintext file permission error\n");
exit(EXIT_FAILURE);
}
size_t block_size = CCA_STRENGTH;
const char *aes_key;
aes_key = (const char *) raw_sk;
aes_ctx aes;
aes_setkey(&aes, aes_key, block_size);
char *iv;
iv = (char *) malloc(block_size * sizeof(char));
size_t bytes_read;
bytes_read = read(fin, iv, block_size);
char *buf = (char *) malloc(block_size * sizeof(char)); /*ctxt-file read buffer*/
char *ptxt = (char *) malloc(block_size * sizeof(char)); /*p-text buffer*/
memset(ptxt, 0, block_size);
bytes_read = read(fin, buf, block_size);
while(bytes_read >= 1)
{
aes_encrypt(&aes, ptxt, iv); /* earlier it was "aes_decrypt(&aes, ptxt, iv);" which was not the correct reverse transformation function */
for(loop_variable = 0; loop_variable < bytes_read; loop_variable++)
{
*(ptxt + loop_variable) = *(ptxt + loop_variable) ^ *(buf + loop_variable);
}
if((result = write_chunk(fd, ptxt, bytes_read)) == -1)
{
perror("Problem when writing to ptxt file... \n");
close(fd);
unlink(ptxt_fname); /*for file deletion*/
aes_clrkey(&aes);
free(ptxt);
free(iv);
free(buf);
exit(EXIT_FAILURE);
}
if((bytes_read = read(fin, buf, block_size)) < 1)
{
close(fd);
aes_clrkey(&aes);
free(ptxt);
free(iv);
free(buf);
break;
}
}
}
void
usage (const char *pname)
{
printf ("Simple File Decryption Utility\n");
printf ("Usage: %s SK-FILE CTEXT-FILE PTEXT-FILE\n", pname);
printf (" Exits if either SK-FILE or CTEXT-FILE don't exist, or\n");
printf (" if a symmetric key sk cannot be found in SK-FILE.\n");
printf (" Otherwise, tries to use sk to decrypt the content of\n");
printf (" CTEXT-FILE: upon success, places the resulting plaintext\n");
printf (" in PTEXT-FILE; if a decryption problem is encountered\n");
printf (" after the processing started, PTEXT-FILE is truncated\n");
printf (" to zero-length and its previous content is lost.\n");
exit (1);
}
int main (int argc, char **argv)
{
int fdsk, fdctxt;
char *sk = NULL;
size_t sk_len = 0;
if (argc != 4) {
usage (argv[0]);
}
else if (((fdsk = open (argv[1], O_RDONLY)) == -1)
|| ((fdctxt = open (argv[2], O_RDONLY)) == -1)) {
if (errno == ENOENT) {
usage (argv[0]);
}
else {
perror (argv[0]);
exit (-1);
}
}
else {
setprogname (argv[0]);
if (!(sk = import_sk_from_file (&sk, &sk_len, fdsk))) {
printf ("%s: no symmetric key found in %s\n", argv[0], argv[1]);
close (fdsk);
exit (2);
}
close (fdsk);
decrypt_file (argv[3], sk, sk_len, fdctxt);
bzero(sk, sk_len);
free(sk);
close (fdctxt);
}
return 0;
}
以下是我的加密代码:
#include "pv.h"
void encrypt_file (const char *ctxt_fname, void *raw_sk, size_t raw_len, int fin)
{
size_t block_size = CCA_STRENGTH;
int fd; /* ctxt fd */
if((fd = open(ctxt_fname,O_WRONLY|O_TRUNC|O_CREAT,0600)) < 0)
{
perror("Ciphertext file permission error\n");
exit(EXIT_FAILURE);
}
char *iv;
iv = (char *) malloc(block_size * sizeof(char));
ri(); /*IV initialized*/
prng_getbytes(iv, block_size);
struct aes_ctx aes;
const char *aes_key = aes_key = (const char *) raw_sk;
aes_setkey(&aes, aes_key, block_size); /*sets the encryption key.*/
char *buf = buf = (char *) malloc(block_size * sizeof(char)); /*file read buffer*/
char *ctxt = ctxt = (char *) malloc(block_size * sizeof(char)); /*ciphertext buffer*/
int result;
size_t looper = 0;
size_t bytes_read;
result = write_chunk(fd, iv, block_size);
if(result == -1)
{
exit(-1);
}
bytes_read = read(fin, buf, block_size); /*returns how many bytes read*/
while(bytes_read >= 1)
{
aes_encrypt(&aes, ctxt, iv);
for(looper = 0; looper < bytes_read; looper++)
{
*(ctxt + looper) = *(ctxt + looper) ^ *(buf + looper);
}
result = write_chunk(fd, ctxt, bytes_read);
if(result == -1)
{
perror("Problem when writing to ctxt file... \n");
close(fd);
unlink(ctxt_fname); /*for file deletion*/
aes_clrkey(&aes);
free(ctxt);
free(iv);
free(buf);
exit(EXIT_FAILURE);
}
printf("crossed written to file\n");
if((bytes_read = read(fin, buf, block_size)) < 1)
{
close(fd);
aes_clrkey(&aes);
free(ctxt);
free(iv);
free(buf);
break;
}
}
}
void usage (const char *pname)
{
printf ("Personal Vault: Encryption \n");
printf ("Usage: %s SK-FILE PTEXT-FILE CTEXT-FILE\n", pname);
printf (" Exits if either SK-FILE or PTEXT-FILE don't exist.\n");
printf (" Otherwise, encrpyts the content of PTEXT-FILE under\n");
printf (" sk, and place the resulting ciphertext in CTEXT-FILE.\n");
printf (" If CTEXT-FILE existed, any previous content is lost.\n");
exit (1);
}
int main (int argc, char **argv)
{
int fdsk, fdptxt;
char *raw_sk;
size_t raw_len;
if (argc != 4)
{
usage (argv[0]);
}
else if (((fdsk = open (argv[1], O_RDONLY)) == -1) || ((fdptxt = open (argv[2], O_RDONLY)) == -1))
{
if (errno == ENOENT)
{
usage (argv[0]);
}
else
{
perror (argv[0]);
exit (-1);
}
}
else
{
setprogname (argv[0]);
if (!(import_sk_from_file (&raw_sk, &raw_len, fdsk)))
{
printf ("%s: no symmetric key found in %s\n", argv[0], argv[1]);
close (fdsk);
exit (2);
}
close (fdsk);
bzero(raw_sk, raw_len);
free(raw_sk);
close (fdptxt);
}
return 0;
}
加密代码首先在密文文件中加上16个字节的IV(因为它应该是我猜的;我们在解密过程中从ctxt文件读取这16个字节)然后实际加密发生(将其视为一个黑盒子)我们发送IV和钥匙;返回16个字节。返回的那16个字节必须与明文文件缓冲区进行异或(如果文件超过16个字节,则每轮最多16个字节)。
发布,将XORed字节(最多16个字节)写入文件。这个事情发生在最后一轮,它最终打破了试图读取没有更多内容要阅读的文件的循环。 read函数,在每次调用时,尝试读取下一个可用字节(最多指定的字节数)。
这不是一个完美的实现,因为我放宽了安全方面(每个周期随机化IV),但是,它必须首先像这样工作。
在数学上,我想要做的应该是这个概念的确切复制品:
ciphertext_block = message_block ^ [AES(IV, Key)]
message_block = ciphertext_block ^ [AES(IV, Key)]
这里,ciphertext / message_block指的是一个字符块,对于第1轮到第n轮,它将是16个字节,但在最后一轮中可以是或不能是16个字节。
在任何情况下,XORing将在16字节字符(AES-CTR的输出)和另一个块(用于加密的消息块,用于解密的密文块,无论如何,它可以是最多16个字节,因此它们是XOR约束,即它们将是XOR输出长度的决定者。)
由于他们是决策者,一旦XORing操作覆盖了他们的长度,XORing循环就会停止,我们继续向文件写入(ctxt文件用于加密,ptxt文件用于解密)。
不应该有任何填充要求。
我不确定是否应该在任何地方使用realloc
函数。
如果任何读者在理解我想要做的事情时遇到问题,我将很乐意提供额外的文件。
该程序有几个库依赖项,但代码编译无错误。
这是我的编译命令:
gcc -g -O2 -ansi -Wall -Wsign-compare -Wchar-subscripts -Werror -I. -I/usr/include/ -I/home/devel/libdcrypt/include/ -c pv_keygen.c pv_misc.c
gcc -g -O2 -ansi -Wall -Wsign-compare -Wchar-subscripts -Werror -o pv_keygen pv_keygen.o pv_misc.o -L. -L/usr/lib/ -L/home/devel/libdcrypt/lib/ -ldcrypt -lgmp
这仅用于编译我的加密文件。对于我的keygen和decrypt文件,几乎相同(并且同样严格)的命令。 Keygen代码似乎工作得很好(我还没有把它包括在内);我能够生成密钥并将其序列化为文件。该密钥文件实际上有两个密钥,我只读AES-CTR的上半部分。下一半将用于MACing(使用AES-CBC)。
文件大小详情
纯文本文件:x字节
密文文件:(x + 16)个字节
解密文本文件:x字节
统计是对的,内容不是。解密的文本文件和纯文本文件必须相同。
我正在尝试:在RedHat上使用 diff plaintext_file decrypted_file 进行文件比较。
密钥文件实际上是32个字节,其中前16个字节用于加密,后16个字节将用于MACing后加密。
密钥文件(序列化为base-64)(十六进制):
0000000 4662 6e4b 6631 7268 4876 676c 772f 664e
0000010 4d5a 6f32 384e 5141 7139 6635 3442 7245
0000020 646c 4a77 5553 4c30 4f63 3d6f 000a
000002d
输入纯文本文件(十六进制):
0000000 6161 6161 6161 6161 6161 6161 610a 6161
0000010 000a
0000011
加密文件(十六进制):
0000000 540e 0e30 d74d 5000 78c1 13e3 0476 d4a2
0000010 61c9 76ac e717 cd6d 013e e872 8e16 4827
0000020 00a2
0000021
解密文件(十六进制):
0000000 8bea 616a 1f1b d6b0 fd13 da46 5824 ec00
0000010 0081
0000011
外部引用(我已将事情修剪到可能存在错误的位置):
1。)http://www.scs.stanford.edu/nyu/05sp/lab/lab1.html
2)http://www.scs.stanford.edu/nyu/05sp/lab/install-libs.html
答案 0 :(得分:0)
为什么不在CTR模式下使用AES,不需要为每个16字节进行AES调用,然后将输出与数据进行异或。
CTR模式接受纯文本,密钥和IV,并生成AES CTR模式加密数据。 IOW CTR模式执行所有XOR'ing和计数器递增。
请注意CTR模式,相同的键/ IV对只能使用一次。
支持AES和其他分组密码的大多数库都具有较低级别的块加密,并使用它来实现更高级的模式,如CBC,CFB,CTR,OFB和PKCS#7néePKCS#等选项5填充。
答案 1 :(得分:-1)
这是修复:
问题存在于我想要的方式以及我这样做的方式。由于没有与实现相关的问题,我的解密代码中存在该问题。
在我的解密代码中,当我实际寻找的东西是精确的逆向转换时,没有必要包括 aes_decrypt 函数(正确的技术术语结束)解密wrt AES)相反,相同的密钥用于解密同一个文件。
作为修复, aes_decrypt 应该只是 aes_encrypt ,它会运行。
现在,我可以继续寻求额外的补充(加强安全性和数据完整性考虑)。