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

Ios 如何访问SecKeyCreateRandomKey()生成的公钥中的字节?,ios,encryption,byte,extract,swift5,Ios,Encryption,Byte,Extract,Swift5,我正在尝试使用AES-GCM在iOS应用程序和ESP微控制器之间发送加密消息。但在我这么做之前,我需要在两个设备之间执行密钥交换,以便它们都有一个共享的秘密。因此,我正在研究用于生成私钥/公钥对的iOS方法,有几种。但是有一个问题,iOS生成的密钥不容易与iOS之外的任何东西兼容(据我所知),这意味着我必须跳入并对密钥进行一些修改。我注意到生成的键总是abdc1234其中abcd从不更改,每次生成键时1234都会更改。因此,我假设abcd只是iOS使用的东西,1234是实际的键。至少,安卓系统就

我正在尝试使用AES-GCM在iOS应用程序和ESP微控制器之间发送加密消息。但在我这么做之前,我需要在两个设备之间执行密钥交换,以便它们都有一个共享的秘密。因此,我正在研究用于生成私钥/公钥对的iOS方法,有几种。但是有一个问题,iOS生成的密钥不容易与iOS之外的任何东西兼容(据我所知),这意味着我必须跳入并对密钥进行一些修改。我注意到生成的键总是
abdc1234
其中
abcd
从不更改,每次生成键时
1234
都会更改。因此,我假设
abcd
只是iOS使用的东西,
1234
是实际的键。至少,安卓系统就是这样。为了验证我的假设,我尝试获取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)
      }
   }
}
因此,第一个print语句输出以下内容

<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!)")
我正在尝试将
字节
部分中
0x04
之后的所有内容设置为字符数组,以便我可以通过蓝牙以数据包序列的形式发送。因此,我必须获取
0x04
之后的所有内容,所有128个字符,并将其放入字节数组中。最后,如果我打印字节数组的内容,它应该是
8820d80482e62f。。。6e0117684ff455540

我尝试了以下方法:

{length = 65, bytes = 0x048820d8 0482e62f 7abac673 02d8a68e ... 6e0117684
ff455540 }
//^^^ 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
向上移动指针,它会打印一个随机的两位数,与任何有用的数字都不匹配,即
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]
问题不仅在于数组的成员与
pubKeyExternRep
中的128个字节中的任何一个都不匹配,而且它还比我需要的128个字节短。它是64字节。对于我尝试过的两种方法(CFDataGetBytes方法和String to Array方法),我都注意到了这一点,无论我得到什么,它都不是128字节,而是64字节

当我打印(publicKeyExternRep!)

更新2:
找到了解决方案,不是标记的那个,而是技术上回答了问题的那个。下班后将发布解决方案

就用吧。编码格式与通常所说的X9.63不同,它是一个平坦的未压缩公钥点,没有命名曲线的参数。

但是如何访问其中的字节,例如,如何将它们放置在数组中以执行诸如串联等操作?目前,如果我使用
let externRep=
创建一个保存外部表示的var,则无法访问字节本身(公钥中存在的所有128个字节)
print(externRep!)
将输出到控制台,但我找不到一种方法来创建包含所有字节的字节数组本身不是
externRep
字节数组吗?我想,要打印出这些值,你需要用十六进制或以64进制为基数,然后将其转换为文本。事实并非如此。它是一个CFData对象。因此,如果我尝试使用
print(externRep[0])
之类的方法获取字节,它会说它做不到。如果我对它进行Base64编码,那么它不是128字节的密钥,而是变为64字节。我需要128字节…对不起?我们这里说的是ECC密钥,对吗?您可能得到的是2 x 32字节的数据,或静态大小为256位的x坐标,后跟256位的y坐标,共同构成公钥点(即不包括EC域参数的公钥)。在这种情况下,04(未压缩点指示器)可能丢失。为什么一个ECC密钥需要128字节?至于打印出来,只要可以使用NSData,就可以使用CFData,对吗?NSData到hex有那么难吗?