0Pricing
Swift Academy · Lezione

Memorizzazione dei segreti nel portachiavi

Salvi e recuperi le credenziali in modo sicuro.

Memorizzazione dei segreti nel portachiavi è una lezione Swift Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Swift Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Swift Academy include 4 lezioni in totale.

Perché usare il Keychain

Le password, i token e le chiavi non devono mai essere conservati in UserDefaults o in file di testo semplice, perché sono facili da leggere. Il Keychain è un database cifrato gestito dal sistema per i piccoli segreti, protetto dall'hardware e dal codice dell'utente. È l'unico luogo corretto per conservare le credenziali.

import Security
// Keychain stores secrets encrypted at rest,
// survives app updates, and gates access by policy.

Gli elementi sono dizionari

L'API Keychain Services è basata su C: si descrive un elemento con un dizionario di query [String: Any] che usa chiavi costanti kSec.... La stessa struttura del dizionario viene riutilizzata per aggiungere, cercare, aggiornare ed eliminare elementi.

import Security
let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrAccount as String: "user@example.com",
    kSecAttrService as String: "com.example.app"
]
_ = query

Classi di elementi

La chiave kSecClass seleziona il tipo di elemento. kSecClassGenericPassword gestisce i token e i segreti dell'app; kSecClassInternetPassword conserva le credenziali del server con gli attributi host e protocollo. Per la maggior parte dei segreti dell'app si utilizza una password generica.

import Security
// kSecClassGenericPassword   -> tokens, API keys
// kSecClassInternetPassword  -> server logins
// kSecClassKey / Certificate -> crypto material
let cls = kSecClassGenericPassword
_ = cls

Aggiunta di un elemento

SecItemAdd inserisce un nuovo elemento. Includa i dati sotto kSecValueData come Data, insieme agli attributi che lo identificano. Restituisce un OSStatus: errSecSuccess indica che l'operazione è riuscita.

import Security
func save(_ token: String, account: String) -> Bool {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: account,
        kSecValueData as String: Data(token.utf8)
    ]
    return SecItemAdd(query as CFDictionary, nil)
        == errSecSuccess
}

Gestione dei duplicati

L'aggiunta di un elemento i cui attributi identificativi esistono già restituisce errSecDuplicateItem. Un salvataggio robusto prova SecItemAdd e, in caso di duplicato, ripiega su SecItemUpdate: è uno schema di upsert.

import Security
func upsert(_ data: Data, account: String) -> Bool {
    let base: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: account]
    var add = base
    add[kSecValueData as String] = data
    let status = SecItemAdd(add as CFDictionary, nil)
    if status == errSecDuplicateItem {
        return SecItemUpdate(base as CFDictionary,
            [kSecValueData as String: data] as CFDictionary)
            == errSecSuccess
    }
    return status == errSecSuccess
}

Rileggere un elemento

SecItemCopyMatching esegue la ricerca. Per ottenere i byte del segreto, deve impostare kSecReturnData su true e kSecMatchLimit su kSecMatchLimitOne. Il risultato viene restituito tramite un parametro di output come CFTypeRef.

import Security
func load(account: String) -> Data? {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: account,
        kSecReturnData as String: true,
        kSecMatchLimit as String: kSecMatchLimitOne]
    var result: CFTypeRef?
    let status = SecItemCopyMatching(
        query as CFDictionary, &result)
    guard status == errSecSuccess else { return nil }
    return result as? Data
}

Aggiornare un elemento

SecItemUpdate accetta due dizionari: una query che individua l'elemento e un dizionario degli attributi da aggiornare. Cambiano solo gli attributi elencati; tutto il resto viene mantenuto.

import Security
func update(_ newData: Data, account: String) -> Bool {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: account]
    let attrs: [String: Any] = [
        kSecValueData as String: newData]
    return SecItemUpdate(query as CFDictionary,
        attrs as CFDictionary) == errSecSuccess
}

Eliminare un elemento

SecItemDelete rimuove gli elementi corrispondenti. Eliminare qualcosa che non esiste restituisce errSecItemNotFound, che può essere trattato come un successo quando si cancellano le credenziali durante il logout.

import Security
func delete(account: String) -> Bool {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: account]
    let status = SecItemDelete(query as CFDictionary)
    return status == errSecSuccess
        || status == errSecItemNotFound
}

Decodificare OSStatus

Gli errori sono codici interi OSStatus. SecCopyErrorMessageString trasforma un codice in una descrizione comprensibile, preziosa per eseguire il debug del motivo per cui un salvataggio o una lettura non sono riusciti.

import Security
func describe(_ status: OSStatus) -> String {
    return SecCopyErrorMessageString(status, nil)
        as String? ?? "OSStatus \(status)"
}

Identificare gli elementi in modo univoco

Gli elementi vengono individuati in base alla combinazione dei loro attributi: in genere kSecAttrService più kSecAttrAccount per le password generiche. Scelga una stringa di servizio stabile e specifica per l'app, così segreti diversi non entreranno mai in conflitto.

import Security
// Uniqueness for generic passwords usually comes from:
//   service (your bundle id) + account (the username)
let service = "com.example.app.auth"
let account = "current-user"
_ = (service, account)

Un piccolo wrapper

Poiché l'API a basso livello è prolissa, i team la racchiudono in un piccolo tipo che espone save, read e delete. In questo modo la procedura kSec resta concentrata in un unico punto e i punti di chiamata rimangono puliti.

import Security
struct TokenStore {
    let service = "com.example.app.auth"
    func read(_ account: String) -> Data? {
        let q: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrService as String: service,
            kSecAttrAccount as String: account,
            kSecReturnData as String: true,
            kSecMatchLimit as String: kSecMatchLimitOne]
        var out: CFTypeRef?
        return SecItemCopyMatching(q as CFDictionary, &out)
            == errSecSuccess ? out as? Data : nil
    }
}

Verifica rapida

Ricordi il modo corretto per recuperare i byte di un segreto memorizzato.

Riepilogo

Ha imparato le operazioni CRUD del Keychain:

  • Memorizzi le credenziali nel Keychain crittografato, mai in UserDefaults o nei file.
  • Descriva gli elementi con dizionari di query kSec; scelga una classe come kSecClassGenericPassword.
  • SecItemAdd / SecItemCopyMatching / SecItemUpdate / SecItemDelete coprono l'intero ciclo di vita; gestisca errSecDuplicateItem con un'operazione di upsert.
  • Identifichi gli elementi tramite servizio e account e decodifichi OSStatus per eseguire il debug.

Domande Frequenti

La lezione «Memorizzazione dei segreti nel portachiavi» è gratuita?

Sì — il testo completo di «Memorizzazione dei segreti nel portachiavi» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Swift Academy, passa a CoddyKit PRO. Il corso Swift Academy include 4 lezioni in totale.

Cosa imparerò in «Memorizzazione dei segreti nel portachiavi»?

Salvi e recuperi le credenziali in modo sicuro. Eserciti Swift Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Swift Academy?

Non è richiesta alcuna esperienza precedente. Swift Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.

Quanto tempo richiede la lezione «Memorizzazione dei segreti nel portachiavi»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Swift Academy?

Sì. Ogni lezione Swift Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Memorizzazione dei segreti nel portachiavi
  2. Controllo degli accessi al portachiavi
  3. Autenticazione biometrica
  4. Protezione dei dati e crittografia
← Torna a Swift Academy