0Pricing
Swift Academy · Aula

Armazenamento de Segredos no Keychain

Salve e recupere credenciais com segurança.

Armazenamento de Segredos no Keychain é uma aula grátis de Swift Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Swift Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Swift Academy inclui 4 aulas no total.

Por que usar as Chaves

Senhas, tokens e chaves nunca devem ficar em UserDefaults ou em arquivos simples — eles são fáceis de ler. O serviço de Chaves é um banco de dados criptografado e gerenciado pelo sistema para pequenos segredos, protegido pelo hardware e pelo código de acesso do usuário. É o único local correto para credenciais.

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

Os itens são dicionários

A API de Serviços de Chaves é baseada em C: você descreve um item com um dicionário de consulta [String: Any], usando chaves constantes kSec.... A mesma estrutura de dicionário é reutilizada para adicionar, pesquisar, atualizar e apagar.

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

Classes de itens

A chave kSecClass escolhe o tipo de item. kSecClassGenericPassword abrange tokens e segredos do aplicativo; kSecClassInternetPassword armazena credenciais de servidores com atributos de host e protocolo. A maioria dos segredos de aplicativos usa uma senha genérica.

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

Adicionando um item

SecItemAdd insere um novo item. Você inclui os dados em kSecValueData como Data, além de atributos que o identificam. Ele retorna um OSStatus — errSecSuccess significa que a operação funcionou.

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
}

Lidando com duplicatas

Adicionar um item cujos atributos de identificação já existem retorna errSecDuplicateItem. Um salvamento robusto tenta usar SecItemAdd e, em caso de duplicata, recorre a SecItemUpdate — um padrão de inserção ou atualização.

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
}

Lendo um item novamente

SecItemCopyMatching faz a busca. Para obter os bytes secretos, defina kSecReturnData como true e kSecMatchLimit como kSecMatchLimitOne. O resultado é retornado por meio de um parâmetro de saída como 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
}

Atualizando um item

SecItemUpdate recebe dois dicionários: uma consulta que encontra o item e um dicionário com os atributos a serem atualizados. Somente os atributos que você listar serão alterados; todo o restante será preservado.

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
}

Excluindo um item

SecItemDelete remove os itens correspondentes. Excluir algo que não existe retorna errSecItemNotFound, que pode ser tratado como sucesso ao limpar credenciais durante o encerramento da sessão.

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
}

Decodificando OSStatus

Os erros são códigos inteiros de OSStatus. SecCopyErrorMessageString transforma um deles em uma descrição compreensível, o que é extremamente útil para depurar por que uma operação de gravação ou leitura falhou.

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

Identificando itens de forma exclusiva

Os itens são identificados pela combinação de seus atributos — normalmente kSecAttrService e kSecAttrAccount para senhas genéricas. Escolha uma string de serviço estável e específica do aplicativo para que segredos diferentes nunca entrem em conflito.

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)

Uma pequena camada de encapsulamento

Como a API bruta é detalhada, as equipes a encapsulam em um tipo pequeno que expõe save, read e delete. Assim, a configuração do kSec fica em um único lugar e os pontos de chamada permanecem limpos.

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ção rápida

Relembre a forma correta de recuperar os bytes de um segredo armazenado.

Recapitulação

Você aprendeu as operações de criar, ler, atualizar e excluir no chaveiro:

  • Armazene as credenciais no chaveiro criptografado, nunca em UserDefaults ou em arquivos.
  • Descreva os itens com dicionários de consulta kSec; escolha uma classe como kSecClassGenericPassword.
  • SecItemAdd / SecItemCopyMatching / SecItemUpdate / SecItemDelete abrangem todo o ciclo de vida; trate errSecDuplicateItem com uma operação de inserção ou atualização.
  • Identifique os itens por serviço e account, e decodifique OSStatus para depuração.

Perguntas Frequentes

A aula “Armazenamento de Segredos no Keychain” é grátis?

Sim — o texto completo de “Armazenamento de Segredos no Keychain” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Swift Academy, atualize para CoddyKit PRO. O curso de Swift Academy inclui 4 aulas no total.

O que vou aprender em “Armazenamento de Segredos no Keychain”?

Salve e recupere credenciais com segurança. Você pratica Swift Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Swift Academy?

Nenhuma experiência prévia é necessária. Swift Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.

Quanto tempo leva a aula “Armazenamento de Segredos no Keychain”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Swift Academy?

Sim. Cada aula de Swift Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Armazenamento de Segredos no Keychain
  2. Controle de Acesso ao Keychain
  3. Autenticação biométrica
  4. Proteção e criptografia de dados
← Voltar para Swift Academy