Swift (Linux): извлечение сертификатов CMS/PKCS#7 и проверка подписи контейнера?
Я пишу набор сервисов в Swift 4, которые будут работать на Linux. Одна из вещей, которые мне нужно сделать, это получить полезную нагрузку, которая подписана цифровой подписью с использованием формата синтаксиса криптографических сообщений (CMS), извлечь сертификат, используемый для его подписания, а затем проверить подпись. Я знаю, что Swift в Linux не содержит фреймворка безопасности или CommonCrypto для такого рода вещей, поэтому я связался с OpenSSL, чтобы попытаться помочь с этим. I'm about 2 years removed from my C / C++ Программирование дней, поэтому я с готовностью признаю, что я в этой части кода.
у меня есть 2 простых класса, чтобы действовать как обертки для OpenSSL BIO
и PKCS7
структуры данных. Они выглядят так:
import Foundation
import OpenSSL
public final class BIOWrapper {
public var bio = BIO_new(BIO_s_mem())
public init(data: Data) {
data.withUnsafeBytes { pointer -> Void in
BIO_write(self.bio, pointer, Int32(data.count))
}
}
public init() {}
deinit {
BIO_free(self.bio)
}
}
public final class PKCS7Wrapper {
public var pkcs7: UnsafeMutablePointer<PKCS7>
public init(pkcs7: UnsafeMutablePointer<PKCS7>) {
self.pkcs7 = pkcs7
}
deinit {
PKCS7_free(self.pkcs7)
}
}
Я могу успешно извлечь данные контейнера PKCS#7 и проверить, что значение кода типа данных NID_pkcs7_signed
используя этот код:
let reqData = Data(bytes: reqBytes)
guard reqData.count > 0 else {
print("Empty request body")
return nil
}
let bioWrapper = BIOWrapper(data: reqData)
guard let container = d2i_PKCS7_bio(bioWrapper.bio, nil) else {
print("No container")
return nil
}
let pkcs7Wrapper = PKCS7Wrapper(pkcs7: container)
let dataTypeCode = OBJ_obj2nid((pkcs7Wrapper.pkcs7.pointee.d.sign).pointee.contents.pointee.type)
print("dataTypeCode : (dataTypeCode)")
if dataTypeCode == NID_pkcs7_data {
print("GOT DATA!")
} else {
print("Didn't get data")
return nil
}
let pkcs7SignedTypeCode = OBJ_obj2nid(pkcs7Wrapper.pkcs7.pointee.type)
if let signed = pkcs7SignedTypeCode == NID_pkcs7_signed {
print("Signed : (signed)")
}
тем не менее, я достиг точки, где я застрял. Как я могу получить данные сертификата X. 509 от полезная нагрузка PKCS#7? Я вижу, что pkcs7Wrapper.pkcs7.pointee.d.sign.pointee.cert
структура данных должна содержать данные цепочки сертификатов. Его тип данных UnsafeMutablePointer<stack_st_x509>
и я думаю, что могу выяснить код для использования OpenSSL PKCS7_verify
метод, как только я получаю данные сертификата X. 509 в памяти. Я просто не знаю, как это сделать.
нашел на этом ресурсе это говорит о проверке квитанций на OSX/iOS, которая затрагивает многие из тех же вопросов. Они получают сертификат X. 509 из файловой системы и передайте данные в PKCS7_verify
метод. Мне просто нужно знать, как получить данные сертификата из контейнера PKCS#7 для передачи.
может кто-нибудь помочь мне с этим? Я признаю, что вызов C из Swift не идеален, но в отсутствие хорошей структуры безопасности/криптографии для Swift я не знаю никаких других вариантов.
1 ответов
основная часть ответа находится в коде, который вы связали:
let store = X509_STORE_new()
X509_STORE_add_cert(store, appleRootX509)
OpenSSL_add_all_digests()
let result = PKCS7_verify(receiptPKCS7, nil, store, nil, nil, 0)
if result != 1 {
log.atLevelDebug(id: 0, source: "Main", message: "Receipt signature verification failed")
exit(errorCode)
}
Кажется, вам не хватает того факта, что вам не нужно самостоятельно извлекать сертификат X509 из данных PKCS7. The PKCS7_verify
функция сделает это в рамках проверки:
предпринята попытка найти все сертификаты подписавшего, сначала посмотрев в параметре certs (если он не равен NULL), а затем посмотрев в любых сертификатах, содержащихся в p7 сама структура. Если не удается найти сертификаты подписавшего, операция завершается неудачно.
поэтому единственным сертификатом, который вам нужно загрузить, является корневой сертификат, который вы заметили, что они загружают из файловой системы в связан код.
Если вам все еще нужно быстрое решение для извлечения сертификата из данных PKCS7 по какой-то причине, вам придется создать ASN.1 анализатор для pkcs7 в. Не уверен, что это легко доступно для Свифта,этот простой код что быстрый поиск дал, и этой хорошее описание данных PKCS7.