从 iOS 导出椭圆曲线密钥以与 OpenSSL 配合使用

nRe*_*wik 3 security ios swift

我生成了私钥/公钥对并将其存储在 Secure Enclave 内。

它是 256 位椭圆曲线密钥。(唯一可以存储在 Secure Enclave 中的密钥类型)。

我使用SecKeyCreateWithDataSecKeyCopyExternalRepresentation在 iOS 设备之间导入/导出公钥,并且它有效。

但是,导出的密钥似乎不适用于 OpenSSL。因为它总是显示'unable to load Key'在这个命令上。

openssl ec -pubin -in public_key_file -text
Run Code Online (Sandbox Code Playgroud)

导出密钥的方式是什么?所以我可以将它与 OpenSSL 一起使用。

nRe*_*wik 6

要使用 OpenSSL,您需要subject public key info (SPKI)DERPEM格式。

SPKI 包含重要信息,例如key.typekey.parameterskey.value

SecKeyCopyExternalRepresentation只返回原始密钥二进制文件,这只是key.value一部分。

您必须从中创建 SPKI key.value。执行此操作的正常方法是阅读https://www.rfc-editor.org/rfc/rfc5480,并将 ASN.1 结构编码为二进制编码的 DER 格式。


但这里有一个捷径。

Secure Enclave 仅支持一种密钥类型,即 256 位 EC 密钥secp256r1(相当于prime256v1OpenSSL)。

DER格式的SPKI是二进制编码数据,例如:

3059301306072a8648ce3d020106082a8648ce3d03010703420004fad2e70b0f70f0bf80d7f7cbe8dd4237ca9e59357647e7a7cb90d71a71f6b57869069bcdd24272932c6bdd51895fe2180ea0748c737adecc1cefa3a02022164d
Run Code Online (Sandbox Code Playgroud)

它总是由两部分组成

  1. 固定模式标头3059301306072a8648ce3d020106082a8648ce3d030107034200

  2. 原始键值04.......

您可以通过组合这两部分来创建 SPKI。

spki = fixed_schema_header + SecKeyCopyExternalRepresentation(...)


func createSubjectPublicKeyInfo(rawPublicKeyData: Data) -> Data {
    let secp256r1Header = Data(bytes: [
        0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
        0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00
        ])
    return secp256r1Header + rawPublicKeyData
}

// Usage
let rawPublicKeyData = SecKeyCopyExternalRepresentation(...)!
let publicKeyDER = createSubjectPublicKeyInfo(rawPublicKeyData: rawPublicKeyData)
write(publicKeyDER, to: "public_key.der")

// Test with OpenSSL
// openssl ec -pubin -in public_key.der -text -inform der
Run Code Online (Sandbox Code Playgroud)