#ios #swift #security #openssl
#iOS #swift #Безопасность #openssl
Вопрос:
Я обмениваюсь данными с устройством, которое требует шифрования. Согласно инструкциям, мое приложение для iOS генерирует 2048-битную пару открытого и закрытого ключей RSA, и я отправляю устройству открытый ключ.
Я создал пару открытых и закрытых ключей, используя командную строку macOS openssl
, показанную здесь (поскольку я не могу понять, как заставить iOS это сделать, но это вопрос будущего):
openssl req -x509 -newkey rsa:2048 -out cert.pem
openssl x509 -in cert.pem -noout -pubkey
Я скопировал значения из cert.pem
закрытого и открытого ключей в свое приложение:
let certificate = "MIIDej....GWB"
let privateKey = "MIIFhz...Q=="
let publicKey = "MIIBI...AQAB"
Когда я отправляю устройству открытый ключ, устройство удовлетворено и отправляет обратно данные в AES-128, зашифрованные с использованием открытого ключа, который я отправил.
Я здесь над головой, но я тот, кто пытается заставить это устройство работать.
Есть ли способ использовать закрытый ключ или сертификат, который я установил как String
s в своем приложении, для декодирования данных, поступающих с устройства?
Я просматривал документы по безопасности и CryptoKit, и у меня кружится голова.
FWIW, я смог использовать SecCertificateCreateWithData
набор строк из cert.pem
файла и прочитать часть его информации, например, сводку. Но я понятия не имею, как применить закрытый ключ или использовать сертификат для декодирования данных. Мне нужны как заметки для чайников или что-то в этом роде.
Спасибо.
Комментарии:
1. «отправляет обратно данные в AES-128, зашифрованные с использованием открытого ключа», невозможно. AES не использует открытые ключи. Он использует симметричные ключи, которые совершенно разные. Не существует единого стандартного способа реализации того, что вы описываете (существует несколько официальных стандартов, но многие системы являются специальными). Правильный способ обработки этого в значительной степени зависит от точного протокола, который реализует сервер. В идеале у вас есть документ, описывающий это. Если нет, то полный код сервера. (К сожалению, реализация специальных протоколов часто требует консультаций, а не вопросов переполнения стека.)
2. Спасибо. Я просто вставил то, что указано в документации, которую мне дали. Я постараюсь найти авторов и работать оттуда. Спасибо.
Ответ №1:
В документации Apple описано, как сгенерировать пару ключей на стороне iOS.
Пример:
let tag = "com.example.keys.mykey".data(using: .utf8)!
let attributes: [String: Any] =
[kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeySizeInBits as String: 2048,
kSecPrivateKeyAttrs as String:
[kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: tag]
]
var publicKey: SecKey?
var privateKey: SecKey?
SecKeyGeneratePair(attributes, amp;publicKey, amp;privateKey)
Дополнительные атрибуты доступны здесь.
И затем вы можете получить внешние представления закрытого или открытого ключа, используя метод: SecKeyCopyExternalRepresentation.
Пример:
var error: Unmanaged<CFError>?
SecKeyCopyExternalRepresentation(secKey, amp;error) as Data?
Для расшифровки данных AES-128 вам необходимо использовать CCCrypt
. Здесь у вас есть пример из службы поддержки Apple, как данные шифруются, но для расшифровки данных вам нужно изменить первый аргумент на kCCDecrypt
.
Пример:
extern NSData * SecDecryptAES128CBCPad(NSData * data, NSData * key, NSData * iv) {
CCCryptorStatus err;
NSMutableData * resu<
size_t resultLength;
NSCParameterAssert(key.length == kCCKeySizeAES128);
NSCParameterAssert(iv.length == kCCBlockSizeAES128);
// Padding can expand the data, so we have to allocate space for that. The rule for block
// cyphers, like AES, is that the padding only adds space on encryption (on decryption it
// can reduce space, obviously, but we don't need to account for that) and it will only add
// at most one block size worth of space.
result = [[NSMutableData alloc] initWithLength:[data length] kCCBlockSizeAES128];
err = CCCrypt(
kCCDecrypt,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
key.bytes, key.length,
iv.bytes,
data.bytes, data.length,
result.mutableBytes, result.length,
amp;resultLength
);
assert(err == kCCSuccess);
// Set the output length to the value returned by CCCrypt. This is necessary because
// we have padding enabled, meaning that we might have allocated more space than we needed.
[result setLength:resultLength];
return resu<
}
Аргументы в CCCrypt
методе (например kCCOptionPKCS7Padding
, iv
), которые вам нужно настроить в соответствии с вашим примером.
Комментарии:
1. Спасибо за подсказку по расшифровке. Генерация пары ключей не работает для этого устройства. Мне сказали, что мне нужны ключи PKCS8 и X509. Открытый ключ, сгенерированный
SecKeyGeneratePair
устройством, не распознается устройством, поэтому я прибегнул к поиску решения для macOS черезopenssl
. Я читал, что iOS, как известно, сложно использовать с сервисами, отличными от Apple, требующими зашифрованного обмена данными. Однако я попытаюсь выяснить, работает ли ваше решение с данными, возвращаемыми устройством. Спасибо.2. @P.Ent Но помните, что использование закрытого ключа в виде простой строки в вашем коде представляет угрозу безопасности (когда приложение доступно публично), потому что его легко получить из двоичного файла с помощью обратного проектирования. Например, дизассемблер хоппера доступен бесплатно, и когда двоичный файл будет загружен в эту программу, все строки будут исключены из вашего кода и будут видны.
3. Я согласен. Поскольку я не могу понять, как заставить iOS генерировать открытый ключ, приемлемый для этого устройства, я помещаю их в приложение в виде строк, чтобы перейти к следующему шагу, который заключается в кодировании / декодировании данных с устройства. Но я понятия не имею, что я делаю, но мне поручено выполнить эту работу. Я просто хотел бы знать, могу ли я использовать эти простые строки. Если нет, я понятия не имею, что делать, кроме как получить степень в области криптографии.
4. Да, потому что, как описано в документах SecKeyCopyExternalRepresentation, он возвращает
PKCS #1
формат. Итак, вам нужно найти решение для преобразования его в PKCS8. Здесь у вас есть документация rfc о том, как должен выглядеть этот формат, а также тема на форуме Apple об этом.