我正在尝试在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发送加密的消息。但是在执行此操作之前,我需要在两个设备之间执行密钥交换,以使它们都...
只需使用print(publicKeyExternRep!)
。编码格式不是通常所说的X9.63,它是没有命名曲线参数的平坦的未压缩公共密钥点。