Techniques de Sécurité Courantes et Cryptographie en Développement iOS

Introduction aux Méthodes de Sécurité iOS

Dans le développement d'applications iOS, la sécurité des données est une considération primordiale. Tandis que des solutions simples comme NSUserDefaults peuvent servir au stockage de données non sensibles, elles ne sont absolument pas adaptées aux informations confidentielles, telles que les mots de passe. Pour une protection robuste, le Trousseau d'accès (Keychain) est le mécanisme recommandé, car il garantit un chiffrement système des données. Cet article explore diverses approches pour sécuriser les informations et authentifier les utilisateurs sur la plateforme iOS.

I. Encodage Base64

L'encodage Base64 est une méthode standard permettant de transformer des données binaires en une séquence de caractères ASCII. Ce n'est pas une méthode de chiffrement à proprement parler, car elle est réversible et son but principal est de permettre la transmission de données binaires dans des systèmes textuels (comme les e-mails ou les URLs).

Principes Fondamentaux :

  • Le Base64 convertit des groupes de 3 octets (24 bits) en 4 caractères Base64 (chaque caractère représentant 6 bits).
  • Si le nombre d'octets d'origine n'est pas un multiple de 3, des caractères de remplissage = sont ajoutés à la fin.
  • La taille des données encodées augmente d'environ un tiers.
  • Les API Objective-C facilitant l'encodage et le décodage Base64 sont courantes depuis iOS 7.

Encodage d'un fichier


// Chemin vers le fichier à encoder
NSString *cheminFichierOriginal = @"/Users/utilisateur/Desktop/photos/photo_vacances.jpeg";
NSData *donneesOriginales = [NSData dataWithContentsOfFile:cheminFichierOriginal];

if (donneesOriginales) {
    // Encodage Base64 des données binaires
    NSData *donneesEncodeesBase64 = [donneesOriginales base64EncodedDataWithOptions:0];

    // Spécifier le chemin de sortie pour le fichier encodé
    NSString *cheminFichierEncode = @"/Users/utilisateur/Desktop/photo_encodee.b64";
    if ([donneesEncodeesBase64 writeToFile:cheminFichierEncode atomically:YES]) {
        NSLog(@"Fichier encodé avec succès et enregistré sous : %@", cheminFichierEncode);
    } else {
        NSLog(@"Échec de l'enregistrement du fichier encodé.");
    }
} else {
    NSLog(@"Impossible de lire les données du fichier original.");
}

Décodage d'un fichier


// Chemin vers le fichier Base64 encodé
NSString *cheminFichierEncode = @"/Users/utilisateur/Desktop/photo_encodee.b64";
NSData *donneesEncodeesBase64 = [NSData dataWithContentsOfFile:cheminFichierEncode];

if (donneesEncodeesBase64) {
    // Décodage des données Base64
    NSData *donneesDecryptees = [[NSData alloc] initWithBase64EncodedData:donneesEncodeesBase64 options:0];

    // Spécifier le chemin de sortie pour le fichier décodé
    NSString *cheminFichierDecode = @"/Users/utilisateur/Desktop/photo_restauree.jpeg";
    if ([donneesDecryptees writeToFile:cheminFichierDecode atomically:YES]) {
        NSLog(@"Fichier décodé avec succès et enregistré sous : %@", cheminFichierDecode);
    } else {
        NSLog(@"Échec de l'enregistrement du fichier décodé.");
    }
} else {
    NSLog(@"Impossible de lire les données du fichier encodé.");
}

Opérations Base64 via Terminal :


# Encoder un fichier image et sauvegarder le résultat dans un fichier texte
base64 mon_image.jpg -o mon_image.txt

# Décoder un fichier texte Base64 pour recréer l'image
base64 -D mon_image.txt -o image_restauree.png

# Encoder une chaîne de caractères
echo "Bonjour le monde" | base64
# Résultat typique : Qm9uam91ciBsZSBtb25kZQo=

# Décoder une chaîne Base64
echo "Qm9uam91ciBsZSBtb25kZQo=" | base64 -D
# Résultat : Bonjour le monde

II. Sécurisation des Requêtes POST

Pour illustrer un flux d'authentification basique avec une approche de sécurité simple (Base64 pour le mot de passe stocké localement), considérons un scénario de connexion utilisateur.

