【问题标题】:Cannot sign data using private key, getting algorithm not supported by the key in swift无法使用私钥签署数据,快速获取密钥不支持的算法
【发布时间】:2020-02-23 07:54:35
【问题描述】:

我已经使用以下代码快速生成了私钥:

 let publicKeyAttr: [NSObject: NSObject] = [
                kSecAttrIsPermanent:true as NSObject,
                kSecAttrApplicationTag:"com.xeoscript.app.RsaFromScrach.public2".data(using: String.Encoding.utf8)! as NSObject] // added this value
        let privateKeyAttr: [NSObject: NSObject] = [
                kSecAttrIsPermanent:true as NSObject,
                kSecAttrApplicationTag:"com.xeoscript.app.RsaFromScrach.private2".data(using: String.Encoding.utf8)! as NSObject] // added this

        var keyPairAttr = [NSObject: NSObject]()
        keyPairAttr[kSecAttrKeyType] = kSecAttrKeyTypeRSA
        keyPairAttr[kSecAttrKeySizeInBits] = 2048 as NSObject
        keyPairAttr[kSecPublicKeyAttrs] = publicKeyAttr as NSObject
        keyPairAttr[kSecPrivateKeyAttrs] = privateKeyAttr as NSObject

        statusCode = SecKeyGeneratePair(keyPairAttr as CFDictionary, &publicKey, &privateKey)

然后我使用私钥对一条数据进行签名,使用SecKeyAlgorithm.rsaEncryptionPKCS1算法。

签名代码如下:

 public func sign(privateKey myPrivateKey: SecKey, value: String, base64EncodingOptions: Data.Base64EncodingOptions = []) throws -> String?
    {
        enum LoginErrors: Error {
            case badUsername
            case badPassword
        }
        guard #available(iOS 10.0, watchOS 3.0, tvOS 10.0, *) else {
               return "Not available"
           }
        let data = value.data(using: .utf8)!

        var error: Unmanaged<CFError>?
        guard let signedData = SecKeyCreateSignature(myPrivateKey,
                                                     SecKeyAlgorithm.rsaEncryptionPKCS1,
                                                     data as CFData,
                                                     &error) as Data? else
        {
            return nil
        }
        return "(signedData.base64EncodedString())"
    }

我遇到了这个异常:

[0] (null)  "NSDescription" : "algid:encrypt:RSA:PKCS1: algorithm not supported by the key <SecKeyRef algorithm id: 1, key type: RSAPrivateKey, version: 4, block size: 2048 bits, addr: 0x280a0e5a0>"  

【问题讨论】:

  • 无法测试代码,但您确定您不是要将 SecKeyAlgorithm.rsaSignatureDigestPKCS1v15SHA256 之类的内容传递给 createsignature 调用吗?将加密算法标识符 . 传递给 CreateSignature 调用似乎很奇怪。
  • @JoachimIsaksson 哪个部分不适合您?我可以提供更多代码实际上我仍在研究要使用的算法。我的 java 服务器在注册期间存储公钥,下次设备想要与服务器通信时,它会从设备发送带有私钥的签名数据。如果我使用SecKeyAlgorithm.rsaSignatureDigestPKCS1v15SHA256 验证在服务器端失败。 java服务器使用RSA,SHA256withRSA算法进行验证。

标签: java ios swift iphone cryptography


【解决方案1】:

SecKeyAlgorithm.rsaEncryptionPKCS1 不正确,这是尝试使用 RSA 私钥进行混合加密。

改为传递适当的内容,例如 rsaSignatureDigestPKCS1v15SHA256rsaSignatureDigestPSSSHA256 或显示的其他选项之一 here

注意,rsaSignatureDigestPKCS1v15SHA256 是确定性的。

另外,我建议在 2020 年使用椭圆曲线签名,RSA,无论多么诱人,都是错误的选择。

现在支持 ECC 的华丽库太多了,我不会使用 SecKit。

【讨论】:

  • 我用 rsaSignatureDigestPKCS1v15SHA256 替换了 rsaEncryptionPKCS1,我得到了经过签名的 base64 字符串。真正的问题是无法使用 java 服务器上的 public 验证这一点。背景:我的 java 服务器在注册期间存储公钥,下次设备想要与服务器通信时,它会从设备发送带有私钥的签名数据。如果我使用 SecKeyAlgorithm.rsaSignatureDigestPKCS1v15SHA256 验证在服务器端失败,验证时布尔值为 false。 java服务器使用RSA、SHA256withRSA算法进行验证。
  • 我用这个在线工具验证:8gwifi.org/…Java代码验证:fun verify(publicKey: PublicKey, challenge: String, signature: String): Boolean { val sign = Signature.getInstance( "SHA256withRSA") sign.initVerify(publicKey) sign.update(challenge.toByteArray(Charsets.UTF_8)) return sign.verify(Base64.decode(signature, Base64.DEFAULT)) }
  • 当然我明白,我个人只会在 iOS 和服务器端使用 libsodium。您在服务器上使用哪个库?我认为这只是服务器的 RSA 实现需要不同的填充方案。
  • 我正在使用java.security.Signature 进行验证。验证用Java代码:fun verify(publicKey: PublicKey, challenge: String, signature: String): Boolean { val sign = Signature.getInstance("SHA256withRSA") sign.initVerify(publicKey) sign.update(challenge.toByteArray()) return sign.verify(Base64.decode(signature, Base64.DEFAULT)) }
  • 啊,这几乎肯定是填充方案之间的不兼容,我稍后会在移动设备上查看。
猜你喜欢
  • 2016-12-28
  • 1970-01-01
  • 2020-03-06
  • 1970-01-01
  • 1970-01-01
  • 2013-05-30
  • 2020-01-24
  • 1970-01-01
  • 2013-12-09
相关资源
最近更新 更多