2016-11-14 7 views
0

Я пытаюсь сделать следующее в моем IOS приложении:Ошибка аутентификации пытается подписать данные с ЕС закрытым ключом от Secure Enclave

  1. генерировать пару ключей с помощью SecKeyGeneratePair, хранение секретного ключа в Secure Enclave
  2. Войдите некоторые данные, используя секретный ключ

Это работает, если я повешу на секретный ключе справки, когда ключи первые сгенерированными, но не работает, если я пытаюсь извлечь ссылку из брелки после отбрасывания начальный p ointer.

Ключи генерируются следующим образом:

func generateKeyPair() -> Bool { 

    if let access = SecAccessControlCreateWithFlags(nil, 
                kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, 
                [.userPresence, .privateKeyUsage], 
                nil) { 

     let privateKeyAttr = [kSecAttrIsPermanent : 1, 
           kSecAttrApplicationTag : privateTag, 
           kSecAttrAccessControl as String: access 
      ] as NSDictionary 

     let publicKeyAttr = [kSecAttrIsPermanent : 0, 
          kSecAttrApplicationTag : publicTag 
      ] as NSDictionary 

     let keyPairAttr = [kSecAttrKeySizeInBits : 256, 
          kSecAttrKeyType : kSecAttrKeyTypeEC, 
          kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave, 
          kSecPrivateKeyAttrs : privateKeyAttr, 
          kSecPublicKeyAttrs : publicKeyAttr] as NSDictionary 

     let err = SecKeyGeneratePair(keyPairAttr, &publicKey, &privateKey) 
     return err == noErr 
} 

метод Подписание ниже:

func signData(plainText: Data) -> NSData? {     
    guard privateKey != nil else { 
     print("Private key unavailable") 
     return nil 
    } 

    let digestToSign = self.sha1DigestForData(data: plainText as NSData) as Data 

    let signature = UnsafeMutablePointer<UInt8>.allocate(capacity: 128) 
    var signatureLength = 128 
    let err = SecKeyRawSign(privateKey!, 
          .PKCS1SHA1, 
          [UInt8](digestToSign), 
          Int(CC_SHA1_DIGEST_LENGTH), 
          signature, 
          &signatureLength) 

    print("Signature status: \(err)") 

    let sigData = NSData(bytes: signature, length: Int(signatureLength)) 

    return sigData 
} 

func sha1DigestForData(data: NSData) -> NSData { 
    let len = Int(CC_SHA1_DIGEST_LENGTH) 
    let digest = UnsafeMutablePointer<UInt8>.allocate(capacity: len) 
    CC_SHA1(data.bytes, CC_LONG(data.length), digest) 
    return NSData(bytesNoCopy: UnsafeMutableRawPointer(digest), length: len) 
} 

Это просит моего отпечатка пальца и работает безупречно. Затем я использую другой способ, чтобы получить ключ ссылки из брелка:

func getPrivateKeyRef() -> SecKey? { 

    let parameters = [ 
     kSecClass as String: kSecClassKey, 
     kSecAttrKeyClass as String: kSecAttrKeyClassPrivate, 
     kSecAttrApplicationTag as String: privateTag, 
     kSecReturnRef as String: true, 
     ] as [String : Any] 
    var ref: AnyObject? 
    let status = SecItemCopyMatching(parameters as CFDictionary, &ref) 
    print("Get key status: \(status)") 

    if status == errSecSuccess { return ref as! SecKey? } else { return nil } 
} 

SecItemCopyMatching возвращает статус успеха, но попытка использовать полученный SecKey элемент в качестве секретного ключа в SecKeyRawSign приводит к ошибке -25293 Authorization/Authentication failed. появляется только этот статус после того, как я предоставил свой отпечаток, так что фактическая проверка отпечатка пальца удалась, но ключ каким-то образом остается непригодным.

Каков правильный способ использования ключа, сохраненного в Secure Enclave, для подписи данных?

+1

Вы были в состоянии получить это работает? У меня такая же проблема, SecItemCopyMatch успешна, но диалог отпечатков пальцев не запускается, и SecKeyRawSign терпит неудачу. – Krypton

+0

@ Криптон да, см. Мой собственный ответ ниже, как я получил его на работу. – SaltyNuts

ответ

0

Понравилось использовать атрибут kSecAttrLabel, что необходимо для правильной выборки ключа. Он должен указываться при создании ключей и при их получении через SecItemCopyMatching.

Мой рабочий раствор для извлечения закрытого ключа:

func getPrivateKey() -> SecKey? { 
    let parameters = [ 
     kSecClass as String: kSecClassKey, 
     kSecAttrKeyClass as String: kSecAttrKeyClassPrivate, 
     kSecAttrApplicationTag as String : "privateTag", 
     kSecAttrLabel as String : "privateTag", 
     kSecReturnRef as String: true, 
     ] as [String : Any] 
    var ref: AnyObject? 
    let status = SecItemCopyMatching(parameters as CFDictionary, &ref) 
    if status == errSecSuccess { 
     return (ref as! SecKey) 
    } 
    return nil 
} 

Если пара ключей был создан так:

var publicKey:SecKey? 
    var privateKey:SecKey? 
    if let access = SecAccessControlCreateWithFlags(nil, 
                kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, 
                [.userPresence, .privateKeyUsage], 
                nil) { 

     let privateKeyAttr = [kSecAttrIsPermanent : 1, 
           kSecAttrApplicationTag as String : "privateTag", 
           kSecAttrLabel as String : "privateTag", 
           kSecAttrAccessControl as String: access 
      ] as NSDictionary 

     let publicKeyAttr = [kSecAttrIsPermanent : 0, 
          kSecAttrApplicationTag as String : "publicTag", 
          kSecAttrLabel as String : "publicTag", 
          ] as NSDictionary 

     // only 256 bit EC keys are supported in the Secure Enclave 
     let keyPairAttr = [kSecAttrKeySizeInBits : 256, 
          kSecAttrKeyType : kSecAttrKeyTypeEC, 
          kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave, 
          kSecPrivateKeyAttrs : privateKeyAttr, 
          kSecPublicKeyAttrs : publicKeyAttr] as NSDictionary 

     let err = SecKeyGeneratePair(keyPairAttr, &publicKey, &privateKey) 

 Смежные вопросы

  • Нет связанных вопросов^_^