A. Configuration de l'Interface Utilisateur

Un écran de connexion typique comprendra :

  • Deux champs de texte (UITextField) pour le nom d'utilisateur et le mot de passe.
  • Un bouton de connexion (UIButton).

L'écran principal de l'application pourrait inclure une UINavigationController et un bouton de déconnexion.

B. Implémentation de la Logique d'Authentification

Chargement des informations utilisateur locales


- (void)chargerInformationsUtilisateurLocal {
    NSUserDefaults *parametresUtilisateur = [NSUserDefaults standardUserDefaults];
    self.champNomUtilisateur.text = [parametresUtilisateur objectForKey:@"cleNomUtilisateur"];
    // Le mot de passe lu ici est toujours encodé en Base64
    self.champMotDePasse.text = [parametresUtilisateur objectForKey:@"cleMotDePasse"];
}

Enregistrement sécurisé des informations utilisateur


- (void)enregistrerInformationsUtilisateurLocal {
    NSUserDefaults *parametresUtilisateur = [NSUserDefaults standardUserDefaults];

    // Stockage du nom d'utilisateur
    [parametresUtilisateur setObject:self.champNomUtilisateur.text forKey:@"cleNomUtilisateur"];

    // Encodage Base64 du mot de passe avant stockage
    NSData *donneesMotDePasse = [self.champMotDePasse.text dataUsingEncoding:NSUTF8StringEncoding];
    NSString *motDePasseEncode = [donneesMotDePasse base64EncodedStringWithOptions:0];

    // Stockage du mot de passe encodé
    [parametresUtilisateur setObject:motDePasseEncode forKey:@"cleMotDePasse"];

    // Synchronisation pour garantir la persistance immédiate
    [parametresUtilisateur synchronize];
}

Gestion de l'action de connexion


- (IBAction)actionBoutonConnexion:(UIButton *)sender {
    if (self.champNomUtilisateur.text.length > 0 && self.champMotDePasse.text.length > 0) {
        // Préparation de la requête
        NSString *urlServiceConnexion = @"http://localhost/api/authentification";
        NSURL *url = [NSURL URLWithString:urlServiceConnexion];
        NSMutableURLRequest *requete = [NSMutableURLRequest requestWithURL:url];
        requete.HTTPMethod = @"POST";

        // Création du corps de la requête (attention: le mot de passe n'est PAS encodé Base64 ici pour la transmission au serveur,
        // car le serveur s'attend souvent au mot de passe clair ou haché selon une autre méthode, mais pas Base64 directement de l'UI.
        // Si le serveur s'attendait à Base64, il faudrait l'encoder ici.)
        // Pour cet exemple, nous simulons un envoi du mot de passe tel quel ou déjà haché côté client.
        NSString *corpsRequete = [NSString stringWithFormat:@"username=%@&password=%@", self.champNomUtilisateur.text, self.champMotDePasse.text];
        requete.HTTPBody = [corpsRequete dataUsingEncoding:NSUTF8StringEncoding];

        // Envoi de la requête asynchrone
        [[[NSURLSession sharedSession] dataTaskWithRequest:requete completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            if (data && !error) {
                NSLog(@"Requête réseau réussie !");
                NSError *jsonError;
                NSDictionary *reponseJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];

                if (reponseJSON && !jsonError && reponseJSON[@"userId"]) {
                    [self enregistrerInformationsUtilisateurLocal]; // Enregistrer le mot de passe encodé localement
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationConnexionReussie" object:nil];
                    });
                } else {
                    NSLog(@"Échec de l'authentification ou erreur JSON: %@", jsonError);
                }
            } else {
                NSLog(@"Échec de la requête réseau: %@", error.localizedDescription);
            }
        }] resume];
    } else {
        NSLog(@"Veuillez saisir un nom d'utilisateur et un mot de passe.");
    }
}

C. Gestion des Transitions d'Écran

Les transitions entre les écrans de connexion et l'interface principale peuvent être gérées via le centre de notification (NSNotificationCenter) dans l'AppDelegate.

