- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试使用 OpenSSL 提供的高级 API 进行加密工作。
通常情况下,它在这里工作得很好。
/**
* Instructions for generating private key file and self signed certificate file.
*
* openssl genrsa -des3 -out keys.pem 2048
* openssl rsa -in keys.pem -out rsa.pem
* openssl req -new -x509 -key rsa.pem -out rsa-cert.pem -days 9999
*
* Compile
* g++ -ggdb -o exe.bex src.cpp -lcrypto
*/
//c standard library
#include <stdio.h>
#include <string.h>
//openssl library
#include <openssl/pem.h>
#include <openssl/pkcs7.h>
#include <openssl/x509.h>
//c++ standard library
#include <iostream>
#include <string>
int main(int argc, char* argv[]) {
FILE* fd = fopen("rsa.pem", "r");
X509* x509;
STACK_OF(X509)* x509_stack = sk_X509_new_null();
EVP_PKEY* key;
if (NULL != fd)
{
key = PEM_read_PrivateKey(fd, NULL, NULL, NULL);
}
fd = fopen("rsa-cert.pem", "r");
if (NULL != fd)
{
while (NULL != (x509 = PEM_read_X509(fd, NULL, NULL, NULL)))
{
sk_X509_push(x509_stack, x509);
}
fclose(fd);
}
OpenSSL_add_all_algorithms();
while (!std::cin.eof()) {
std::string msg;
//get input text
printf("Message to PKCS7 encrypt: ");
fflush(stdout);
std::getline(std::cin, msg);
if (223 < msg.length())
{
// SMIME_read_PKCS7 bug, need to be fixed.
//
// bt:
//#0 asn1_d2i_read_bio (in=0x60bc40, pb=0x7fffffffe238) at a_d2i_fp.c:286
//#1 0x00007ffff7aeb762 in ASN1_item_d2i_bio (it=0x7ffff7dc2da0, in=0x60bc40, x=0x0) at a_d2i_fp.c:113
//#2 0x00007ffff7b0201c in b64_read_asn1 (bio=0x60bc40, it=0x7ffff7dc2da0) at asn_mime.c:191
//#3 0x00007ffff7b02dd0 in SMIME_read_ASN1 (bio=0x60af00, bcont=0x7fffffffe350, it=0x7ffff7dc2da0) at asn_mime.c:527
//#4 0x00007ffff7b39db2 in SMIME_read_PKCS7 (bio=0x60af00, bcont=0x7fffffffe350) at pk7_mime.c:96
//#5 0x0000000000401668 in main (argc=1, argv=0x7fffffffe4b8) at ./crypto-pkcs.cpp:99
//
std::cout << "string too long " << msg.length() << std::endl;
continue;
}
if (msg.empty())
{
std::cout << "string too short" << std::endl;
continue;
}
//save input
BIO* bio_input_plain_text = BIO_new(BIO_s_mem());
BIO_write(bio_input_plain_text, msg.c_str(), msg.length());
BIO_flush(bio_input_plain_text);
//create PKCS7 object in the way of PKCS7_encrypt.
PKCS7* pkcs7_encrypt = PKCS7_encrypt(x509_stack, bio_input_plain_text, EVP_aes_256_cbc(), 0);
if (NULL == pkcs7_encrypt) {
std::cout << "PKCS7_encrypt returns NULL" << std::endl; return -1;}
//dump encryped info.
BIO* bio_encrypted_smime = BIO_new(BIO_s_mem());
if (SMIME_write_PKCS7(bio_encrypted_smime, pkcs7_encrypt, bio_input_plain_text, 0) != 1){ std::cout << "SMIME_write_PKCS7 failed" << std::endl; return -1;}
BIO_flush(bio_encrypted_smime);
//get internal data address
const char* encrypted = NULL;
BIO_get_mem_data(bio_encrypted_smime, &encrypted); //encrypted has no new resource, only the reflection of the internal BIO data.
//char encrypted[8 * 1024] = "";
//copy BIO to char array
//BIO_read(bio_encrypted_smime, encrypted, sizeof encrypted - 1); //if we read the data out of BIO, later we need to write it back, BIO_read deletes the internal data inside BIO
std::cout << "PKCS7_encrypt length:" << strlen(encrypted) << std::endl << encrypted << std::endl;
//please be careful while taking care of BIO object.
//if we call BIO_read against BIO to get out data, the operation will cause the data deleted in the BIO at the same time.
//here we recover BIO data.
//BIO_write(bio_encrypted_smime, encrypted, strlen(encrypted));
//BIO_flush(bio_encrypted_smime);
BIO* bio_pkcs7 = BIO_new(BIO_s_mem());
//read&load PKCS7 object from SMIME format.
PKCS7* pkcs7_smime = SMIME_read_PKCS7(bio_encrypted_smime, &bio_pkcs7);
if (NULL == pkcs7_smime) {std::cout << "SMIME_read_PKCS7 returns NULL" << std::endl;return -1;}
BIO_flush(bio_pkcs7);
BIO* bio_pkcs7_decrypt = BIO_new(BIO_s_mem());
//decrypt in the way of PKCS7_decrypt
if (0 == PKCS7_decrypt(pkcs7_smime, key, x509, bio_pkcs7_decrypt, 0)){ std::cout << "PKCS7_decrypt failed" << std::endl;return -1;}
BIO_flush(bio_pkcs7_decrypt);
//char decrypted[8 * 1024] = "";
//dump decrypted data.
//BIO_read(bio_pkcs7_decrypt, decrypted, sizeof decrypted - 1);
const char* decrypted = NULL;
//get internal data address
BIO_get_mem_data(bio_pkcs7_decrypt, &decrypted);
std::cout << "PKCS7_decrypt length: " << strlen(decrypted) << std::endl << decrypted << std::endl;
//cleanup, idiot! donot forget to release resource you piece of shit!
BIO_free(bio_pkcs7_decrypt);
BIO_free(bio_pkcs7);
BIO_free(bio_encrypted_smime);
PKCS7_free(pkcs7_smime);
PKCS7_free(pkcs7_encrypt);
}
X509_free(x509);
sk_X509_pop_free(x509_stack, X509_free);
return 0;
}
这段代码适用于 openssl-1.0.1g。我尝试了线程和无线程配置选项。
但是如果我们输入一个 224 长度的纯文本而没有 if-continue 的东西,加密仍然有效,它无法在 SMIME_read_PKCS7 的方法中解密,查看上面的回溯评论。
在输入长度为223的情况下,加密后的S/MIME长度为1200。
输入224长度的情况下,S/MIME格式的加密结果长度超过1200,SMIME_read_PKCS7无法处理这个长度,内部调用查看上面的bt,但是我没有找到任何文档或页面解释。
SMIME_read_PKCS7 的 secret 是什么?
缺陷一:
在@jww 的帮助下。应该有
BIO_set_mem_eof_return(bio_encrypted_smime, 0);
之前
PKCS7* pkcs7_smime = SMIME_read_PKCS7(bio_encrypted_smime, &bio_pkcs7);
缺陷2:
BIO_get_mem_data 这个应该返回数据的长度,实际上我们需要根据长度处理 char*,不要只依赖空终止,除非你期望附加垃圾值。
最佳答案
What is the secret of SMIME_read_PKCS7?
嗯,真的没有 secret 。它只是 buggy 。根据 SMIME_read_PKCS7(3) 上的文档:
BUGS
The MIME parser used by SMIME_read_PKCS7() is somewhat primitive.
While it will handle most S/MIME messages more complex compound
formats may not work.
The parser assumes that the PKCS7 structure is always base64
encoded and will not handle the case where it is in binary
format or uses quoted printable format.
The use of a memory BIO to hold the signed content limits the
size of message which can be processed due to memory restraints:
a streaming single pass option should be available.
OpenSSL User Group about SMIME_read_PKCS7
上有一些不错的话题.
关于c++ - OpenSSL库中的SMIME_read_PKCS7方法有输入长度1200的限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23622837/
将 KLV 字符串拆分为键、长度、值作为元素的列表/元组的更有效方法是什么? 为了添加一点背景,前 3 位数字作为键,接下来的 2 位表示值的长度。 我已经能够使用以下代码解决该问题。但我不认为我的代
首先,我试图从文件中提取视频持续时间,然后在无需实际上传文件的情况下显示它。 当用户选择视频时 - 信息将显示在其下方,包括文件名、文件大小、文件类型。不管我的技能多么糟糕 - 我无法显示持续时间。我
我是 Scala 编程新手,这是我的问题:如何计算每行的字符串数量?我的数据框由一列 Array[String] 类型组成。 friendsDF: org.apache.spark.sql.DataF
我有一个React Web应用程序(create-react-app),该应用程序使用react-hook-forms上传歌曲并使用axios将其发送到我的Node / express服务器。 我想确
如果给你一个网络掩码(例如 255.255.255.0),你如何在 Java 中获得它的长度/位(例如 8)? 最佳答案 如果您想找出整数低端有多少个零位,请尝试 Integer.numberOfTr
我需要使用 jQuery 获取 div 数量的长度。 我可以得到它,但在两个单击事件中声明变量,但这似乎是错误的,然后我还需要使用它来根据数字显示隐藏按钮。我觉得我不必将代码加倍。 在这里摆弄 htt
我对此感到非常绝望,到目前为止我在 www 上找不到任何东西。 情况如下: 我正在使用 Python。 我有 3 个数组:x 坐标、y 坐标和半径。 我想使用给定的 x 和 y 坐标创建散点图。 到目
我有一个表单,我通过 jQuery 的加载函数动态添加新的输入和选择元素。有时加载的元素故意为空,在这种情况下我想隐藏容器 div,这样它就不会破坏样式。 问题是,我似乎无法计算加载的元素,因此不知道
我决定通过替换来使我的代码更清晰 if (wrappedSet.length > 0) 类似 if (wrappedSet.exists()) 是否有任何 native jq 函数可以实现此目的?或者
简单的问题。如果我有一个如下表: CREATE TABLE `exampletable` ( `id` int(11) NOT NULL AUTO_INCREMENT, `textfield`
我正在使用经典 ASP/MySQL 将长用户输入插入到我的数据库中,该输入是从富文本编辑器生成的。该列设置为 LONG-TEXT。 作为参数化查询(准备语句)的新手,我不确定用于此特定查询的数据长度。
我正在获取 Stripe 交易费用的值(value)并通过禁用的文本字段显示它。 由于输入文本域,句子出现较大空隙 This is the amount $3.50____________that n
我有一个 div,其背景图像的大小设置为包含。但是,图像是视网膜计算机(Macbook Pro 等)的双分辨率图像,所以我希望能够以某种方式让页面知道即使我说的是背景大小:包含 200x200 图像,
我正在开发一个具有“已保存”和“已完成”模块的小部件。当我删除元素时,它会从 dom 中删除/淡化它,但是当我将其标记为完成时,它会将其克隆到已完成的选项卡。这工作很棒,但顶部括号内的数字不适合我。这
我有一个来自 json 提要的数组,我知道在 jArray 中有一个联盟,但我需要计算出该数组的计数,以防稍后将第二个添加到提要中。目前 log cat 没有注销“teamFeedStructure”
目标:给定一个混合类型的数组,确定每个级别的元素数量。如果同一层有两个子数组,则它们的每个元素都计入该层元素的总数。 方法: Array.prototype.elementsAtLevels = fu
我需要帮助为 Java 中的单链表制作 int size(); 方法。 这是我目前所拥有的,但它没有返回正确的列表大小。 public int size() { int size = 0;
我正在为学校作业创建一个文件服务器应用程序。我目前拥有的是一个简单的 Client 类,它通过 TCP 发送图像,还有一个 Server 类接收图像并将其写入文件。 这是我的客户端代码 import
我有这对功能 (,) length :: Foldable t => t a -> b -> (Int, b) 和, head :: [a] -> a 我想了解的类型 (,) length he
我正在GitHub Pages上使用Jekyll来构建博客,并希望获得传递给YAML前题中Liquid模板的page.title字符串的长度,该字符串在每个帖子的YAML主题中。我还没有找到一种简单的
我是一名优秀的程序员,十分优秀!