iOS Swift生成PKCS#1公钥与Java SPKI格式适配问题
存在误导性的初始问题
结合后续讨论及相关问题,现已明确引发本问题的初始假设:
'iOS:生成PKCS格式而非ASN.1格式的公钥'
存在根本性错误。
修正后的假设
正确的假设应为:
- Swift(iOS)生成的是PKCS#1格式的密钥
- Java 17生成的密钥虽外观相似,但采用的是**SubjectPublicKeyInfo(简称SPKI)**格式
为便于文档留存,初始问题内容保持不变(见下方)
在iOS设备上使用Swift生成PKCS格式的公钥
常规方案
iOS生成的公钥采用ASN.1格式表示
示例:生成密钥对(ASN.1格式)
以下Swift示例代码用于从密钥对中提取ASN.1格式的公钥:
// Keypair attributes let tag = "my_personal_keystore_keypair_alias".data(using: .utf8)! let attributes: [String: Any] = [kSecAttrKeyType as String: kSecAttrKeyTypeRSA, kSecAttrKeySizeInBits as String: "4096", kSecPrivateKeyAttrs as String: [kSecAttrIsPermanent as String: true, kSecAttrApplicationTag as String: tag] ] var error: Unmanaged<CFError>? // Generate PrivateKey / Keypair guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else { throw error!.takeRetainedValue() as Error } // Extract PublicKey guard let publicKey = SecKeyCopyPublicKey(privateKey), let publicKeyOptional = SecKeyCopyExternalRepresentation(publicKey, nil) else { return "PublicKey could not be accessed." } let publicKeyData = publicKeyOptional as Data let base64PublicKey = publicKeyData.base64EncodedString() print("PublicKey, base64: ", base64PublicKey)
我未找到获取PKCS格式公钥的方法。
Apple开发者文档
似乎存在SecItemExport接口,但我无法理解其使用说明。
StackOverflow相关问题
此类需求并非首次提出,但最佳答案指向已失效资源,无法使用。
附加条件
不允许使用第三方密钥生成库。
- 原因是无法信任第三方库能妥善处理私钥,因此仅信任Apple官方提供的接口。
- 不过,可使用第三方库将仅公钥从ASN.1格式转换为PKCS格式。
致谢
感谢您的阅读与分享,期待您的帮助 :)
实验附录
以下是上述代码生成的公钥示例,提供多个以避免偶然情况…… ;-)
第一个:
MIICCgKCAgEAl0HYn9IdRmexAR9dSh3SxmFazWF0RV2TKmtRxGySvCA+aHZ/Dp+8tC0YDWpQzP+tZdlDWNOBj/D7i1z4b+UZk8F9ZEoi+w61kYQz+KjMkRuYrPBFi4A/gsS2qGeFJ4OvLQzGObZ0C+5/E+wunUWyQCVjgjTHKH8yqfVXeWYFKmaSSZblSZJAObE8Ao5J38DMINF1oWG+GdZt8RTLf35ULLEa8zKvFXrfBkDjiQH90WKPwDxWwvFInqZhjpsFxLytiKW+iBLqa4+0P7uwXVodFXa38RW9dk9mEsLvj6764BKtPAaWym9XZfEZNBu0jwlfO07k0augynGps6bsSIyYglDImlTRagdA/e+1AMBlSxEFVO4NpCjEpMT7rNX/LYPeEaJ8fTC3axOM1yEntcwUfSSCDulVPGlWlFbPxt29y1RrGtMmwfbTlbOQf2okMf0mGx9Ytd9HWadIdWh4FqDVWA8MF82PP1YsOW5TA0hkprK1qJwfkaLRKnmpfL5a7gWn4HWzpdDqrezhbc/zTCeHbX5c61mgWsAIWnB3fyXsJHpR62+QtBEznwhDxafVCQyUmsDqbncBxilEnFIn08G+6ox2PQC8GhNdpFVGsSoqpDfctsm51/tUYLpyeIBdzw/3nMLL1J5jL3yWr7ZKgnzNwjpC8l6c6gpsF3NRodeVhp8CAwEAAQ==
第二个:
MIICCgKCAgEAlSbN7rlX6EMCDGuxQm9G6qqXIWshDvI5VaN4QPNCFcFzPjI/FyaHqi43+mxTyKGycT6TNqvanSu67yoIA80tSlFH2LndWv6sPQeHKxNwwFKU98Y/uL3M6hKIVXDwa6kZGM58dfY9qMWEOPXB4AwZtVaxJ4ePHFAR0kEOAHLCPpQxFkNlkg9FlCwlBzZbhHkI5uhCmlGEiLpLaJNJzjn7yo33m65189J6tIh3vopZ2ahFHb/vo6SVSbtS7Y0YlinJwH3MCGLm5+pKBpE64t5lgEhDPYSF7pKpLhEVqC5ETaya3mYTkXPSCiY/9Mo5zddniUGrxAJaY940jY3QNYeFmWPEEdhhIW2tUbuiM3IlHAqk4Du5p/2o1QcSVZdBsHStSGdcWqs00Z+ooxXwrOpMOUnZeb8Jt5dGDyHwjOmPf0N8dDQwz+5pgOoTkxd/z5cTK9tMv/nC+Mbbt8LRsct16M3LYrRAYnA8unX1ZD3eXTJPOSB/fM9Hmf1ObxQro9tatC5RaJjS0Xg5aepUsey62BW9lj4kHCkRPD4w1OmjDWGUCOSEhwy0KwqFyRBppYUMndEbJb3GKEjpekcQYwjERPtH/vEVxaN5gGYaCORancUaNH+d03zAmi0G830QXQvyohyKUkGw5qljEBH5R5Wqu7YLTlUes0rQEx8DpLVclaMCAwEAAQ==
第三个:
MIICCgKCAgEA1ZqMyEHgyW/uFK0+BRbByiu2ZMG/HsasoC27h4FEjvSxQQTtMgAZpoFNAjLstDWcN6PtT4137LVW3L0nsYvth+MG91mkpiByqoCNc6RigQDODNkmPlOk0ICIBII06CYx/FhzyVnm+idbi+TCZ4k9SFYkqN4iuve3QSDp8AJjIoKQEdJGcwiSE85eMXoNLmqCJ0ACxEYLHUI8n/rm2Zo3pJNRYL/WIsJvjzZAFHJ0I8ZwGzB7pNbTr6IGiXFxy8mZ51/yaQCe2/sPQLIVlYwD+lBCpDNoX3S86JLCEWOHmvntcPoPyvKnyaaE4i8yU1XUtCC1oSK4yodJPSrCzixIjG72P/puoUkTHWsLzPQ3yVVJYztvp+ETVwUj+wm8VD5GzbnPrwkO5MctmRhIEPZ1s63Tv4we1PtjlsFvsFPTYm1nuoSgsscfdjcb1/YFF/JcnVreuQcuHNrxecSxa47XzuETb5CfvoB+pVj7hZjOkEABWWcpaMTciIDk9CYUNByM33YFCt8tIPB/uuC3Kt8EpdfkypHh7CcNgHv6O6YXeUuNrb7XjE5DdtcbRMVHHWo8bNzLOHYgd7HMY346Ie6Ko8SFGMNV4Npk+c2CGzZgpBvo3+PfjGfXQjBVcdt9asQvF1fc922Zx2Oyy7Uc+xmTHkpKZqZB2LU++N+aHOa/370CAwEAAQ==
验证密钥格式的最快方式是使用在线工具:进入加密板块,粘贴其中一个公钥并输入待加密的示例数据。预期密钥为PKCS#1格式,因此选择RSA/ECB/PKCS1Padding或RSA/None/PKCS1Padding作为加密类型。尽管工具生成的密钥格式相似,但上述操作均会提示“unknown key type passed to RSA”,说明iOS生成的密钥为ASN.1格式。我们仍需获取PKCS#1格式的密钥…… :)
内容的提问来源于stack exchange,提问作者d.braun1991

