Swift生成的RSA公钥导入Node.js失败,求解决方案
Swift RSA公钥传输至Node.js解析错误解决方案
问题根源
Swift通过SecKeyGeneratePair生成的公钥,默认导出的DER格式可能是PKCS#1标准(仅包含模数和指数),而Node.js的crypto模块默认期望X.509(SPKI)格式的公钥,这是导致ASN.1解析错误的核心原因。
具体解决步骤
1. Swift端导出标准X.509格式PEM公钥
确保导出的是SPKI格式的公钥(X.509标准),而非PKCS#1:
func exportPublicKeyToPEM(_ publicKey: SecKey) -> String? { var error: Unmanaged<CFError>? guard let derData = SecKeyCopyExternalRepresentation(publicKey, &error) as Data? else { print(error?.takeRetainedValue() ?? "导出公钥失败") return nil } // 按PEM标准封装:添加头尾标识+64字节换行 let base64Str = derData.base64EncodedString(options: .lineLength64Characters) return "-----BEGIN PUBLIC KEY-----\n\(base64Str)\n-----END PUBLIC KEY-----" }
注:iOS 10+系统中
SecKeyCopyExternalRepresentation对RSA公钥默认导出SPKI格式,无需额外转换。
2. 传输时避免编码错误
通过JSON发送PEM字符串时,直接使用原始字符串,不要手动转义或修改换行符:
let params = ["publicKey": pemPublicKey] do { let jsonData = try JSONSerialization.data(withJSONObject: params) // 发起POST请求(示例用URLSession) var request = URLRequest(url: URL(string: "http://your-server/upload-key")!) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.httpBody = jsonData // 发送请求逻辑... } catch { print(error) }
3. Node.js端明确指定格式解析
接收请求后,明确指定公钥的格式和类型,避免自动识别出错:
const express = require('express'); const bodyParser = require('body-parser'); const crypto = require('crypto'); const app = express(); app.use(bodyParser.json()); app.post('/upload-key', (req, res) => { const publicKeyPem = req.body.publicKey; try { const publicKey = crypto.createPublicKey({ key: publicKeyPem, format: 'pem', type: 'spki' // 强制指定SPKI格式 }); res.send('公钥解析成功'); } catch (err) { console.error(err); res.status(500).send('公钥解析失败'); } }); app.listen(3000, () => console.log('服务器运行在3000端口'));
排查工具
如果问题仍存在,用以下方式验证:
- 在Swift端打印导出的PEM字符串,复制到本地文件,执行
openssl rsa -pubin -in key.pem -text,验证公钥是否有效 - 在Node.js端打印
req.body.publicKey,确认和Swift端的原始PEM完全一致,无缺失或转义错误 - 若直接传输DER格式,Node.js需按如下解析:
const publicKey = crypto.createPublicKey({ key: Buffer.from(req.body.publicKeyDer, 'base64'), format: 'der', type: 'spki' });
内容的提问来源于stack exchange,提问作者Matt Braniff
相关产品推荐
相关产品推荐

