Получить SecKey из строки закрытого ключа RSA, закодированной парольной фразой в Swift или Objective C - PullRequest
3 голосов
/ 25 апреля 2020

У нас есть корпоративное мобильное приложение, которое поставляется с зашифрованным закрытым ключом. Мы намерены предоставить пользователям парольную фразу для использования этого закрытого ключа, который затем позволит им обмениваться данными с внутренним сервером. Ранее я настроил это с помощью Python или C#, но не могу понять, как это сделать в Swift или Objective C. Я адаптировал кое-что из этого вопроса о переполнении стека: Шифрование с использованием сертификата RSA в 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 String также работает и для меня. Мне удобно работать с Objective- C или Swift на основе ответа.

EDIT Вот пример ключа для целей тестирования:

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

1 Ответ

1 голос
/ 01 мая 2020

Я взял предоставленный вами образец зашифрованного ключа и вставил его в этот превосходный декодер ASN.1 . Он дает следующий результат:

ASN.1 Decoding Result

Это очень полезная сводка шагов, необходимых для дешифрования зашифрованного текста с помощью имеющегося у вас ключа:

  • Первые две записи OBJECT IDENTIFIER указывают на режим заполнения, используемый во время шифрования, и функцию получения ключа, используемую для получения ключа шифрования из вашего "кода доступа": заполнение PKCS # 5 и PBKDF2 для получения ключа. Значения OCTET STRING и INTEGER, указанные ниже, представляют собой соль и число итераций для PBKDF2.
  • Третий OBJECT IDENTIFIER указывает алгоритм шифрования - TripleDES в режиме CB C. Не идеально, но достаточно безопасно, я думаю. OCTET STRING под этим является 8-байтовым IV, поскольку DES имеет размер блока 64 бита.
  • Финальный OCTET STRING - это зашифрованный текст.

Итак, в итоге вам нужно:

  • Найти способ получить нужные вам значения, например, соль, число итераций, IV и зашифрованный текст - при условии, что алгоритмы, используемые для этих ключей, остаются прежними. Иногда вы можете сойти с рук, перепрыгивая в необработанные данные и вырезая эти значения - в зависимости от ваших потребностей, вам может понадобиться использовать декодер ASN.1.
  • Когда придет время для расшифровки - вытащите соль и число итераций (сначала OCTET STRING и INTEGER). Вытащите IV (второй OCTET STRING) и зашифрованный текст (последний OCTET STRING).
  • Примените PBKDF2, используя указанную соль и число итераций, к вашему паролю, который вы указали в вопросе. Из этого вам потребуется извлечь 192 бита ключевого материала, так как мы используем TripleDES.
  • Расшифруйте зашифрованный текст, используя ключевой материал из последнего шага в режиме CB C, используя IV, который вы извлекли. Используйте отступ PCKS # 5, который обычно используется по умолчанию.
  • Готово!
...