我在文件 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
结果是验证成功,并且 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
有人可以告诉我有什么问题吗?请注意,如果我传递了一个签名数据消息,并且代码未更改,它就可以工作。我得到了验证成功和明文数据,但是当我发送一个明确的签名数据时,它失败了。请帮忙。