Comment Kode stocke vos codes
Où Kode conserve vos clés 2FA, comment elles se synchronisent et comment les récupérer.
Uniquement dans votre trousseau
Chaque compte – y compris la clé secrète qui sert à générer les codes – est enregistré comme un élément du trousseau de l’iPhone, disponible après le premier déverrouillage. La clé n’est jamais enregistrée dans la base de données de l’app, dans les réglages, dans des fichiers journaux, dans des analyses ni dans des rapports de plantage.
Trousseau iCloud
Avec la synchronisation activée (par défaut), l’élément est marqué comme synchronisable, si bien que le trousseau iCloud l’emporte sur vos autres appareils Apple et sur un nouvel iPhone. Le trousseau iCloud est chiffré de bout en bout. Si vous désactivez la synchronisation, les clés restent uniquement sur cet iPhone (« cet appareil uniquement ») et ne passent pas sur un autre téléphone.
Aucun serveur
Kode n’effectue aucune connexion réseau. Les codes sont calculés selon la norme TOTP (RFC 6238) avec HMAC-SHA1/256/512 – les mêmes codes que Google Authenticator.
Verrouillage
Face ID ou code à l’ouverture de l’app, puis à nouveau après une minute en arrière-plan. Tant que l’app n’est pas active, un écran de verrouillage couvre tout, si bien que le sélecteur d’apps n’affiche jamais de code. Un code copié est retiré du presse-papiers de l’iPhone au bout de 60 secondes. Vous pouvez le coller sur votre Mac grâce au presse-papiers universel ; il y reste jusqu’à ce que vous copiiez autre chose.
Le format du fichier de sauvegarde
La sauvegarde chiffrée est un fichier JSON. La clé est dérivée de votre mot de passe avec PBKDF2-HMAC-SHA256 (600 000 itérations, sel de 16 octets), et le contenu est chiffré en AES-256-GCM. ciphertext est le texte chiffré suivi de l’étiquette GCM de 16 octets. Tous les champs binaires sont en Base64.
{
"format": "kode-backup",
"version": 1,
"kdf": { "name": "PBKDF2-HMAC-SHA256", "iterations": 600000, "salt": "…" },
"cipher": { "name": "AES-256-GCM", "nonce": "…" },
"ciphertext": "…"
}
Une fois déchiffré, le contenu est une liste de comptes. Chaque compte a aussi une adresse otpauth:// toute prête, que la plupart des apps savent importer.
{
"created": "2026-09-24T09:41:00Z",
"accounts": [
{
"issuer": "GitHub", "name": "anna", "secret": "JBSWY3DPEHPK3PXP",
"algorithm": "SHA1", "digits": 6, "period": 30,
"uri": "otpauth://totp/GitHub:anna?secret=JBSWY3DPEHPK3PXP&issuer=GitHub&algorithm=SHA1&digits=6&period=30"
}
]
}
Pour déchiffrer le fichier sans Kode (Python avec le paquet cryptography) :
import base64, getpass, hashlib, json, sys
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
backup = json.load(open(sys.argv[1]))
b64 = base64.b64decode
key = hashlib.pbkdf2_hmac("sha256", getpass.getpass().encode(),
b64(backup["kdf"]["salt"]), backup["kdf"]["iterations"], 32)
plain = AESGCM(key).decrypt(b64(backup["cipher"]["nonce"]), b64(backup["ciphertext"]), None)
for account in json.loads(plain)["accounts"]:
print(account["uri"])