- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
所以我花了几个小时浏览谷歌搜索结果和一些与 openssl 函数相关的联机帮助页,试图找出如何使用 EVP 函数和 3DES 加密。现在我的代码正在使用 <openssl/des.h>
中的这些函数:
DES_ede2_cbc_encrypt()
DES_set_odd_parity()
DES_set_key_checked()
DES_ecb2_encrypt()
我的理解是,通过使用 EVP 函数,我可以统一处理 3DES 的 ECB 和 CBC 模式之间的加密/解密逻辑(我上面列表中的第一个和最后一个函数)。两者管理输入/输出数据的方式不同。
我找不到任何通过高级 EVP 函数进行 DES 加密的示例。在evp.h
header ,我看到类似 EVP_des_ede3_ecb
的内容和 EVP_des_ede3_cbc
,但我不确定如何使用它们。由于您必须以一种奇怪的方式为 DES 设置 key (使用上面列表中间的 2 个函数),我不确定在 EVP 方式中加载 key 会是什么样子。
如何将 DES 与 EVP 一起使用?如果有人可以提供真正有帮助的加密、解密和 key 设置示例。我试图用 C++ 包装所有这些类似 C 的代码,并尽可能使用 STL 对象/算法。我希望我的“DES”包装器在 DES 的不同密码模式之间在语义上相同。我不确定这是否可行,但这就是我尝试使用 EVP 的原因。
最佳答案
我觉得你想做的应该是可以的。 EVP API 非常注重使用所有参数来初始化上下文对象,然后在不知道其中内容的情况下使用上下文对象。您甚至可能受益于 OpenSSL 允许您提供不需要的参数...例如在为 ECB 模式初始化上下文时提供 IV(将被忽略)。
在进入 EVP 版本之前,让我们先谈谈您发布的功能。
OpenSSL 将 DES key 的生成分为三个步骤:
第一步是使用任何合适的 (N/D)RBG(OpenSSL 提供 RAND_DRBG_bytes
和 RAND_bytes
)。第二步出现是因为 DES key 的某些位对密码强度没有贡献;因此按照惯例,它们被设置为给出 key 奇偶校验的字节。这是DES_set_odd_parity
的功能(有关更多解释,请参阅 https://crypto.stackexchange.com/questions/34199/purpose-of-des-parity-bits。)最后一步在 OpenSSL 中有几个选项:(a) 相信用户已经提供了一个好的 key ,然后展开它;或者 (b) 检查用户提供的内容以确保它不是弱 key ,并在展开 key 计划之前检查它是否具有奇校验。后者由您列出的函数执行,DES_set_key_checked
.前者更信任的版本是 DES_set_key_unchecked
.
好的,那么为什么这一切有用呢?好吧,这一切在 API 的 EVP 版本中都有一个直接模拟。使用 DES 函数,您可以执行以下操作:
RAND_bytes
(或等价物)制作随 secret 钥DES_set_odd_parity
设置奇偶校验位DES_set_key_checked
展开关键时间表DES_<mode>_encrypt
使用展开的 key 计划进行加密使用 EVP,您将执行以下(大部分)等效步骤:
调用 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, dest_buf)
生成适合 EVP_CIPHER_CTX *ctx
的密码的随 secret 钥已经初始化。此步骤还通过调用 DES_set_odd_parity
在后台设置奇校验。 .请注意,假定 dest_buf 足够大以容纳 ctx
的 key 类型。被配置为。参见 https://github.com/openssl/openssl/blob/master/crypto/evp/e_des3.c 中的第 280 行
调用 EVP_EncryptInit
传递调用 DES_set_key_unchecked
的 key 在引擎盖下展开关键计划并将其存储在上下文中。请注意,这是 set-key 的 unchecked 变体; EVP API 只是假定您提供了一个好的 key 。参见 https://github.com/openssl/openssl/blob/master/crypto/evp/e_des3.c 中的第 226 行(对于 2 键 ede)
注意鸡和蛋的小问题:你必须用算法类型初始化上下文,这样它就知道要生成什么样的 key ;并且您必须提供 key 来初始化上下文。 EVP_*Init 优雅地处理 NULL 参数,因此它允许您部分初始化。例如,
uint8_t twokey[16];
EVP_EncryptInit(ctx, EVP_des_ede_cbc(), NULL, NULL);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, twokey);
EVP_EncryptInit(ctx, NULL, twokey, iv);
另请注意,如果您已有 key ,则不需要 OpenSSL 来随机生成 key 。 EVP_EncryptInit
非常乐意相信您提供的任何 key 。
这是一个使用硬编码 key 的相当长的示例,但使用 openssl 函数来更正其奇偶校验。
#include <openssl/evp.h>
#include <openssl/des.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
int res;
uint8_t key[16] = {
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87, 0x98
};
uint8_t iv[8] = {
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0
};
uint8_t message[16] = {0,1,2,3,4,5,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf};
uint8_t ciphertext[24] = {0}; //leave room for padding!
int ciphertext_total = 0;
uint8_t decrypted [16] = {0};
int decrypted_total = 0;
//Select our cipher of choice: 2-key 3DES in CBC mode (hence the IV)
const EVP_CIPHER *tdea_ede = EVP_des_ede_cbc();
printf("hardcoded key: ");
{
int i;
for(i=0; i< (int)sizeof(key); i++)
{
printf("%02x ", key[i]);
}
printf("\n");
}
//Note I have to set parity on each of the keys, and I'm doing 2-key 3DES
//DES_cblock is an annoying typdef of uchar[8]
DES_set_odd_parity((DES_cblock *)key);
DES_set_odd_parity((DES_cblock *)(key+8));
printf("key with odd parity: ");
{
int i;
for(i=0; i< (int)sizeof(key); i++)
{
printf("%02x ", key[i]);
}
printf("\n");
}
printf("Message: ");
{
int i;
for(i=0; i< (int)sizeof(message); i++)
{
printf("%02x ", message[i]);
}
printf("\n");
}
/* encrypt */
{
int outl = 0;
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit(ctx, tdea_ede, key, iv);
res = EVP_EncryptUpdate(ctx, ciphertext, &outl, message, (int)sizeof(message));
printf("Update wrote %d bytes\n", outl);
ciphertext_total += outl;
EVP_EncryptFinal(ctx, ciphertext + ciphertext_total, &outl);
printf("Final wrote %d bytes\n", outl);
ciphertext_total += outl;
}
printf("Ciphertext: ");
{
int i;
for(i=0; i<ciphertext_total; i++)
{
printf("%02x ", ciphertext[i]);
}
printf("\n");
}
/* decrypt */
{
int outl = 0;
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_DecryptInit(ctx, tdea_ede, key, iv);
res = EVP_DecryptUpdate(ctx, decrypted, &outl, ciphertext, ciphertext_total );
printf("Update wrote %d bytes\n", outl);
decrypted_total += outl;
EVP_DecryptFinal(ctx, decrypted + decrypted_total, &outl);
printf("Final wrote %d bytes\n", outl);
decrypted_total += outl;
}
printf("Decrypted: ");
{
int i;
for(i=0; i<decrypted_total; i++)
{
printf("%02x ", decrypted[i]);
}
printf("\n");
}
}
它的输出是:
$ ./a.out
hardcoded key: 11 22 33 44 55 66 77 88 21 32 43 54 65 76 87 98
key with odd parity: 10 23 32 45 54 67 76 89 20 32 43 54 64 76 86 98
Message: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
Update wrote 16 bytes
Final wrote 8 bytes
Ciphertext: 5d f9 44 ff 82 0b c3 47 90 be 11 fb 62 01 15 f0 65 45 f6 05 3f fa 81 96
Update wrote 16 bytes
Final wrote 0 bytes
Decrypted: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
我承认,我很惊讶地看到密文比消息大,但后来我想起了 OpenSSL 默认应用填充。
如果您不熟悉 EVP API 的初始化/更新/最终模型,请注意它是为流设计的。您可以根据需要多次调用更新,只有当它获得足够的数据来处理一个 block 时,您才会看到它写入任何输出。这就是为什么会有“final”……填充任何剩余数据并处理最后一个 block (如果有人在飞行中)。
另外,请注意该示例泄漏了 EVP_CIPHER_CTX 对象......这些对象应该在某个时候被释放。
关于c++ - 如何使用具有低级 DES 函数的 openssl EVP 库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49310030/
我在网上搜索但没有找到任何合适的文章解释如何使用 javascript 使用 WCF 服务,尤其是 WebScriptEndpoint。 任何人都可以对此给出任何指导吗? 谢谢 最佳答案 这是一篇关于
我正在编写一个将运行 Linux 命令的 C 程序,例如: cat/etc/passwd | grep 列表 |剪切-c 1-5 我没有任何结果 *这里 parent 等待第一个 child (chi
所以我正在尝试处理文件上传,然后将该文件作为二进制文件存储到数据库中。在我存储它之后,我尝试在给定的 URL 上提供文件。我似乎找不到适合这里的方法。我需要使用数据库,因为我使用 Google 应用引
我正在尝试制作一个宏,将下面的公式添加到单元格中,然后将其拖到整个列中并在 H 列中复制相同的公式 我想在 F 和 H 列中输入公式的数据 Range("F1").formula = "=IF(ISE
问题类似于this one ,但我想使用 OperatorPrecedenceParser 解析带有函数应用程序的表达式在 FParsec . 这是我的 AST: type Expression =
我想通过使用 sequelize 和 node.js 将这个查询更改为代码取决于在哪里 select COUNT(gender) as genderCount from customers where
我正在使用GNU bash,版本5.0.3(1)-发行版(x86_64-pc-linux-gnu),我想知道为什么简单的赋值语句会出现语法错误: #/bin/bash var1=/tmp
这里,为什么我的代码在 IE 中不起作用。我的代码适用于所有浏览器。没有问题。但是当我在 IE 上运行我的项目时,它发现错误。 而且我的 jquery 类和 insertadjacentHTMl 也不
我正在尝试更改标签的innerHTML。我无权访问该表单,因此无法编辑 HTML。标签具有的唯一标识符是“for”属性。 这是输入和标签的结构:
我有一个页面,我可以在其中返回用户帖子,可以使用一些 jquery 代码对这些帖子进行即时评论,在发布新评论后,我在帖子下插入新评论以及删除 按钮。问题是 Delete 按钮在新插入的元素上不起作用,
我有一个大约有 20 列的“管道分隔”文件。我只想使用 sha1sum 散列第一列,它是一个数字,如帐号,并按原样返回其余列。 使用 awk 或 sed 执行此操作的最佳方法是什么? Accounti
我需要将以下内容插入到我的表中...我的用户表有五列 id、用户名、密码、名称、条目。 (我还没有提交任何东西到条目中,我稍后会使用 php 来做)但由于某种原因我不断收到这个错误:#1054 - U
所以我试图有一个输入字段,我可以在其中输入任何字符,但然后将输入的值小写,删除任何非字母数字字符,留下“。”而不是空格。 例如,如果我输入: 地球的 70% 是水,-!*#$^^ & 30% 土地 输
我正在尝试做一些我认为非常简单的事情,但出于某种原因我没有得到想要的结果?我是 javascript 的新手,但对 java 有经验,所以我相信我没有使用某种正确的规则。 这是一个获取输入值、检查选择
我想使用 angularjs 从 mysql 数据库加载数据。 这就是应用程序的工作原理;用户登录,他们的用户名存储在 cookie 中。该用户名显示在主页上 我想获取这个值并通过 angularjs
我正在使用 autoLayout,我想在 UITableViewCell 上放置一个 UIlabel,它应该始终位于单元格的右侧和右侧的中心。 这就是我想要实现的目标 所以在这里你可以看到我正在谈论的
我需要与 MySql 等效的 elasticsearch 查询。我的 sql 查询: SELECT DISTINCT t.product_id AS id FROM tbl_sup_price t
我正在实现代码以使用 JSON。 func setup() { if let flickrURL = NSURL(string: "https://api.flickr.com/
我尝试使用for循环声明变量,然后测试cols和rols是否相同。如果是,它将运行递归函数。但是,我在 javascript 中执行 do 时遇到问题。有人可以帮忙吗? 现在,在比较 col.1 和
我举了一个我正在处理的问题的简短示例。 HTML代码: 1 2 3 CSS 代码: .BB a:hover{ color: #000; } .BB > li:after {
我是一名优秀的程序员,十分优秀!