Configuration initiale et gestion des notifications


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Enregistrement des observateurs de notifications
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(gererConnexionReussie) name:@"NotificationConnexionReussie" object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(gererDeconnexionReussie) name:@"NotificationDeconnexionReussie" object:nil];

    // Vérification de l'état de connexion persistant
    NSUserDefaults *parametresUtilisateur = [NSUserDefaults standardUserDefaults];
    NSString *nomUtilisateurSauvegarde = [parametresUtilisateur objectForKey:@"cleNomUtilisateur"];
    NSString *motDePasseSauvegarde = [parametresUtilisateur objectForKey:@"cleMotDePasse"]; // C'est le mot de passe encodé

    if (nomUtilisateurSauvegarde && motDePasseSauvegarde) {
        [self gererConnexionReussie]; // Afficher l'interface principale
    } else {
        [self gererDeconnexionReussie]; // Afficher l'interface de connexion
    }

    return YES;
}

Action en cas de connexion réussie


- (void)gererConnexionReussie {
    NSLog(@"Utilisateur connecté !");
    UIStoryboard *storyboardPrincipal = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    self.window.rootViewController = [storyboardPrincipal instantiateInitialViewController];
}

Action en cas de déconnexion réussie


- (void)gererDeconnexionReussie {
    NSLog(@"Utilisateur déconnecté !");
    UIStoryboard *storyboardConnexion = [UIStoryboard storyboardWithName:@"Login" bundle:nil];
    self.window.rootViewController = [storyboardConnexion instantiateInitialViewController];
}

Gestion de la déconnexion depuis l'interface principale


