从iOS导出椭圆曲线键以使用OpenSSL

我在Secure Enclave中生成并存储了一个私钥/公钥对。

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

我使用SecKeyCreateWithDataSecKeyCopyExternalRepresentation在iOS设备之间导入/导出公钥,并且它可以工作。

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

 openssl ec -pubin -in public_key_file -text 

导出密钥的方法是什么? 所以我可以在OpenSSL中使用它。

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

SPKI包含基本信息,例如key.typekey.parameterskey.value

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

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


但这是一条捷径。

Secure Enclave仅支持一种密钥类型,256位EC密钥secp256r1 (相当于OpenSSL中的prime256v1 )。

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

 3059301306072a8648ce3d020106082a8648ce3d03010703420004fad2e70b0f70f0bf80d7f7cbe8dd4237ca9e59357647e7a7cb90d71a71f6b57869069bcdd24272932c6bdd51895fe2180ea0748c737adecc1cefa3a02022164d 

它总是由两部分组成

  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