Как создать пару асимметричных ключей RSA в Swift для IOS?

Мне нужен способ создать пару асимметричных ключей RSA в Swift. Мне не нужно хранить его в связке ключей или еще где-то. Мне просто нужно сгенерировать пару ключей и засунуть оба ключа в переменные String.

Ключи должны быть совместимы с PHP на другом конце. Я буду использовать симметричное шифрование, чтобы защитить закрытый ключ и сохранить его на телефоне. Я отправлю открытый ключ веб-службе, реализованной на PHP, и веб-служба сохранит открытый ключ в базе данных.

Этот открытый ключ позже будет использоваться веб-службой для шифрования таких значений, как одноразовые пароли и другие конфиденциальные значения, предназначенные для приложения IOS. Я реализую аналогичную схему для небольших фрагментов данных, поступающих из приложения IOS в веб-службу.

Единственное задокументированное объявление API, которое я смог найти для создания пары ключей в Swift, показано на сайте developer.apple.com:

func SecKeyGeneratePairAsync(_ parameters: CFDictionary!,
                           _ deliveryQueue: dispatch_queue_t!,
                           _ result: SecKeyGeneratePairBlock!)

Я пытался понять, как это использовать, но XCode не любит символы подчеркивания, и я не уверен, что я на самом деле должен делать с этим или как его использовать.

Даже если XCode примет это, я не уверен, как я буду вызывать функцию и какие значения ей передавать и т. д. Я включил «безопасность импорта» вверху, так что это не проблема.

Смешно, что это должно быть так сложно. Все, что я хочу сделать, это сгенерировать пару асимметричных ключей.

Это легко сделать на PHP, .NET, Java или любом другом языке, но я не могу найти четкую документацию по этому поводу для Swift. Я должен использовать Swift для этого приложения. Я не хочу использовать OpenSSL, потому что он устарел.

Я использую Swift, потому что чертовски ненавижу объективный C. Swift — причина, по которой я наконец-то перешел к разработке IOS.

Я не знаю, как интегрировать класс Objective C со Swift, и я бы предпочел чистое решение Swift, если оно есть. Если нет, я был бы признателен за некоторые советы о том, как интегрировать решение Objective C и заставить его работать.

Приведенный выше фрагмент — единственный вызов функции, предоставляемый Apple, и, естественно, он неполный, не имеет смысла и не работает.


person C Landreaux    schedule 03.03.2015    source источник
comment
См. мой ответ на этот вопрос для примера вызова SecKeyGeneratePair() из Swift. Это не асинхронная пара, но вы должны туда добраться.   -  person Jeff Hay    schedule 16.04.2015
comment
Асинхронность просто означает, что вызов выполняется в фоновом режиме и вызывает обратный вызов, когда он завершен, чтобы вернуть пару ключей, в то время как SecKeyGeneratePair делает это в работающем потоке и возвращает ключ. Ключи одинаковые.   -  person gnasher729    schedule 13.08.2017
comment
Я знаю, что это поздний ответ. Но если вы все еще ищете это, обратитесь к среде. com/@nipunr/   -  person NipunR    schedule 02.04.2020


Ответы (2)


Хороший пример того, как это сделать в Swift, есть в проекте CertificateSigningRequestSwift_Test на GitHub. Используя один вызов SecKeyCreateRandomKey(), можно одновременно сгенерировать пару открытого и закрытого ключей, и они будут сохранены в цепочке ключей.

        let tagPublic = "com.example.public"
        let tagPrivate = "com.example.private"

        let publicKeyParameters: [String: AnyObject] = [
            String(kSecAttrIsPermanent): kCFBooleanTrue,
            String(kSecAttrApplicationTag): tagPublic as AnyObject,
            String(kSecAttrAccessible): kSecAttrAccessibleAlways
        ]

        var privateKeyParameters: [String: AnyObject] = [
            String(kSecAttrIsPermanent): kCFBooleanTrue,
            String(kSecAttrApplicationTag): tagPrivate as AnyObject,
            String(kSecAttrAccessible): kSecAttrAccessibleAlways
        ]

        //Define what type of keys to be generated here
        var parameters: [String: AnyObject] = [
            String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
            String(kSecAttrKeySizeInBits): 2048,
            String(kSecReturnRef): kCFBooleanTrue,
            kSecPublicKeyAttrs as String: publicKeyParameters as AnyObject,
            kSecPrivateKeyAttrs as String: privateKeyParameters as AnyObject,
        ]

        //Use Apple Security Framework to generate keys, save them to application keychain
        var error: Unmanaged<CFError>?
        let privateKey = SecKeyCreateRandomKey(parameters as CFDictionary, &error)

        if privateKey == nil{
            print("Error creating keys occurred: \(error!.takeRetainedValue() as Error), keys weren't created")
            return
        }

        //Get generated public key
        let query: [String: AnyObject] = [
            String(kSecClass): kSecClassKey,
            String(kSecAttrKeyType): kSecAttrKeyTypeRSA,
            String(kSecAttrApplicationTag): tagPublic as AnyObject,
            String(kSecReturnRef): kCFBooleanTrue
        ]

        var publicKeyReturn:AnyObject?

        let result = SecItemCopyMatching(query as CFDictionary, &publicKeyReturn)

        if result != errSecSuccess{
            print("Error getting publicKey from keychain occurred: \(result)")
            return
        }

        let publicKey = publicKeyReturn as! SecKey?

        //Set block size
        let keyBlockSize = SecKeyGetBlockSize(self.publicKey!)

        //Ask keychain to provide the publicKey in bits
        let query: [String: AnyObject] = [
            String(kSecClass): kSecClassKey,
            String(kSecAttrKeyType): keyAlgorithm.secKeyAttrType,
            String(kSecAttrApplicationTag): tagPublic as AnyObject,
            String(kSecReturnData): kCFBooleanTrue
        ]

        var tempPublicKeyBits:AnyObject?

        _ = SecItemCopyMatching(query as CFDictionary, &tempPublicKeyBits)

        guard let publicKeyBits = tempPublicKeyBits as? Data else {
            return
        }
person mbonness    schedule 11.11.2017

Heimdall кажется тем, что вы ищете. Он прост в использовании, может создавать пары ключей RSA, шифровать, расшифровывать, подписывать и проверять.

Он использует цепочку для ключей iOS/OS X для хранения ключей, поэтому ключи хранятся безопасным образом.

Из файла Readme на GitHub:

if let heimdall = Heimdall(tagPrefix: "com.example") {
    let testString = "This is a test string"

    // Encryption/Decryption
    if let encryptedString = heimdall.encrypt(testString) {
        println(encryptedString) // "cQzaQCQLhAWqkDyPoHnPrpsVh..."

        if let decryptedString = heimdall.decrypt(encryptedString) {
            println(decryptedString) // "This is a test string"
        }
    }

    // Signatures/Verification
    if let signature = heimdall.sign(testString) {
        println(signature) // "fMVOFj6SQ7h+cZTEXZxkpgaDsMrki..."
        var verified = heimdall.verify(testString, signatureBase64: signature)
        println(verified) // True

        // If someone meddles with the message and the signature becomes invalid
        verified = heimdall.verify(testString + "injected false message",
                                    signatureBase64: signature)
        println(verified) // False
    }
}
person vrwim    schedule 05.05.2015
comment
Насколько я могу судить, Хеймдалль делает все с RSA, кроме генерирует пару ключей, о чем и спрашивали в сообщении. - person Ogre Codes; 04.02.2017
comment
@OgreCodes Heimdall действительно генерирует пары ключей. - person SeanR; 30.05.2017