Keychain con Swift

Privacidad y Seguridad son dos de los pilares fundamentales sobre los que debemos construir nuestras Apps, no importa el sistema para el que las hagamos.

En este tutorial vamos a ver como usar el Keychain de iOS para guardar información sensible de forma segura. ¿Y qué es el Keychain?

The keychain services API helps you solve this problem by giving your app a mechanism to store small bits of user data in an encrypted database called a keychain.

Así que lo primero que tenemos que tener claro es que sirve para guardar cantidades pequeñas de información, si queremos guardar de forma segura información del tamaño de una base de datos tendrás que emplear otras técnicas.

Estructura de Keychain

Lo primero que tenemos que saber es que la información que guardemos en el Keychain se agrupa en clases, y que dichas clases tienen una serie de atributos en los que está almacenada la información.

Las clases nos dicen el tipo de información que vamos a guardar, una clave, un certificado… Existe 5 clases:

  • kSecClassGenericPassword

  • kSecClassInternetPassword

  • kSecClassCertificate

  • kSecClassIdentity

  • kSecClassKey

Cada una de estás clases tiene una serie de atributos que podemos cumplimentar como ya hemos comentado antes. Para ver una lista completa de cada uno de estos atributos lo mejor es ir la página de Item Attributes Keys and Values.

Y qué es lo que vamos a hacer

Vamos a usar una App de ejemplo que almacena una contraseña de acceso a un servicio de series TV imaginario.

Lo primero que tenemos que aprender es a buscar en el Keychain un elemento en concreto.

En nuestro caso buscaremos una contraseña para un sevicio y usuario determinado. Y eso se consigue gracias a la función SecItemCopyMatching(_:_:) que devuelve un OSStatus con el estado de la operación de búsqueda.

Los parámetros que espera la función son…

  1. Un diccionario que describe la búsqueda que queremos realizar. Este diccionario, de tipo CFDictionary, puede contener…
    • La clase que queremos buscar

    • Los atributos que deben tener los resultado.

    • Los parámetros de búsqueda. Puedes encontrarlos en Search Attribute Keys and Values. Aquí especificamos si queremos hacer una búsqueda que ignore mayúsculas y minúsculas, que coincida el texto completo, etc.

    • Los tipos de vuelta. Hay una lista en Item Return Result Keys y pueden ser…

      • kSecRetuernRef para obtener una referencia a los datos.

      • kSecReturnPersistentRef para una referencia de datos persistentes

      • kSecReturnData para los datos en sí.

      • kSecReturnAttributes para obtener sólo los atributos.

  2. Una referencia a la estructura que contedrá los resultado de la búsqueda.

Veamos un ejemplo:

Esta referencia es un tipo CFTypeRef y que luego podremos convertir en un diccionario o en un array mediantes un casting.

Añadiendo al Keychain

Ahora que ya sabemos buscar podemos comprobar que en la primera ejecución de la app no hay ninguna contraseña guardada para nuestro servicio por lo que ha llegado el momento de añadir una nueva en el Keychain.

Esto lo vamos a hacer con la función SecItemAdd(_:_:) que recibe como parámetros un diccionario de tipo CFDictionary con los datos de lo que queremos guardar y un referencia de tipo CFTypeRef que contendrá la nueva información recien añadida.

El diccionario puede contener la siguiente información:

  1. La clase del tipo que queremos añadir.

  2. El dato que queremos almacenar. Para ello usamos la clave kSecValueData

  3. Atributos adicionales que nos ayudarán a encontrar este elemento en el Keychain posteriormente. Los podemos encontrar en Item Attribute Keys and Values.

  4. El tipo de dato que queremos devolver cuando se complete la operación. Los encontramos nuevamente en Item Return Result Keys.

Por ejemplo…

La función devuelve un OSStatus con información sobre el estado de la operación de guardado.

Modificar un dato en el Keychain

Esta operación la haremos haciendo uso de la función SecItemUpdate(_:_:) a la que le pasamos como parámetro un diccionario con los parámetros de búsqueda para encontrar el elemento y otro diccionar con los nuevos valores.

Eliminar algo del Keychain

Para borrar algo del Keychain invocamos la función SecItemDelete(_:) pero en este caso sólo necesitamos pasar un diccionar con los parámetros de la búsqueda para encontrar el elemento.

Código Fuente

Como siempre tenéis a vuestra disposición al App de prueba que acompaña al artículo en este repositorio de GitHub.

¡Bola Extra!

Además de ver Keychain también podrás echarle un vistazo el nuevo tipo Result recien incorporado a Swift 5.

Se usa para devolver el resultado de una de las operación del Keychain y en el controlador verás como se contruye usando su inicializador.

Próximo artículo

En la siguiente entrada verás como se integra el Keychain con Face ID o Touch ID.

Y si quieres ir preparándote puedes repasar la guía sobre Face ID.

Enlaces de interés

QUIZÁ TE INTERESE…