Как получить доступ к байту в ключе publi c, сгенерированном SecKeyCreateRandomKey ()? - PullRequest
0 голосов
/ 28 февраля 2020

Я пытаюсь отправить зашифрованные сообщения с помощью 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: найденное решение, это не то, что помечено, но технически ответило на вопрос. Разместим решение после работы!

1 Ответ

1 голос
/ 29 февраля 2020

Просто используйте SecKeyCopyExternalRepresentation(_:_:). Кодированный формат - это не то, что обычно называют X9.63, это плоская несжатая ключевая точка publi c без параметров названной кривой.

...