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

iOS Swift使用自定义私钥对字节数组进行SHA256withRSA签名的实现

你现有Swift代码签名结果和Java不一致的核心原因是算法选择错误:你使用的rsaSignatureDigestPSSSHA256要求输入为预计算完成的SHA256摘要,但Java实现是传入原始字节数组由Signature内部自动计算摘要,两边逻辑完全不匹配。同时私钥导入参数不全、强制解包也会导致功能不稳定。

以下是可与Java实现完全对齐的Swift代码:

import Security

// 签名错误枚举
enum SignError: Error {
    case invalidPrivateKey
    case invalidInputData
    case signFailed(CFError?)
}

/// 非对称签名方法
/// - Parameters:
///   - originalString: 待签名的原始字符串
///   - privateKeyBase64: Base64编码的私钥(支持PEM格式带头尾的输入)
///   - algorithm: 签名算法,需和Java侧算法完全对应
///   - base64Options: 签名结果Base64编码的配置项
/// - Returns: Base64编码的签名结果
public func sign(originalString: String, privateKeyBase64: String, algorithm: SecKeyAlgorithm = .rsaSignatureMessagePSSSHA256, base64Options: Data.Base64EncodingOptions = []) throws -> String {
    // 清理PEM格式私钥的头尾和换行符
    var cleanedKeyString = privateKeyBase64
        .replacingOccurrences(of: "-----BEGIN RSA PRIVATE KEY-----", with: "")
        .replacingOccurrences(of: "-----END RSA PRIVATE KEY-----", with: "")
        .replacingOccurrences(of: "-----BEGIN PRIVATE KEY-----", with: "")
        .replacingOccurrences(of: "-----END PRIVATE KEY-----", with: "")
        .replacingOccurrences(of: "\n", with: "")
        .trimmingCharacters(in: .whitespacesAndNewlines)
    
    guard let keyData = Data(base64Encoded: cleanedKeyString) else {
        throw SignError.invalidPrivateKey
    }
    
    // 私钥导入配置,密钥长度需和实际私钥对应,常见为2048/4096
    let keyAttributes: [CFString: Any] = [
        kSecAttrKeyType: kSecAttrKeyTypeRSA,
        kSecAttrKeyClass: kSecAttrKeyClassPrivate,
        kSecAttrKeySizeInBits: 2048,
        kSecAttrIsPermanent: false
    ]
    
    var error: Unmanaged<CFError>?
    guard let privateKey = SecKeyCreateWithData(keyData as CFData, keyAttributes as CFDictionary, &error) else {
        throw SignError.signFailed(error?.takeRetainedValue())
    }
    
    // 校验私钥支持所选签名算法
    guard SecKeyIsAlgorithmSupported(privateKey, .sign, algorithm) else {
        throw SignError.invalidPrivateKey
    }
    
    guard let inputData = originalString.data(using: .utf8) else {
        throw SignError.invalidInputData
    }
    
    // 执行签名
    guard let signedData = SecKeyCreateSignature(privateKey, algorithm, inputData as CFData, &error) as Data? else {
        throw SignError.signFailed(error?.takeRetainedValue())
    }
    
    return signedData.base64EncodedString(options: base64Options)
}

Java与Swift算法对应表

可根据Java侧algorithm.getJvmName()的返回值替换Swift的algorithm参数:

Java算法名Swift SecKeyAlgorithm值
SHA1withRSA.rsaSignatureMessagePKCS1v15SHA1
SHA256withRSA.rsaSignatureMessagePKCS1v15SHA256
SHA512withRSA.rsaSignatureMessagePKCS1v15SHA512
SHA256withRSA/PSS.rsaSignatureMessagePSSSHA256
SHA512withRSA/PSS.rsaSignatureMessagePSSSHA512

注意事项

  • 默认情况下Java和Swift的PSS签名参数一致:盐长等于摘要长度、掩码生成函数为MGF1+对应哈希算法,可直接对齐;如果Java侧自定义了PSS参数,需同步调整Swift侧配置
  • 如果使用椭圆曲线(ECC)签名,只需将kSecAttrKeyType改为kSecAttrKeyTypeEC,算法替换为对应的ecdsaSignatureMessageX962SHA256即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 01:06:00