ios - 如何访问 SecKeyCreateRandomKey() 生成的公钥中的字节?
问题描述
我正在尝试使用 AES-GCM 在 iOS 应用程序和 ESP 微控制器之间发送加密消息。但在我这样做之前,我需要在两个设备之间执行密钥交换,以便它们都有一个共享的秘密。所以我正在研究用于生成私钥/公钥对的 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
,它打印出一个随机的两位数字,该数字与任何有用的东西不匹配,即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。
0x04
之后我只需要所有 128 个字节print(publicKeyExternRep!)
更新2:找到解决方案,它不是标记的,但在技术上确实回答了这个问题。下班后会发布解决方案!
解决方案
只需使用SecKeyCopyExternalRepresentation(_:_:)
. 编码格式顺便说一下不是通常所说的X9.63,它是一个扁平的未压缩公钥点,没有命名曲线的参数。
推荐阅读
- azure-web-app-service - Linux 上的 Azure Web App 我更改了 Scale Up 和 down 然后我在网站上收到 Application Error
- r - 在 shinyapps.io 上加载 rgdal 库失败
- bash - 获取最新的 SQL 转储文件
- javascript - 阅读后更改消息的背景颜色
- swift - 如何克服导航到其他视图控制器 iOS swift 的延迟?
- windows - 与 PowerCfg.exe /setacvalueindex 对应的 Windows 注册表设置
- javascript - 放大时自动隐藏文本
- javascript - 返回节点内的所有 HTML 元素
- python - 在重复出现的子字符串之间查找字符串?
- javascript - 整数变化,当我不要求他