我在文件testSmimeMsg.txt中输入了这样的消息:
ABC is our biggest acquisition ever and as you can imagine, customers
and partners alike are eager to hear how we plan to integrate it into
XYZ. Specifically, how are we going to bring the two traditionally
separate silos of desktop and mobile together?
To help explain our vision for uniting we released a
video describing our architecture and
technology integration plans. Definitely watch the video to learn more,
and the rest of this blog will give you a summary of our plans and a bit
more color on certain areas.
我使用以下命令制作一个明确的签名消息:
$ openssl smime -sign -in testSmimeMsg.txt -out testSmimeClearTextMessage.txt -signer sender.pem
sender.pem是从.p12文件生成的,它具有CERTIFICATE和RSA PRIVATE KEY内容。 然后我使用以下命令验证我刚刚创建的签名消息。
$ openssl smime -verify -in testSmimeClearTextMessage.txt -noverify -out testSmimeVerifiedClearTextMessage.txt
结果是Verification Successful,testSmimeVerifiedClearTextMessage.txt中的内容与testSmimeMsg.txt相同。完善! 现在假设我想通过PKCS7_verify()方法验证相同的内容。 C代码
jbyteArray aw_SMIME_Verify_Signature_And_Get_Message(JNIEnv *env, jobject obj, jbyteArray signedMsg, jstring senderCertPath, jstring rootCertPath)
{
//SenderCertPath and rootCertPath are currently NULL. For now, I just want openssl
//to extract the signer cert from message and verify message. Root certificate and chain
//of trust verification etc is ignored for now.
jbyteArray cmsContent = NULL;
PKCS7 *pkcs7 = NULL;
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
ERR_load_X509_strings();
ERR_load_PKCS7_strings();
ERR_load_BIO_strings();
pkcs7 = getP7FromEncryptedMessage_SMIME(env, signedMsg); //this works. pkcs7 is non null.
if (pkcs7 == NULL) {
LOGE ("aw_SMIME_Verify_Signature_And_Get_Message: Error reading p7 from message. Returning");
goto exit_free;
}
cmsContent = verify_Signature_And_Get_Message(env, pkcs7, senderCertPath, rootCertPath);
exit_free:
if (pkcs7) {
PKCS7_free(pkcs7);
pkcs7 = NULL;
}
return cmsContent;
}
------------------------------
PKCS7 *getP7FromEncryptedMessage_SMIME(JNIEnv *env, jbyteArray encryptedSMIMEMessage) {
BIO *in = NULL;
int encryptedMessageLength = 0;
const unsigned char *encryptedBuf = NULL;
PKCS7 *p7 = NULL;
//obtain the p7 structure from the encrypted message
encryptedMessageLength = env->GetArrayLength(encryptedSMIMEMessage); //get size of encrypted message byte[]
encryptedBuf = (const unsigned char *)env->GetByteArrayElements(encryptedSMIMEMessage, 0); //create a buffer of that size
in = BIO_new(BIO_s_mem());
BIO_set_mem_eof_return(in, 0);
BIO_write(in, encryptedBuf, encryptedMessageLength); //create a BIO with the char* of encrypted message
p7 = SMIME_read_PKCS7(in, NULL); //get the p7 structure
if(in) {
BIO_free(in);
}
if (encryptedBuf) {
env->ReleaseByteArrayElements(encryptedSMIMEMessage, (jbyte *)encryptedBuf, 0);
}
return p7;
}
----------------------
jbyteArray verify_Signature_And_Get_Message(JNIEnv *env, PKCS7 *pkcs7, jstring senderCertPath, jstring rootCertPath)
{
X509* rootCert = NULL;
X509* senderCert = NULL;
STACK_OF(X509) *st1 = NULL;
X509_STORE* m_store = NULL;
BIO *out = BIO_new(BIO_s_mem());
BIO_set_fp(out, stdout, BIO_NOCLOSE);
BUF_MEM *bptr = NULL;
jbyteArray cmsContent = NULL;
int cmsLen = 0;
if(rootCertPath != NULL) {
rootCert = getCertificateFromPath(env, rootCertPath);
m_store = X509_STORE_new();
//TODO: check what to be in cert store
X509_STORE_add_cert(m_store,rootCert);
}
if(senderCertPath != NULL) {
senderCert = getCertificateFromPath(env, senderCertPath);
st1 = sk_X509_new_null();
sk_X509_push(st1, senderCert);
}
//st1 and m_store are NULL as they are not used for now.
int verifyResult = PKCS7_verify( pkcs7, st1, m_store, NULL, out, PKCS7_NOVERIFY);
if(verifyResult != 1) { //FAILS HERE!!!!
LOGE ("verify_Signature_And_Get_Message: Error verifying signer certificate. Returning");
LOGE(ERR_error_string(ERR_get_error(), NULL));
goto exit_free;
}
BIO_get_mem_ptr(out, &bptr);
cmsLen = bptr->length;
cmsContent = env->NewByteArray(cmsLen);
env->SetByteArrayRegion(cmsContent, 0, cmsLen, (jbyte *)bptr->data);
exit_free:
if (serverCert) {
X509_free(serverCert);
serverCert = NULL;
}
if (rootCert) {
X509_free(rootCert);
rootCert = NULL;
}
if (m_store) {
X509_STORE_free(m_store);
m_store = NULL;
}
if (st1) {
sk_X509_pop_free(st1, X509_free);
}
if (out) {
BIO_free_all(out);
out = NULL;
}
return cmsContent;
}
运行时,我收到错误:
verify_Signature_And_Get_Message: Error verifying signer certificate. Returning
error:2107507A:PKCS7 routines:PKCS7_verify:no content
有人可以告诉我什么是错的吗? 请注意,如果我传递了签名数据消息,但代码保持不变,则可以正常工作。我得到了验证成功和明文数据,但是当我发送明确的签名数据时,它就失败了。 请帮忙。
答案 0 :(得分:0)
我解决了这个问题。问题是我没有使用PKCS7_read_SMIME()API的content参数。如果消息是明确签名的,则在此参数中返回消息内容,然后需要将该消息内容与NODETACHED标志一起传递给PKCS7_verify()方法。有关更多详细信息,请参阅两个API的opeenssl doc。