在过去的两周里,我一直在试图使用OpenSSL在Swift 4中创建和验证CMS签名。我的代码最终注定要在Linux上运行,所以我不能使用macOS安全框架。我相信我终于让CMS签名创建正常工作了。我的代码如下:
let testBundle = Bundle(for: type(of: self))
guard let textUrl = testBundle.url(forResource: "test_message", withExtension: "txt"),
let signingKeyUrl = testBundle.url(forResource: "signing_key", withExtension: "pem"),
let signingCertUrl = testBundle.url(forResource: "signing_cert", withExtension: "pem") else {
exit(1)
}
let certFileObject = signingCertUrl.path.withCString { filePtr in
return fopen(filePtr, "rb")
}
defer {
fclose(certFileObject)
}
let keyFileObject = signingKeyUrl.path.withCString { filePtr in
return fopen(filePtr, "rb")
}
defer {
fclose(keyFileObject)
}
guard let key = PEM_read_PrivateKey(keyFileObject, nil, nil, nil),
let cert = PEM_read_X509(certFileObject, nil, nil, nil) else {
exit(1)
}
OpenSSL_add_all_ciphers()
OpenSSL_add_all_digests()
OPENSSL_add_all_algorithms_conf()
guard let textData = FileManager.default.contents(atPath: textUrl.path) else {
exit(1)
}
guard let textBIO = BIO_new(BIO_s_mem()) else {
print("Unable to create textBIO")
exit(1)
}
_ = textData.withUnsafeBytes({dataBytes in
BIO_write(textBIO, dataBytes, Int32(textData.count))
})
guard let cms = CMS_sign(cert, key, nil, textBIO, UInt32(CMS_BINARY)) else {
exit(1)
}
当我调试此代码时,我发现在cms
调用之后正在设置CMS_sign
对象,所以我相信签名是正确生成的。在此之后,我正在尝试验证我刚刚创建的签名。该代码如下所示:
let store = X509_STORE_new()
X509_STORE_add_cert(store, cert)
let outBIO = BIO_new(BIO_s_mem())
let result = CMS_verify(cms, nil, store, nil, outBIO, 0)
print("result : \(result)")
if result != 1 {
let errorCode: UInt = ERR_get_error()
print("ERROR : \(String(format: "%2X", errorCode))")
}
但是,当我运行此代码时,result
== 0,表示错误。 OpenSSL返回的错误代码是0x2E099064
。我运行了这个命令:
openssl errstr 0x2E099064
这给了我关于错误的信息:
错误:2E099064:CMS例程:func(153):reason(100)
经过一番挖掘,我认为该错误对应于PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH。我从pkcs7.h file here.我得到的不是100%,这是正确的错误信息。
我的问题是,为什么我的签名验证失败了?我使用完全相同的证书来验证签名。所有这些代码都是内联的,所以任何地方都没有丢失。你们中的任何人都可以告诉我哪里出了问题吗?