簡體   English   中英

輸出 SecKeyCopyExternalRepresentation

[英]Output SecKeyCopyExternalRepresentation

我試圖將公鑰從我的 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())

示例輸出:

BJSCZtBatd2BYEHtyLB0qTZNlphKf3ZTGI6Nke3dSxIDpyP9FWMZbG0zcdIXWENyndskfxV0No/yz369ngL2EHZYw6ggNysOnZ5IQSPOLFFl44m1aARXQ==TVAzjda

在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()
)

我得到的錯誤是ValueError: Could not deserialize key data.

那么文檔中描述的SecKeyCopyExternalRepresentation的輸出究竟是什么:

該方法以 PCKS #1 格式返回 RSA 密鑰的數據。 對於橢圓曲線公鑰,格式遵循ANSI X9.63標准,使用字節串04 || X|| Y. 對於橢圓曲線私鑰,輸出格式為公鑰與秘密標量的大端編碼連接,或 04 || X|| 是|| K. 所有這些表示都使用固定大小的整數,根據需要包括前導零。

如何描述X6.93格式? 我將如何將它轉換為我可以在 python 代碼中使用的東西?

PS 我試圖將諸如-----BEGIN PUBLIC KEY-----標題添加到 xcode 輸出中。

我還沒有完全找到問題的答案,因為我仍然不知道 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")
}

示例輸出:

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

使用密碼學在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

輸出以下內容: <cryptography.hazmat.backends.openssl.ec._EllipticCurvePublicKey object at 0x7fb4f6f50e10>

請注意,您必須自己在 python 中添加新行才能使這一切正常工作。

更新

ECC 密鑰的SecKeyCopyExternalRepresentation的輸出是密鑰的 X9.62 或 X9.63 格式(未壓縮形式)。 這與 DER 和 PEM 編碼非常不同。

編碼為04 || X || Y 04 || X || Y 04 || X || Y表示公鑰和04 || X || Y || K 04 || X || Y || K 04 || X || Y || K為私鑰。 04是此格式的固定字節。 XY和可選的K值是定義此鍵曲線的點或坐標。 更多關於這里的信息

我將為那些無法使用第三方的人提供答案。

格式的輸出是04 || X|| 是 [|| K]沒有許多外部系統期望的 EC 標頭標識符。 將其導出到其他平台時,您需要添加該標頭。 下面是一個例子:

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/yz369ngL2EHZYw6ggNysOnZ5IQSPOLFFl44m1aARXQ==TVAzjda

密鑰似乎格式不正確。

它似乎是一個 EC 密鑰。 我懷疑是公開的04 || X || Y 04 || X || Y 04 || X || Y ,但我可能是錯的。 你知道key在哪個字段結束嗎? 該字段告訴您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