- (IBAction)actionBoutonDeconnexion:(id)sender {
    // 1. Nettoyage des informations locales
    NSUserDefaults *parametresUtilisateur = [NSUserDefaults standardUserDefaults];
    [parametresUtilisateur removeObjectForKey:@"cleNomUtilisateur"];
    [parametresUtilisateur removeObjectForKey:@"cleMotDePasse"];
    [parametresUtilisateur synchronize];

    // 2. Notification pour changer d'écran
    [[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationDeconnexionReussie" object:nil];
}

III. Authentification par Jeton (Token)

Le jeton, ou "token", est une valeur unique générée par le serveur pour confirmer l'identité d'un utilisateur après une authentification réussie. Il agit comme un passeport temporaire, évitant à l'utilisateur de devoir saisir ses identifiants à chaque interaction.

Fonctionnement Général :

  • Génération : Après une connexion réussie, le serveur génère un jeton unique basé sur les informations de l'utilisateur et le stocke (généralement dans une base de données ou un cache distribué).
  • Distribution : Ce jeton est ensuite renvoyé au client (application mobile).
  • Stockage Client : L'application cliente stocke ce jeton de manière sécurisée (par exemple, dans le Trousseau d'accès ou les préférences utilisateur si le risque est gérable).
  • Utilisation : Pour chaque requête subséquente nécessitant une authentification, le client inclut ce jeton dans l'en-tête de la requête ou comme paramètre.
  • Validation Serveur : Le serveur reçoit le jeton, le compare à celui qu'il a stocké et, si valide, autorise l'accès à la ressource demandée.

Gestion de l'État de Connexion :

La présence d'un jeton valide côté client indique généralement que l'utilisateur est connecté, éliminant ainsi le besoin d'une nouvelle saisie des identifiants. Si aucun jeton n'est présent ou s'il est expiré, l'utilisateur est invité à se reconnecter.

Considérations sur les Jetons :

  • Durée de Vie : Les jetons ont une durée de validité limitée. Pour les applications courantes, cela peut être plusieurs jours, mois ou même un an. Pour les applications bancaires ou de paiement, la durée est beaucoup plus courte (quelques minutes) pour des raisons de sécurité accrues.
  • Invalidation : Un changement de mot de passe ou une déconnexion explicite de l'utilisateur devrait entraîner l'invalidation du jeton existant et la génération d'un nouveau jeton lors de la prochaine connexion.
  • Unicité : Les jetons doivent être suffisamment complexes et uniques pour prévenir les attaques par devinette ou réutilisation. Souvent, un nouveau jeton est généré à chaque connexion, invalidant les précédents.

IV. Hachage MD5 (Message-Digest Algorithm 5)

MD5 est une fonction de hachage cryptographique qui prend une entrée (message de n'importe quelle longueur) et produit une sortie de taille fixe (un "condensat" ou "empreinte numérique" de 128 bits, généralement représenté par une chaîne hexadécimale de 32 caractères). Il est crucial de noter que le processus de hachage est irréversible : il est impossible de reconstituer l'entrée originale à partir de la valeur MD5.

Caractéristiques :

  • Compacité : Indépendamment de la taille de l'entrée, la sortie MD5 a toujours une longueur fixe.
  • Facilité de Calcul : Le calcul de la valeur MD5 à partir des données d'origine est rapide et facile.
  • Résistance aux Modifications : La moindre modification des données d'entrée (même un seul octet) entraînera une valeur MD5 radicalement différente.
  • Faible Résistance aux Collisions : Bien qu'il soit difficile de trouver une entrée différente qui produise la même valeur MD5 qu'une entrée donnée (préimage de seconde espèce), des vulnérabilités ont été découvertes permettant de trouver deux entrées différentes produisant le même MD5 (collisions). Pour cette raison, MD5 n'est plus recommandé pour la sécurité cryptographique (ex: signatures numériques) mais reste utile pour des vérifications d'intégrité non sécuritaires.

Applications :

  • Vérification d'Intégrité : Souvent utilisé pour vérifier que les fichiers téléchargés n'ont pas été corrompus ou modifiés. Une "empreinte numérique" unique est générée pour chaque fichier.
  • Signatures Numériques : Historiquement utilisé pour signer des documents, bien que des algorithmes plus robustes soient maintenant préférés.
  • Authentification Sécurisée : Pour stocker des mots de passe, on stocke leur hachage MD5 plutôt que le mot de passe clair. Lors de la connexion, le mot de passe saisi est haché et comparé au hachage stocké.

Utilisation de MD5 en Objective-C (avec une catégorie NSString+Hash)

Hachage d'une chaîne simple


// Supposons une catégorie NSString+Hash qui fournit la méthode md5String
NSString *motDePasseInitial = @"MonMotDePasseSecret";
NSString *motDePasseHache = [motDePasseInitial md5String];
NSLog(@"MD5 simple : %@", motDePasseHache);

Utilisation du "Salage" (Salting)

Le salage consiste à ajouter une chaîne aléatoire (le "sel") au mot de passe avant de le hacher. Cela rend les attaques par tables arc-en-ciel beaucoup plus difficiles et garantit que deux utilisateurs ayant le même mot de passe clair auront des hachages différents.


NSString *motDePasseUtilisateur = @"password123";
// Un sel complexe et unique à chaque mot de passe est idéal
NSString *valeurDeSel = @"&#$@ABCDEF123xyz_SALT_APP";

// Concaténation du mot de passe et du sel avant hachage
NSString *motDePasseAvecSel = [motDePasseUtilisateur stringByAppendingString:valeurDeSel];
NSString *motDePasseHacheAvecSel = [motDePasseAvecSel md5String];
NSLog(@"MD5 avec sel : %@", motDePasseHacheAvecSel);

Chaque application devrait utiliser une "valeur de sel" robuste et si possible unique par utilisateur pour renforcer la sécurité.

V. Mots de Passe Dynamiques (Basés sur un Horodatage)

Les mots de passe dynamiques ou à usage unique renforcent la sécurité en intégrant un élément temporel dans le processus de hachage. Même avec un mot de passe clair et un algorithme de hachage constants, le résultat final change à chaque connexion grâce à l'horodatage.

Principe :

  • Le client calcule un hachage du mot de passe, puis concatène cet hachage avec un horodatage précis (généralement à la minute ou seconde près).
  • Le résultat combiné est ensuite haché à nouveau.
  • Le serveur effectue le même calcul, en tenant compte de sa propre horloge et d'une petite marge de tolérance (par exemple, la minute actuelle et la minute précédente) pour compenser les décalages d'horloge.

Mise en œuvre avec HMAC-MD5

HMAC (Keyed-Hash Message Authentication Code) est une construction spécifique qui combine une clé secrète avec une fonction de hachage (ici MD5) pour un hachage plus sûr, souvent utilisé pour l'authentification de messages.

Paramètres Initiaux


// Le mot de passe de l'utilisateur
NSString *motDePasseClair = @"utilisateurTest";

// Une clé HMAC secrète, souvent fournie par le serveur ou dérivée de manière unique
// (supposons qu'elle est statique pour cet exemple, mais elle devrait être dynamique et sécurisée)
NSString *cleHMACSecrete = @"c1eF0rM3tD3P4ss3S3cur3"; // Exemple de clé

Processus de Hachage Dynamique


// 1. Premier hachage HMAC-MD5 du mot de passe clair avec la clé secrète
NSString *premiereHachage = [motDePasseClair hmacMD5StringWithKey:cleHMACSecrete];

// 2. Obtention de l'horodatage actuel (important qu'il soit synchronisé avec le serveur)
NSDate *dateActuelle = [NSDate date];
NSDateFormatter *formateurDate = [[NSDateFormatter alloc] init];
formateurDate.dateFormat = @"yyyy-MM-dd HH:mm"; // Format à la minute pour la tolérance

NSString *chaineHorodatage = [formateurDate stringFromDate:dateActuelle];

// 3. Concaténation du premier hachage et de l'horodatage
NSString *donneesPourDeuxiemeHachage = [premiereHachage stringByAppendingString:chaineHorodatage];

// 4. Deuxième hachage HMAC-MD5 du résultat combiné
NSString *motDePasseFinalHache = [donneesPourDeuxiemeHachage hmacMD5StringWithKey:cleHMACSecrete];

NSLog(@"Mot de passe dynamique généré : %@", motDePasseFinalHache);

Envoi de la Requête au Serveur


// Création de l'URL pour le service de connexion HMAC
NSURL *urlServiceHMAC = [NSURL URLWithString:@"http://localhost/api/login_hmac"];

// Configuration de la requête POST
NSMutableURLRequest *requeteHMAC = [NSMutableURLRequest requestWithURL:urlServiceHMAC];
requeteHMAC.HTTPMethod = @"POST";

// Préparation du corps de la requête avec le mot de passe dynamique
NSString *corpsRequiseHMAC = [NSString stringWithFormat:@"username=mon_utilisateur&dynamicPassword=%@", motDePasseFinalHache];
requeteHMAC.HTTPBody = [corpsRequiseHMAC dataUsingEncoding:NSUTF8StringEncoding];

// Envoi de la requête
[[[NSURLSession sharedSession] dataTaskWithRequest:requeteHMAC completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    if (data && !error) {
        NSLog(@"Réponse du serveur HMAC : %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    } else {
        NSLog(@"Erreur lors de la requête HMAC : %@", error.localizedDescription);
    }
}] resume];

VI. Accès au Trousseau (Keychain)

Le Trousseau d'accès est un service sécurisé fourni par iOS pour stocker des informations sensibles (mots de passe, certificats, clés cryptographiques, etc.). Il utilise des algorithmes de chiffrement robustes, comme AES 256, pour garantir la confidentialité des données.

Caractéristiques :

  • Chiffrement Robuste : Les données sont chiffrées au niveau du système d'exploitation, rendant leur accès difficile même si l'appareil est compromis.
  • API C-basée : L'API native du Trousseau est en C, mais des bibliothèques tierces comme SSKeychain simplifient grandement son utilisation en Objective-C/Swift.
  • Persistance : Les éléments du Trousseau persistent même après la désinstallation de l'application, ce qui peut être utile pour maintenir un état d'authentification ou des identifiants utilisateur.

Utilisation Simplifiée avec SSKeychain

SSKeychain est une bibliothèque populaire qui encapsule l'API complexe du Trousseau d'accès, offrant une interface simple et orientée objet.

Stockage d'un mot de passe


#import <SSKeychain.h> // Assurez-vous d'avoir importé la bibliothèque

// L'identifiant du service est souvent le bundle ID de l'application
NSString *identifiantService = [[NSBundle mainBundle] bundleIdentifier];

// Le nom du compte associé à ce mot de passe
NSString *nomCompte = @"utilisateur_api";

// Le mot de passe à stocker
NSString *motDePasseASauvegarder = self.champMotDePasseTrousseau.text;

NSError *erreurStockage = nil;
if ([SSKeychain setPassword:motDePasseASauvegarder forService:identifiantService account:nomCompte error:&erreurStockage]) {
    NSLog(@"Mot de passe stocké avec succès dans le Trousseau.");
} else {
    NSLog(@"Échec du stockage du mot de passe : %@", erreurStockage.localizedDescription);
}

Chargement d'un mot de passe


#import <SSKeychain.h>

// L'identifiant du service et le nom du compte doivent correspondre à ceux utilisés lors du stockage
NSString *identifiantService = [[NSBundle mainBundle] bundleIdentifier];
NSString *nomCompte = @"utilisateur_api";

NSError *erreurLecture = nil;
NSString *motDePasseCharge = [SSKeychain passwordForService:identifiantService account:nomCompte error:&erreurLecture];

if (motDePasseCharge) {
    self.champMotDePasseTrousseau.text = motDePasseCharge;
    NSLog(@"Mot de passe chargé depuis le Trousseau.");
} else {
    NSLog(@"Aucun mot de passe trouvé ou erreur de lecture : %@", erreurLecture.localizedDescription);
}

VII. Authentification Biomètrique (Touch ID / Face ID)

Les fonctionnalités d'authentification biométrique, comme Touch ID (introduit avec l'iPhone 5S, SDK iOS 8.0) et Face ID, offrent une méthode rapide et sécurisée pour vérifier l'identité de l'utilisateur sans qu'il ait à saisir un mot de passe. Elles sont couramment utilisées pour simplifier les processus de déverrouillage d'applications ou de validation de paiements.

Procédure d'Utilisation :

L'intégration de l'authentification biométrique se fait via le framework LocalAuthentication.

1. Importation du Framework


#import <LocalAuthentication/LocalAuthentication.h>

2. Vérification de la Version du Système


// Vérifiez que le système d'exploitation supporte LocalAuthentication
if ([UIDevice currentDevice].systemVersion.floatValue < 8.0) {
    NSLog(@"Version du système iOS trop ancienne pour l'authentification biométrique. Nécessite iOS 8.0 ou supérieur.");
    return;
}

3. Vérification de la Compatibilité de l'Appareil


LAContext *contexteAuth = [[LAContext alloc] init];
NSError *erreurBio = nil;

// Vérifier si l'appareil supporte l'authentification biométrique (Touch ID ou Face ID)
// LAPolicyDeviceOwnerAuthenticationWithBiometrics : Authentification avec Touch ID ou Face ID
if (![contexteAuth canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&erreurBio]) {
    NSLog(@"L'appareil ne supporte pas l'authentification biométrique : %@", erreurBio.localizedDescription);
    // Gérer les cas où la biométrie est désactivée ou non configurée
    switch (erreurBio.code) {
        case LAErrorBiometryNotAvailable:
            NSLog(@"Authentification biométrique non disponible sur cet appareil.");
            break;
        case LAErrorBiometryNotEnrolled:
            NSLog(@"Aucune donnée biométrique n'est configurée (doigts ou visage).");
            break;
        case LAErrorBiometryLockout:
            NSLog(@"Authentification biométrique verrouillée, trop de tentatives échouées.");
            break;
        default:
            NSLog(@"Erreur inconnue de biométrie : %@", erreurBio.localizedDescription);
            break;
    }
    return;
}

4. Demande d'Authentification Biométrique


// Message affiché à l'utilisateur dans l'invite d'authentification
NSString *raisonAuthentification = @"Veuillez vous authentifier pour accéder à l'application.";

[contexteAuth evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:raisonAuthentification reply:^(BOOL succes, NSError *erreur) {
    dispatch_async(dispatch_get_main_queue(), ^{ // Traiter le résultat sur le thread principal
        if (succes) {
            NSLog(@"Authentification biométrique réussie !");
            // Procéder à l'accès à la fonctionnalité sécurisée
        } else {
            NSLog(@"Authentification biométrique échouée ou annulée : %@", erreur.localizedDescription);
            // Gérer les erreurs spécifiques, par exemple :
            switch (erreur.code) {
                case LAErrorUserCancel:
                    NSLog(@"L'utilisateur a annulé l'authentification.");
                    break;
                case LAErrorUserFallback:
                    NSLog(@"L'utilisateur a choisi une méthode de secours (par exemple, le code).");
                    // Ici, vous pouvez implémenter une logique de fallback, comme demander un code PIN
                    break;
                case LAErrorAuthenticationFailed:
                    NSLog(@"Authentification échouée (empreinte non reconnue, etc.).");
                    break;
                default:
                    NSLog(@"Autre erreur d'authentification : %@", erreur.localizedDescription);
                    break;
            }
        }
    });
}];

Étiquettes: iOS Security Objective-C Base64 MD5 HMAC

Publié le 7 août à 01h43