如何访问由SecKeyCreateRandomKey()生成的公钥中的字节?

问题描述 投票:0回答:1

我正在尝试在iOS应用和ESP微控制器之间使用AES-GCM发送加密的消息。但是在执行此操作之前,我需要在两个设备之间执行密钥交换,以便它们都具有共享的机密。因此,我正在研究用于生成私钥/公钥对的iOS方法,其中有几种。但是,有一个问题,iOS生成的密钥与iOS之外的任何事物都不容易兼容(据我所知),这意味着我必须加入并对其进行一些修改。我注意到生成的密钥始终为abdc1234,其中每次生成密钥时,abcd从不更改,1234更改。因此,我假设abcd只是iOS使用的东西,而1234是实际的密钥。至少,这就是在Android中发生的情况。因此,为了检验我的假设,我试图获取在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值。我可以看到它已打印,因此必须有一种访问它的方法,但是是的,我到处搜索并且没有骰子。我的理论是我可以“砍掉”所生成密钥的“ iOS”部分,这甚至可能是不正确的,但事实是,我什至不能在无法将字节发送到ESP的情况下对其进行测试。我希望有一种更简单的方法来实现iOS应用程序和ESP之间的密钥交换,但是就目前而言,这是我所知道的唯一方法。哦,是的,我通过蓝牙发送了密钥字节,我能够通过蓝牙将iOS应用程序连接到ESP,这就是我试图进行密钥交换的方式。我知道蓝牙已经过技术加密,但是我只想进行密钥交换,然后通过使用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之后的所有内容都放置在字符数组中,以便我可以通过蓝牙以一系列数据包的形式发送它。因此,必须获得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向上移动指针,并打印出一个随机的两位数字,该数字与任何有用的字符都不匹配,即[ C0]或类似的内容。

我也尝试过:

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个字节,而且还比我需要的128个字节短。它是64个字节。我实际上注意到了我尝试过的两个方法(CFDataGetBytes方法和String to Array方法),无论我得到什么,它永远不会有128个字节,总会是64个字节。

pubKeyExternRep时只需要0x04之后的所有128个字节>

更新2:找到了解决方案,它不是被标记的,但是从技术上来说确实可以回答问题。下班后将发布解决方案!

我正在尝试在iOS应用和ESP微控制器之间使用AES-GCM发送加密的消息。但是在执行此操作之前,我需要在两个设备之间执行密钥交换,以使它们都...

ios encryption byte extract swift5
1个回答
1
投票

只需使用print(publicKeyExternRep!)。编码格式不是通常所说的X9.63,它是没有命名曲线参数的平坦的未压缩公共密钥点。

© www.soinside.com 2019 - 2024. All rights reserved.