简体   繁体   English

输出 SecKeyCopyExternalRepresentation

[英]Output SecKeyCopyExternalRepresentation

I'm trying to pass around a public key from my iPhone to other parties, however I am unable to use the output from iOS.我试图将公钥从我的 iPhone 传递给其他方,但是我无法使用 iOS 的输出。

let parameters: [String: Any] = [
    kSecAttrKeySizeInBits as String: 384,
    kSecAttrKeyType as String: kSecAttrKeyTypeEC,
    kSecPrivateKeyAttrs as String: [
        kSecAttrIsPermanent as String: false
    ]
]

var error: Unmanaged<CFError>?
let privateKey = SecKeyCreateRandomKey(parameters as CFDictionary, &error)
let publicKey = SecKeyCopyPublicKey(privateKey!)

let pub = SecKeyCopyExternalRepresentation(publicKey!, &error)
let pubData = pub as Data?
print(pubData!.base64EncodedString())

Example output:示例输出:

BJSCZtBatd2BYEHtyLB0qTZNlphKf3ZTGI6Nke3dSxIDpyP9FWMZbG0zcdIXWENyndskfxV0No/yz369ngL2EHZYw6ggNysOnZ5IQSPOLFFl44m1aAk0o0NdaRXTVAz4jQ== BJSCZtBatd2BYEHtyLB0qTZNlphKf3ZTGI6Nke3dSxIDpyP9FWMZbG0zcdIXWENyndskfxV0No/yz369ngL2EHZYw6ggNysOnZ5IQSPOLFFl44m1aARXQ==TVAzjda

In python (where my second party is) I have the following:在python(我的第二方所在的地方)中,我有以下内容:

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization

pub_key = serialisation.load_pem_public_key(
    data=xcode_data.encode(),
    backend=default_backend()
)

The error I get is ValueError: Could not deserialize key data.我得到的错误是ValueError: Could not deserialize key data.

So what exactly is the output of the SecKeyCopyExternalRepresentation as described by the documentation:那么文档中描述的SecKeyCopyExternalRepresentation的输出究竟是什么:

The method returns data in the PCKS #1 format for an RSA key.该方法以 PCKS #1 格式返回 RSA 密钥的数据。 For an elliptic curve public key, the format follows the ANSI X9.63 standard using a byte string of 04 ||对于椭圆曲线公钥,格式遵循ANSI X9.63标准,使用字节串04 || X || X|| Y. For an elliptic curve private key, the output is formatted as the public key concatenated with the big endian encoding of the secret scalar, or 04 || Y. 对于椭圆曲线私钥,输出格式为公钥与秘密标量的大端编码连接,或 04 || X || X|| Y ||是|| K. All of these representations use constant size integers, including leading zeros as needed. K. 所有这些表示都使用固定大小的整数,根据需要包括前导零。

How would one describe the X6.93 format?如何描述X6.93格式? And how would I go about converting it to something I can use in the python code?我将如何将它转换为我可以在 python 代码中使用的东西?

PS I have tried to add headers such as -----BEGIN PUBLIC KEY----- to the xcode output. PS 我试图将诸如-----BEGIN PUBLIC KEY-----标题添加到 xcode 输出中。

I havent quite found the answer to the question as I still don't know what exactly the output is that Apple provides, however, I came up with a solution found in this key import export manager .我还没有完全找到问题的答案,因为我仍然不知道 Apple 提供的输出究竟是什么,但是,我想出了在这个关键的导入导出管理器中找到的解决方案。

let parameters: [String: Any] = [
    kSecAttrKeySizeInBits as String: 384,
    kSecAttrKeyType as String: kSecAttrKeyTypeEC,
    kSecPrivateKeyAttrs as String: [
        kSecAttrIsPermanent as String: false
    ]
]

var pubKey: SecKey?
var priKey: SecKey?
var error: Unmanaged<CFError>?
let keyPair = SecKeyGeneratePair(parameters as CFDictionary, &pubKey, &priKey)

let publicKeyData = SecKeyCopyExternalRepresentation(pubKey!, &error)
// Code from the library
let ieManager = CryptoExportImportManager()
if let exportPEM = ieManager.exportPublicKeyToPEM(publicKeyData as Data!, keyType: kSecAttrKeyTypeEC as String, keySize: 384) {
    print(exportPEM)
} else {
    print("Error exporting to PEM")
}

Example output:示例输出:

Exporting EC raw key: 97 bytes -----BEGIN PUBLIC KEY----- MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEFpCnTrJFQq0mZBvy+vzl9noKLZ4/s1cf I6hygug6s8dvBreMhabAcAbbhSa1losjCxV450nq92W9ZymonYasaAuhshDWjmvx 2qTXHEpVEVb9GawqX6XqpWtIBf+meHKS -----END PUBLIC KEY-----

Implementation in python using cryptography使用密码学在python中实现

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization

xcode = '-----BEGIN PUBLIC KEY-----\nMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEFpCnTrJFQq0mZBvy+vzl9noKLZ4/s1cf\nI6hygug6s8dvBreMhabAcAbbhSa1losjCxV450nq92W9ZymonYasaAuhshDWjmvx2\nqTXHEpVEVb9GawqX6XqpWtIBf+meHKS\n-----END PUBLIC KEY-----'
pub_key = serialization.load_pem_public_key(xcode.encode(), default_backend())
xcode

