我嘗試寫一個郵件聊天器來用S/MIME簽名郵件。到目前爲止,我已經完成了代碼簽署郵件。我在openssl中使用了demos/smime代碼示例來完成這項工作。不幸的是,這些例子演示瞭如何將輸入消息寫入輸出文件,但我需要將結果作爲字符串。如何將PKCS7_sign結果轉換爲char *或std :: string
這是我的SMIME-方法:
void Smime::sign() {
if (!isLoaded())
return;
// Null-mailer or unknown
if (mailFrom.empty())
return;
auto *client = util::mlfipriv(ctx);
bool signedOrEncrypted = false;
std::vector<std::string> contentType;
contentType.push_back("multipart/signed");
contentType.push_back("multipart/encrypted");
contentType.push_back("application/pkcs7-mime");
if (client->sessionData.count("Content-Type") == 1) {
std::string value {client->sessionData["Content-Type"]};
std::size_t found;
for (int i=0; i<contentType.size(); i++) {
found = value.find(contentType.at(i));
if (found != std::string::npos) {
signedOrEncrypted = true;
break;
}
}
}
if (signedOrEncrypted) {
const char logmsg[] = "Message already signed or encrypted";
syslog(LOG_NOTICE, "%s", logmsg);
return;
}
/*
* TODO:
* Catch more cases, where an email already could have been encrypted
* or signed elsewhere.
*/
mapfile::Map email {mailFrom};
auto cert = fs::path(email.getSmimeFilename<mapfile::Smime::CERT>());
auto key = fs::path(email.getSmimeFilename<mapfile::Smime::KEY>());
if (!fs::exists(cert) && !fs::is_regular(cert))
return;
if (!fs::exists(key) && !fs::is_regular(key))
return;
// Signing starts here
BIO *in = nullptr, *out = nullptr, *tbio = nullptr;
X509 *scert = nullptr;
EVP_PKEY *skey = nullptr;
PKCS7 *p7 = nullptr;
int flags = PKCS7_DETACHED | PKCS7_STREAM;
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
// S/MIME certificate
tbio = BIO_new_file(cert.string().c_str(), "r");
if (!tbio) {
std::cerr << "Error: BIO_new_file(Cert) failed" << std::endl;
return;
}
scert = PEM_read_bio_X509(tbio, nullptr, 0, nullptr);
// S/MIME key
tbio = BIO_new_file(key.string().c_str(), "r");
if (!tbio) {
std::cerr << "Error: BIO_new_file(Key) failed" << std::endl;
return;
}
skey = PEM_read_bio_PrivateKey(tbio, nullptr, 0, nullptr);
if (!scert || !skey) {
std::cerr << "Error: Neither cert or key was loaded" << std::endl;
return;
}
// Loading mail content from temp file
in = BIO_new_file(client->getTempFile().c_str(), "r");
if (!in) {
std::cerr << "Error: Unable to load content from temp file"
<< std::endl;
return;
}
// Signing
p7 = PKCS7_sign(scert, skey, nullptr, in, flags);
if (!p7) {
std::cerr << "Error: Message could not be signed" << std::endl;
return;
}
// Cleanup
PKCS7_free(p7);
X509_free(scert);
EVP_PKEY_free(skey);
BIO_free(in);
BIO_free(out);
BIO_free(tbio);
smimeSigned = true;
}
由於有超過1600人頁OpenSSL的,我不知道到哪裏尋找信息。我很樂意使用「p7」並將它寫入一個簡單的std :: string(或char *,如果需要的話)。我編寫的milter應用程序將拾取此字符串並執行更改主體(尚未寫入,但這是我的想法)。
有人可以指點我的例程/手冊頁,或有代碼示例可以幫助我嗎?
在此先感謝
,我不相信你可以把它放在一個'字符*'因爲有可能是嵌入式'NULL',這將截斷結果。 – jww
示例代碼調出= BIO_new_file(「smout.txt」,「w」); ... SMIME_write_PKCS7(out,p7,in,flags) 結果是base64編碼。我很確定,只有一兩個職能可以完成這項工作。但是哪個? :-) –