- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想加密一个包含少量字符串的结构,然后对其进行解密。我尝试了以下代码。原始代码是从网上找到的,并且运行良好。我将它的输入更改为结构。以下是代码。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
typedef struct ticket { /* test field */
int ticketId;
char username[20];
char date[20];
} USR_TICKET;
// a simple hex-print routine. could be modified to print 16 bytes-per-line
static void hex_print(const void* pv, size_t len)
{
const unsigned char * p = (const unsigned char*)pv;
if (NULL == pv)
printf("NULL");
else
{
size_t i = 0;
for (; i<len;++i)
printf("%02X ", *p++);
}
printf("\n");
}
// main entrypoint
int main(int argc, char **argv)
{
int keylength;
printf("Give a key length [only 128 or 192 or 256!]:\n");
scanf("%d", &keylength);
/* generate a key with a given length */
unsigned char aes_key[keylength/8];
memset(aes_key, 0, keylength/8);
if (!RAND_bytes(aes_key, keylength/8))
exit(-1);
/* input struct creation */
size_t inputslength = sizeof(USR_TICKET);
USR_TICKET ticket;
ticket.ticketId = 1;
time_t now = time(NULL);
strftime(ticket.date, 20, "%Y-%m-%d", localtime(&now));
strcpy(ticket.username, "ravinda");
printf("Username - %s\n", ticket.username);
printf("Ticket Id - %d\n", ticket.ticketId);
printf("Date - %s\n", ticket.date);
/* init vector */
unsigned char iv_enc[AES_BLOCK_SIZE], iv_dec[AES_BLOCK_SIZE];
RAND_bytes(iv_enc, AES_BLOCK_SIZE);
memcpy(iv_dec, iv_enc, AES_BLOCK_SIZE);
// buffers for encryption and decryption
const size_t encslength = ((inputslength + AES_BLOCK_SIZE) / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
unsigned char enc_out[encslength];
unsigned char dec_out[inputslength];
memset(enc_out, 0, sizeof(enc_out));
memset(dec_out, 0, sizeof(dec_out));
// so i can do with this aes-cbc-128 aes-cbc-192 aes-cbc-256
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(aes_key, keylength, &enc_key);
AES_cbc_encrypt((unsigned char *)&ticket, enc_out, inputslength, &enc_key, iv_enc, AES_ENCRYPT);
AES_set_decrypt_key(aes_key, keylength, &dec_key);
AES_cbc_encrypt(enc_out, dec_out, encslength, &dec_key, iv_dec, AES_DECRYPT);
printf("original:\t");
hex_print((unsigned char *)&ticket, inputslength);
printf("encrypt:\t");
hex_print(enc_out, sizeof(enc_out));
printf("decrypt:\t");
hex_print(dec_out, sizeof(dec_out));
USR_TICKET * dyc = (USR_TICKET *)dec_out;
printf("Username - %s\n", dyc->username);
printf("Ticket Id - %d\n", dyc->ticketId);
printf("Date - %s\n", dyc->date);
return 0;
}
问题是只有结构的前两个成员可以正确解密。在那之后数据被破坏了。我在这里做错了什么?
最佳答案
我几乎会说这是 OpenSSL 的问题。似乎当传递给 AES_cbc_encrypt
的 length
参数是 > AES_BLOCK_SIZE
但不是其整数倍时(即 length mod AES_BLOCK_SIZE != 0
),然后最后一个 block 使用初始 IV 加密,而不是 CBC 模式应该使用的前一个密文 block 。
您可以通过以下两种方式之一解决此问题:
将您的结构复制到缓冲区,其大小是 AES_BLOCK_SIZE
的整数倍,或分两部分加密 - 完整 block ,后跟单个部分块。后者具有避免额外内存使用的优点,可以按如下方式完成:
size_t fullBlocks = inputslength - (inputslength % AES_BLOCK_SIZE);
size_t remainingBlock = inputslength - fullBlocks;
AES_cbc_encrypt((unsigned char *)&ticket, enc_out, fullBlocks, &enc_key, iv_enc, AES_ENCRYPT);
AES_cbc_encrypt((unsigned char *)&ticket + fullBlocks, enc_out + fullBlocks, remainingBlock, &enc_key, iv_enc, AES_ENCRYPT);
然后您应该能够像目前一样毫无问题地解密。但值得注意的是,您应该将 dec_out
声明为与 enc_out
相同的大小,因为您当前在解密时超出了 dec_out
缓冲区。
编辑:
我将此作为 OpenSSL 中的错误提出:https://rt.openssl.org/Ticket/Display.html?id=3182&user=guest&pass=guest虽然对于这实际上是一个错误还是只是(未记录的)未定义行为存在一些争论,但普遍的共识是应该使用 EVP
例程,而不是这些低级函数。
关于c - 使用 C 中的 openssl 库进行简单的 AES 加密解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19889740/
我只想使用这 3 种模式从 openSSL 测试 AES: key 长度为 128,192 和 256,但我的解密文本与我的输入不同,我不知道为什么。此外,当我传递一个巨大的输入长度(比如说 1024
最近我终于(在 stackoverflow 的用户@WhozCraig 的帮助下)开始在 CBC 模式下使用 AES。现在,我想做完全相同的事情,但使用 AES IGE。我查看了 openssl-1.
网络设备已经配置了 snmpv3 用户,使用 AES192 作为隐私协议(protocol)。但是当执行以下命令时 snmpwalk -v3 -l authPriv -u user -a SHA -A
我在 c# 中使用 AES 算法进行加密和解密。我使用 AesCryptoServiceProvider 类进行加密和解密。 这是我在代码中的设置 AesCryptoServiceProvider r
我正在尝试使用具有不同 key 大小的 openssl 的 AES_decrypt 函数来解密密文。我能够成功解密 key 大小 = 128 的消息。这是我的代码 mydecrypt.c #inclu
如何在 AES-128、AES-192 和 AES-256 之间切换。我目前的实现仅使用 AES-128 Cipher cipher = Cipher.getInstance("AES/CBC/NoP
我的问题是我想在一个线图上叠加一个散点图,这两个图的颜色随着一个变量而变化。我只想保留一种颜色的图例。如果我使用 scale_colour_discrete(guide = "none") 它们都将消
我想用 C# 编写一个可以打开 KeePass 的程序1.x kdb 文件。我下载了源代码并尝试移植密码数据库读取功能。数据库内容已加密。加密 key 通过以下方式获得: 用户输入密码; 计算密码的
我只想将ruby代码迁移到Java 这是我的 ruby 代码 require 'openssl' require 'base64' key = '7c54367a45b37a192abc2cd7f45
我正在使用 AES 的 PyCrypto 实现,并且我正在尝试使用 24 字节 key 加密一些文本(24 字节)。 aes_ecb = AES.new('\x00'*24, AES.MODE_ECB
有人比较这些加密算法的优缺点吗? 最佳答案 使用 AES。 更多详细信息: DES 是七十年代的旧“数据加密标准”。它的 key 大小对于适当的安全性而言太短(56 个有效位;这可以被暴力破解,如 m
我在 iOS 中加密一个 NSString,编码和解码都很好: NSString *stringtoEncrypt = @"This string is to be encrypted"; NSStr
我正在尝试使用 nVidia CUDA 在 CTR 模式下实现 AES-256。我已经成功地为 key 扩展编写了 CPU 代码,现在我需要实现实际的 AES-256 算法。根据维基百科,我见过一些代
我正在 Contiki OS 中研究 AES 安全性。我有 AES 库,它支持两种类型的加密/解密: 即时 固定键 在即时中,当我使用 key 加密数据时,会生成新 key 和加密数据。这个新生成的
关于 AES 有很多问题,但我有以下问题。我目前正在使用以下 AES 实现来加密数据 byte [] PRFkey = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
有没有人一起比较这些加密算法的优缺点? 最佳答案 使用 AES。 更多细节: DES 是七十年代的旧“数据加密标准”。它的 key 大小对于适当的安全性来说太短了(56 位有效位;这可以被强制执行,正
我的团队需要开发一种解决方案,以在用 Java 编写的 Android 应用程序的上下文中加密二进制数据(存储为 byte[])。加密后的数据将通过多种方式传输和存储,在此过程中不排除出现数据损坏的情
我在客户端使用 CryptoJS AES 算法加密文本,我在服务器端用 java 解密它,但出现异常。 JS代码: var encrypted = CryptoJS.AES.encrypt("Mess
我之所以问这个问题,是因为 2 天来我已经阅读了很多关于加密 AES 加密的帖子,就在我以为我明白了的时候,我意识到我根本没有明白。 这篇文章是最接近我的问题的,我有完全相同的问题但没有得到解答: C
我想知道 AES 加密后的数据大小,这样我就可以避免缓冲我的 AES 后数据(在磁盘或内存上)主要是为了知道大小。 我使用 128 位 AES 和 javax.crypto.Cipher 和 java
我是一名优秀的程序员,十分优秀!