2015-03-03 5 views
4

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

Ключи должны быть совместимы с 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. Свифт - причина, по которой я, наконец, прыгаю в развитие IOS.

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

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

Пожалуйста, помогите, если вы можете ... это было бы очень оценено. :) Спасибо

- = Cameron

+0

Смотрите мой ответ на [этот вопрос] (http://stackoverflow.com/questions/29489391/generate-base64-url-encoded-x-509-format-2048-bit-rsa-public-key -with-swift/29662582 # 29662582) для примера вызова SecKeyGeneratePair() из Swift. Это не асинхронная пара, но вы должны туда попасть. –

+0

«Async» означает, что вызов выполняется в фоновом режиме и вызывает обратный вызов, когда он завершен, чтобы вернуть пару ключей, в то время как SecKeyGeneratePair выполняет его в текущем потоке и возвращает ключ. Клавиши одинаковы. – gnasher729

ответ

0

Я не знаком с быстрым только решением этой проблемы, но прохладная вещь о стриже, что все, что было сделано в Objective-C по-прежнему относится к быстрому основанные на проектах.

Чтобы выполнить шифрование RSA я использовал Приближенные упоминалось в следующей ссылке:

http://jslim.net/blog/2013/01/05/rsa-encryption-in-ios-and-decrypt-it-using-php/

В основном автор создает оболочку вокруг каркаса безопасности классов Apple, так что вы можете сосредоточиться только на шифрование.Кроме того, вы можете изменить методы инициализации, как следовать, чтобы получить длину открытого ключа и данные/ключевой путь общественности в качестве параметров:

- (id)initWithData:(NSData *)keyData publicKeyLength:(int) publicKeyLength { 
    self = [super init]; 

    if (self) { 
     if (keyData == nil) { 
      return nil; 
     } 

     certificate = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef) keyData); 
     if (certificate == nil) { 
      NSLog(@"Can not read certificate from data"); 
      return nil; 
     } 

     policy = SecPolicyCreateBasicX509(); 
     OSStatus returnCode = SecTrustCreateWithCertificates(certificate, policy, &trust); 
     if (returnCode != 0) { 
      NSLog(@"SecTrustCreateWithCertificates fail. Error Code: %d", (int)returnCode); 
      return nil; 
     } 

     SecTrustResultType trustResultType; 
     returnCode = SecTrustEvaluate(trust, &trustResultType); 
     if (returnCode != 0) { 
      return nil; 
     } 

     publicKey = SecTrustCopyPublicKey(trust); 
     if (publicKey == nil) { 
      NSLog(@"SecTrustCopyPublicKey fail"); 
      return nil; 
     } 

     maxPlainLen = SecKeyGetBlockSize(publicKey) - 12; 

     self.publicKeyLength = publicKeyLength; 
    } 

    return self; 
} 

- (id)initWithPublicKeyPath:(NSString *)publicKeyPath publicKeyLength:(int) publicKeyLength { 
    if (publicKeyPath == nil) { 
     NSLog(@"Can not find %@", publicKeyPath); 
     return nil; 
    } 

    NSData *publicKeyFileContent = [NSData dataWithContentsOfFile:publicKeyPath]; 

    return [self initWithData:publicKeyFileContent publicKeyLength:publicKeyLength]; 
} 

Эти классы могут быть использованы через быстры, чтобы сделать это просто добавить файлы проект и файл заголовка на Bridging-Header.h. После этого вы используете класс на стрижа:

let rsa = RSA(publicKeyPath: "public_key.der",publicKeyLength: 256); 
rsa.encryptToString("stringToEncrypt") 
1

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

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

Из GitHub Readme:

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 
    } 
} 
+0

Насколько я могу судить, Heimdall делает все с RSA * кроме * генерирует ключевую пару, о которой сообщается в сообщении. –

+0

@OgreCodes Heimdall * does * создает пары ключей. – SeanR

0

Существует хороший пример того, как сделать это в 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 
     }