【问题标题】:Retrieve SecKey from RSA private key string encoded with passphrase in Swift or Objective C从 Swift 或 Objective C 中用密码短语编码的 RSA 私钥字符串中检索 SecKey
【发布时间】:2020-08-09 05:25:52
【问题描述】:

我们有一个带有加密私钥的企业移动应用。我们打算为用户提供密码以使用该私钥,这将允许他们与后端服务器进行通信。我之前使用 Python 或 C# 进行了设置,但无法弄清楚如何在 Swift 或 Objective C 中执行此操作。我已经从这个堆栈溢出问题中调整了其中的一些内容:Encrypt using RSA Certificate in Swift

     static func getCertificate(from certificate: String?, usingPhrase phrase: String?) -> SecKey? {
        guard let certificate = certificate else {
            print("Nil string passed in, nil being returned")
            return nil
        }
        let beginning = "-----BEGIN ENCRYPTED PRIVATE KEY-----"
        let tail = "-----END ENCRYPTED PRIVATE KEY-----"
        let certificateString = certificate.replacingOccurrences(of: beginning, with: "")
                                           .replacingOccurrences(of: tail, with: "")
                                           .replacingOccurrences(of: "\n", with: "")
                                           .replacingOccurrences(of: " ", with: "")
        guard let data = Data(base64Encoded: certificateString) else {
            print("Unable to cast string to data")
            return nil
        }

        // ** I'm assuming here is where I need to decrypt the key before I can create the certificate **

        guard let cert = SecCertificateCreateWithData(nil, data as NSData) else {
            print("Unable to cast certificate to SecCertificate")
            return nil
        }

        var secTrust: SecTrust?

        // Retrieve a SecTrust using the SecCertificate object. Provide X509 as policy
        let status = SecTrustCreateWithCertificates(cert, SecPolicyCreateBasicX509(), &secTrust)

        // Check if the trust generation is success
        guard status == errSecSuccess else { return nil }

        // Retrieve the SecKey using the trust hence generated
        guard let trust = secTrust else {
            print("Trust policy not created")
            return nil
        }

        // ** I acknowledge that this method creates a public key and I am passing in a private key
        // ** I am not sure what method needs to be used instead
        guard let secKey = SecTrustCopyPublicKey(trust) else { return nil }

        return secKey
    }

最终,我需要使用密码来解密私钥。我计划将它用作 SecKey,但获取它的 Base64 字符串表示形式也适用于我。我很乐意通过基于 Objective-C 或 Swift 的答案工作。

编辑 以下是用于测试目的的示例密钥:

-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIj6w/NvIjTXICAggA
MBQGCCqGSIb3DQMHBAi6qjkA0+yxyQSCBMhqdUDLRCLUjbgqe3rbF2lHn6yTsYbk
pfLWHkKT4pvQtaqXJvPZErb3E27va3HXvVDJfJS0/iwsnzIn6p2J9ZtgIGs4OBRU
kUw8lVAhNHTkAw/sj+OHdWexfOL5vKE3DgXqnAVGyhm4CNDXQ/9UDqkmtmHsMOlz
nqbOdWhMS/Uj/Dh41urw3sstpX4wZCHGTFNDL83pDAv7jfAZF/NSQq8ft/BPknMu
HLvYvd3fR4iKqKswcvR5c2q+CLbfEbXbVty6B/JMDSoi3wuh9lezMesIhTUYDSaK
QgkCEtrJ4FsO/tPXtyGvCjKVgvfvn8njQPtphq/gbKBeXpopsFGi19iY8fCkPQSb
Cp6FttMvJPwJvIb/qUZWGu9OWaBhmn0MH+qtXED6yxqXSyQDRYg1Vurfm0azQxUb
zJIy8qgla9GVvoGYpIGDvsQZFzur6le8G6/6c85raI9LZ88Bo8gEsTeQgPMxG1c+
7kRvn/hl/n0Oh8VsPOHjx2N/Y9vcmlyIlCDPIuGiYcNy1ICDv/kaBD9JVJVA5S7X
+MRZG8+EesjTiZseVUwK9OhnE4Jws2UzAk3zfMvzvnAgxue/FcRPUfYiHakNu83z
SFqayIUGz3zD0XLdWBVrh2QPvxW6eP3AFdIpjrPzwq1kDDw19VaAu7mw7JexrOyW
qvCO/VIHXqflL/OCxPT5BUQ9pbxTCEfv5wbWzczKWWub0AhPexDBW7wat3HwUGeb
oeEwnmNxAXxxz/RJeK1zKUAKGWQPI8X4bG/IZFmk1dgeJ8bo9My5b05Zw9d/gw7C
Xi5nZ5sG5ERp3jKLsT2czbr66w4HV4L38mASVtTUeXyySvnz//Ib40FC46Gi7SqP
pcpl1CrDi0UWe/cbQ/qkcaFrgdvIGsuSfZf8amq1FHnB47NUblYmm1WPCqeNtgzY
srAy/aVtF6FvG+uy6sCrP76c9HY1ZvyeO/82t/Sd5jnoq+VCKtarRNjEEfdwNGQp
X/ycspdn+a0XkXthSBvHWcCmQmgAV8Yp5TR0r2PgGqHk3lRq9/yKWy1gRuPSiRpZ
HzOOfZ4DmVELRf5R5+UCVJ5idkKZb2t+R7rl5/9grf8iCeUPngIkxrZvr4b7/mQm
fkmIMSUYT9CVeBprF5f2wLbbAmPpoUnULTnVzrOhZYCZGRQLyGGdX+CELBNxc8Er
dt4deeutCQm+H0d5V09HO9AOAwlESyt9q4CEAcSzSzzMygvWLe04csdcCSV2htAm
n0zDwhqGZ2LI+dUTGw4apOdBuNeveaHBrlp7XhCIOJ35SAWrb8baPizwl4iw5fA0
ucBZzRDAavDhj6XMQSwsOaCfzYfpASqwkm2Zjk3znWS18xpXRxvgqfCHpJRo9M4f
SQlRpT3Nqw5vn8BV+ioBvwxQd/1XsMbjKKwbwk+1wB/E/mHAiIQUQJ6Ec/WqzKqn
biqlBuSGLrS5O8ynu83DERFiatCAkNkl6nCaWtNu2KWtKM52y03BN3MBxS1kU+FI
afb7mN75j1gTZFH6EmujfVfrL/f8aO1dkxHO4IuWb5r7DaY7AByZgo1EKGiSIh3N
rtQVsAQr1/NcO6GVSHQU5egpI/eocvHvrAzsvlE2sqNBKm4NVogXjms7avKIbtA4
+Ro=
-----END ENCRYPTED PRIVATE KEY-----

此密钥的密码是

8720c10d735d7fb218b9e48db942a494

【问题讨论】:

  • 您能否提供您正在使用的密钥类型的样本,以便我进行检查?
  • @Harikrishnan,添加了示例密钥。感谢您查看此内容!

标签: ios objective-c swift encryption rsa


【解决方案1】:

我提取了您提供的示例加密密钥并将其粘贴到this excellent ASN.1 decoder。它产生以下结果:

这实际上是使用您拥有的密钥解密密文所需步骤的非常有用的总结:

  • 前两个OBJECT IDENTIFIER 条目提示加密期间使用的填充模式以及用于从“密码”获取加密密钥的密钥派生函数:PKCS #5 填充和用于密钥派生的 PBKDF2。其下方的 OCTET STRINGINTEGER 值是 PBKDF2 的盐和迭代计数。
  • 第三个OBJECT IDENTIFIER表示加密算法——CBC模式下的TripleDES。不理想,但我想足够安全。其下方的OCTET STRING 是 8 字节 IV,因为 DES 具有 64 位块大小。
  • 最后的OCTET STRING 是密文。

因此,总而言之,您需要:

  • 找到获得所需值的方法,例如salt、迭代计数、IV 和密文——假设用于这些密钥的算法保持不变。有时,您可以在原始数据中跳来跳去并将这些值切分出来 - 根据您的需要,您可能需要使用 ASN.1 解码器。
  • 当需要解密时 - 提取盐和迭代计数(首先是 OCTET STRINGINTEGER)。取出IV(第二个OCTET STRING)和密文(最后一个OCTET STRING)。
  • 使用指定的盐和迭代计数将 PBKDF2 应用于您的密码,即您在问题中提供的密码。您需要从中提取 192 位密钥材料,因为我们使用的是 TripleDES。
  • 使用您提取的 IV 在 CBC 模式下使用最后一步中的密钥材料解密密文。使用 PCKS#5 填充,这通常是默认设置。
  • 完成!

【讨论】:

  • 这真的很有帮助;我将查看他们的 JavaScript,看看我可以将什么转换为 Swift/Obj-C。我的偏好是用 Swift 编写(比 Obj-C 更舒服);您对实施有什么建议吗(您的步骤很有意义,不要误会我的意思)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-03
  • 1970-01-01
  • 2017-07-08
  • 1970-01-01
相关资源
最近更新 更多