ios - 从使用 Swift 或 Objective C 中的密码短语编码的 RSA 私钥字符串中检索 SecKey

标签 ios objective-c swift encryption rsa

我们有一个带有加密私钥的企业移动应用程序。我们打算为用户提供密码,以便使用该私钥,然后允许他们与后端服务器进行通信。我之前已经使用 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 的答案。

编辑 这是用于测试目的的示例 key :

-----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-----

这个 key 的密码是

8720c10d735d7fb218b9e48db942a494

最佳答案

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

ASN.1 Decoding Result

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

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

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

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

关于ios - 从使用 Swift 或 Objective C 中的密码短语编码的 RSA 私钥字符串中检索 SecKey,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61428695/

相关文章:

ios - 如何在 20 个字符后切断 TextView ?

ios - FirebaseDatabase - removeAllObservers() - 它实际上删除了什么?

ios - 在 Objective-C 中创建仅对子类可见的属性

ios - TableView限制使用(Swift)

ios - dequeueReusableCellWithIdentifier 返回 nil

ios - 为无尽的跑酷游戏创建动态大小的 SKSpriteNode 平台

swift - 在 NSImage 上使用 lockFocus 时如何强制使用非视网膜图像?

ios - 使用 AVPlayer 黑屏(在模拟器和设备中)

ios - Swift 的 equatable 协议(protocol)一致性检查

ios - Swift:使用 drawStroke(_:touch:) 绘制一条半透明线