Я пытаюсь отправить зашифрованные сообщения с помощью AES-GCM между приложением iOS и микроконтроллером ESP. Но прежде чем сделать это, мне нужно выполнить обмен ключами между двумя устройствами, чтобы у них обоих был общий секрет. Итак, я изучаю iOS методы для генерации пар ключей private / publi c и их несколько. Однако есть одна проблема: ключи, сгенерированные iOS, не могут быть легко совместимы с чем-либо за пределами iOS (насколько я понимаю), что означает, что я должен прыгнуть и внести некоторые изменения в ключи. Я заметил, что генерируемые ключи всегда abdc1234
, где abcd
никогда не меняется и 1234
меняется каждый раз, когда генерируется ключ. Поэтому я предполагаю, что abcd
- это просто то, что iOS использует, а 1234
- фактический ключ. По крайней мере, так происходит в Android. Поэтому, чтобы проверить свою гипотезу, я пытаюсь получить необработанные байты ключа publi c, сгенерированного в iOS, чтобы я мог отрезать abcd
и отправить фактический ключ 1234
в ESP. Проблема в том, что я не могу найти, как получить доступ к байту, который содержит ключ. Вот что я попробовал до сих пор ...
let tag = "".data(using: .utf8)!
let attributes: [String: Any] = [
kSecAttrType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeySizeInBits as String: 256,
kSecPrivateKeyAttrs as String: [
kSecAttrIsPermanent as String: true,
kSecAttrApplicationTag as String: tag
]
]
let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error)
let publicKey = SecKeyCopyPublicKey(privateKey!)
print("\(publicKey!)")
var address = Unmanaged.passUnretained(publicKey!).toOpaque()
do{
withUnsafeBytes(of: &address) { bytes in
for byte in bytes{
print(byte)
}
}
}
Итак, первый оператор печати выдает следующее
<SecKeyRef curve type: kSecECCurveSecp256r1, algorithm id: 3, key type: ECPublicKey, version: 4, block size: 256, bits, y: ..., x: ..., addr: 0x...>
Что пока хорошо, ключ, который я хочу, находится на кривой что я хочу и ключ правильной длины и тому подобное. Но теперь следующий отпечаток выдает следующее
144
70
215
9
1
0
0
0
Вот и все. Ясно, что последние 8 вещей, которые будут напечатаны, не являются ключом, они слишком короткие. Так что да, как мне извлечь значения x и y ключа publi c. Я могу видеть, что это напечатано, поэтому должен быть способ получить к нему доступ, но да, я искал везде и никаких кубиков Моя теория о том, что я могу «отрубить» часть «iOS» сгенерированного ключа, может быть даже неверной, но дело в том, что я даже не могу проверить это, не имея возможности отправлять байты в ESP. Я надеюсь, что есть более простой способ добиться обмена ключами между приложением iOS и ESP, но пока это единственный способ, которым я знаю. О да, я посылаю байты ключа через Bluetooth, я смог подключить приложение iOS к ESP через Bluetooth, и вот как я пытаюсь произвести обмен ключами. Я знаю, что Bluetooth технически зашифрован, но я просто хочу обменяться ключами, а затем шифровать сообщения Bluetooth с помощью AES-GCM. Так пожалуйста. Если вы знаете способ доступа к байтам ключа, пожалуйста, поделитесь!
ОБНОВЛЕНИЕ:
Я использую этот код для генерации пары ключей для обмена ключами ECDH:
let attributes: [String: Any] = [
kSecAttrType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeySizeInBits as String: 256,
kSecPrivateKeysAttrs as String: [
kSecAttrIsPermanent as String: true
]
]
var error: Unmanaged<CFError>?
privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error)!
publicKey = SecKeyCopyPublicKey(privateKey!)!
let pubKeyExternRep = SecKeyCopyExternalRepresentation(publicKey!, &error)
print("\(publicKeyExternRep!)")
Который выводит следующее:
{length = 65, bytes = 0x048820d8 0482e62f 7abac673 02d8a68e ... 6e0117684
ff455540 }
Я пытаюсь получить все, что находится после секции 0x04
в bytes
, в массиве символов, чтобы я мог отправить его по Bluetooth в последовательности пакеты. Поэтому обязательно, чтобы я получил все после 0x04
, все 128 символов, и имел его в байтовом массиве. В конце концов, если я распечатаю содержимое байтового массива, он должен просто сказать: 8820d80482e62f ... 6e0117684ff455540
.
Я попробовал следующее:
//^^^ previous code block that generates the key pair ^^^
let length = CFDataGetLength(pubKeyExternRep!)
let range = CFRange.init(location: 0, length: length)
let uint8Pointer = UnsafeMutablePointer<UInt8>.allocate(capacity:length)
CFDataGetBytes(pubKeyExternRep!, range, uint8Pointer)
print("\(uint8Pointer.pointee)")
Это выведет следующее:
4
Это выглядит многообещающе, поскольку оно соответствует первым 4 клавишам, 0x04
, но затем я перемещаю указатель вверх, переключая location: 5
, и он печатает случайное число двух ди git, которое не ' не подходит ни к чему полезному, например, 68
или что-то в этом роде.
Я также попробовал это:
^^^ previous code block that generates the key pair ^^^
let keyData = pubKeyExternRep as Data?
let dataString = keyData?.base64EncodedString()
var byteArray: [UInt8] = []
byteArray = Array(dataString!.utf8)
print("\(byteArray)")
Теперь это очень приближает меня к тому, что мне нужно, это байтовый массив и я могу выполнять над ним операции и объединять вещи и прочее, если я распечатываю, он выводит следующее:
[66, 79, 76, ..., 119, 81, 61]
Проблема не только в том, что члены массива не совпадают ни с одним из 128 байтов в pubKeyExternRep
, но также короче, чем 128 байтов, которые мне нужны. Это 64 байта. На самом деле это то, что я заметил для обоих методов, которые я пробовал (метод CFDataGetBytes и метод String to Array), что бы я ни получал, это никогда не 128 байтов, это всегда 64.
Мне просто нужны все 128 байт после 0x04
, когда я print(publicKeyExternRep!)
ОБНОВЛЕНИЕ 2: найденное решение, это не то, что помечено, но технически ответило на вопрос. Разместим решение после работы!