You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Swift中用RSA私钥生成签名?Java转Swift实现遇阻

问题根源与修复方案

导致SecKeyCreateWithData失败的核心原因

你的Swift代码在密钥导入步骤失败,主要源于以下三个关键问题:

  • 私钥格式不兼容:openssl genrsa -des3生成的是PKCS#1格式私钥,但SecKeyCreateWithData要求导入PKCS#8格式密钥,而Java代码明确使用PKCS#8解析逻辑。
  • 哈希计算错误:createHash函数直接传入字符串而非UTF-8字节数据,且用字符数代替字节数作为哈希长度,导致哈希结果完全错误。
  • 签名算法不匹配:Swift使用的PSS填充算法与Java的SHA256WithRSA(PKCS#1 v1.5填充)不兼容,即使密钥导入成功也会生成无效签名。

修复步骤与完整代码

第一步:转换私钥格式

执行以下openssl命令将PKCS#1格式私钥转为PKCS#8格式:

openssl pkcs8 -topk8 -inform PEM -in WM_IO_my_rsa_key_pair -outform PEM -out WM_IO_private_key.pem -nocrypt

(需保留密码则移除-nocrypt参数)

第二步:修正Swift代码

import CommonCrypto
import Security

func computeSHA256Hash(for string: String) -> Data {
    guard let data = string.data(using: .utf8) else { return Data() }
    var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
    data.withUnsafeBytes { buffer in
        CC_SHA256(buffer.baseAddress, CC_LONG(data.count), &hash)
    }
    return Data(hash)
}

func createSignature(stringToSign: String) throws -> String? {
    guard let url = Bundle.module.url(forResource: "WM_IO_private_key", withExtension: "pem") else {
        return nil
    }
    
    let privateKeyPEM = try String(contentsOf: url, encoding: .utf8)
        .replacingOccurrences(of: "-----BEGIN PRIVATE KEY-----", with: "")
        .replacingOccurrences(of: "-----END PRIVATE KEY-----", with: "")
        .components(separatedBy: .whitespacesAndNewlines).joined()
    
    guard let privateKeyData = Data(base64Encoded: privateKeyPEM, options: .ignoreUnknownCharacters) else {
        return nil
    }
    
    let attributes: [CFString: Any] = [
        kSecAttrKeyType: kSecAttrKeyTypeRSA,
        kSecAttrKeyClass: kSecAttrKeyClassPrivate,
        kSecAttrKeySizeInBits: 2048
    ]
    
    var error: Unmanaged<CFError>?
    guard let secKey = SecKeyCreateWithData(privateKeyData as CFData, attributes as CFDictionary, &error) else {
        throw error?.takeRetainedValue() as Error ?? NSError(domain: "KeyImportError", code: -1, userInfo: nil)
    }
    
    let hash = computeSHA256Hash(for: stringToSign)
    let algorithm: SecKeyAlgorithm = .rsaSignatureMessagePKCS1v15SHA256
    
    guard let signatureData = SecKeyCreateSignature(secKey, algorithm, hash as CFData, &error) as Data? else {
        throw error?.takeRetainedValue() as Error ?? NSError(domain: "SignatureError", code: -1, userInfo: nil)
    }
    
    return signatureData.base64EncodedString()
}

关键修复说明

  1. 格式对齐:通过openssl转换后,私钥格式与Java代码的PKCS#8解析逻辑保持一致,解决密钥导入失败问题。
  2. 哈希修正:正确处理字符串的UTF-8字节数据,生成标准的256位哈希值。
  3. 算法匹配:使用.rsaSignatureMessagePKCS1v15SHA256替代PSS算法,确保签名格式与Java实现完全兼容。
  4. 错误处理优化:完善错误抛出逻辑,便于排查后续问题。

内容的提问来源于stack exchange,提问作者Berry Blue

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 04:01:07