Outputs the following: <cryptography.hazmat.backends.openssl.ec._EllipticCurvePublicKey object at 0x7fb4f6f50e10>输出以下内容: <cryptography.hazmat.backends.openssl.ec._EllipticCurvePublicKey object at 0x7fb4f6f50e10>

Note that you do have to add the new lines yourself in python in order for this all to work.请注意,您必须自己在 python 中添加新行才能使这一切正常工作。

Update更新

The output of the SecKeyCopyExternalRepresentation for ECC keys is the X9.62 or X9.63 format of the key (in uncompressed form). ECC 密钥的SecKeyCopyExternalRepresentation的输出是密钥的 X9.62 或 X9.63 格式(未压缩形式)。 This is very different from DER and therefor PEM encoding.这与 DER 和 PEM 编码非常不同。

The encoding is 04 || X || Y编码为04 || X || Y 04 || X || Y 04 || X || Y for a public key and 04 || X || Y || K 04 || X || Y表示公钥和04 || X || Y || K 04 || X || Y || K 04 || X || Y || K for a private key. 04 || X || Y || K为私钥。 04 is a fixed byte for this format. 04是此格式的固定字节。 The X , Y and optionally K value are points or coordinates that define the curve of this key. XY和可选的K值是定义此键曲线的点或坐标。 More info about that over here .更多关于这里的信息

I will provide an answer for those who can't use a third party.我将为那些无法使用第三方的人提供答案。

The output of the format is 04 ||格式的输出是04 || X || X|| Y [ ||是 [|| K] without the EC header identifier that many outside systems expect. K]没有许多外部系统期望的 EC 标头标识符。 You'll need to add that header when exporting it for other platforms.将其导出到其他平台时,您需要添加该标头。 Here's an example:下面是一个例子:

let fullKeyData = CFDataCreateMutable(kCFAllocatorDefault, CFIndex(0))
if fullKeyData != nil
{
    //Fixed schema header per key size in bits
    //var headerBytes256r1: [UInt8] = [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] //uncomment if you use 256 bit EC keys
    var header384r1: [UInt8] = [0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00] //384 bit EC keys
    //var header521r1: [UInt8] = [0x30, 0x81, 0x9B, 0x30, 0x10, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23, 0x03, 0x81, 0x86, 0x00] // For 521 bit EC keys
    let headerSize = CFIndex(header384r1.count)

    CFDataAppendBytes(fullKeyData, &header384r1, headerSize)
    CFDataAppendBytes(fullKeyData, CFDataGetBytePtr(pub), CFDataGetLength(pub)) //pub = data you got from SecKeyCopyExternalRepresentation

    var pem = ""
    //pem.append("-----BEGIN PUBLIC KEY-----\n") //uncomment if needed
    pem.append((fullKeyData as Data?)?.base64EncodedString() ?? "")
    //pem.append("\n-----END PUBLIC KEY-----\n") //uncomment if needed

    //do something with pem
}

BJSCZtBatd2BYEHtyLB0qTZNlphKf3ZTGI6Nke3dSxIDpyP9FWMZbG0zcdIXWENyndskfxV0No/yz369ngL2EHZYw6ggNysOnZ5IQSPOLFFl44m1aAk0o0NdaRXTVAz4jQ== BJSCZtBatd2BYEHtyLB0qTZNlphKf3ZTGI6Nke3dSxIDpyP9FWMZbG0zcdIXWENyndskfxV0No/yz369ngL2EHZYw6ggNysOnZ5IQSPOLFFl44m1aARXQ==TVAzjda

The key appears to be malformed. 密钥似乎格式不正确。

It appears to be an EC key.它似乎是一个 EC 密钥。 I suspect it is the public one detailed as 04 || X || Y我怀疑是公开的04 || X || Y 04 || X || Y 04 || X || Y , but I could be wrong. 04 || X || Y ,但我可能是错的。 Do you know what field the key is over?你知道key在哪个字段结束吗? The field tells you how many bytes are in X and Y .该字段告诉您XY有多少字节。

$ cat key.dat
BJSCZtBatd2BYEHtyLB0qTZNlphKf3ZTGI6Nke3dSxIDpyP9FWMZbG0zcdIXWENyndskfxV0No/yz369ngL2EHZYw6ggNysOnZ5IQSPOLFFl44m1aAk0o0NdaRXTVAz4jQ==

$ base64 -d key.dat | hexdump -C
00000000  04 94 82 66 d0 5a b5 dd  81 60 41 ed c8 b0 74 a9  |...f.Z...`A...t.|
00000010  36 4d 96 98 4a 7f 76 53  18 8e 8d 91 ed dd 4b 12  |6M..J.vS......K.|
00000020  03 a7 23 fd 15 63 19 6c  6d 33 71 d2 17 58 43 72  |..#..c.lm3q..XCr|
00000030  9d db 24 7f 15 74 36 8f  f2 cf 7e bd 9e 02 f6 10  |..$..t6...~.....|
00000040  76 58 c3 a8 20 37 2b 0e  9d 9e 48 41 23 ce 2c 51  |vX.. 7+...HA#.,Q|
00000050  65 e3 89 b5 68 09 34 a3  43 5d 69 15 d3 54 0c f8  |e...h.4.C]i..T..|
00000060  8d                                                |.|
00000061

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM