diff --git a/android-client/web/app.html b/android-client/web/app.html index 4a8c53f..e4c632b 100644 --- a/android-client/web/app.html +++ b/android-client/web/app.html @@ -395,7 +395,11 @@
×
- +
×
@@ -535,12 +539,15 @@
×
-
×
-
The master password never leaves this device. It is what - decrypts the vault; the token only opens the repository.
+
The sync password never leaves this device. It is what + encrypts the copy kept in the repository, so it must be the same on every + device that shares it; the token only opens the repository. It is not the + password that opens a vault created on this phone - that one is asked for + on the home screen.

Unlock code

diff --git a/mainApk.pas b/mainApk.pas index 8a3f43f..3c17307 100644 --- a/mainApk.pas +++ b/mainApk.pas @@ -134,6 +134,17 @@ type // rafraichissement de fond silencieux : sans lui, chaque modification // faite sur le poste ferait apparaitre une invite au lancement. FSyncPwd: string; + /// LE MOT DE PASSE DU COFFRE LOCAL, et lui seul. + /// + /// Il ouvre `vault-local.json` - un coffre ne sur ce telephone et pas + /// encore publie. Il n'a RIEN a voir avec le secret du depot, meme si + /// l'utilisateur choisit la meme valeur pour les deux : ce sont deux roles, + /// et les confondre faisait qu'un coffre cree ici pretendait sceller le + /// depot avec son propre mot de passe. + /// + /// Vide des que le conteneur local disparait - c'est-a-dire des que la + /// reconciliation a passe l'autorite au depot. + FVaultPwd: string; /// Coordonnees du serveur. Delphi en est le detenteur ; la page ne fait /// que les editer et les lui renvoyer quand un champ est quitte. @@ -895,9 +906,20 @@ begin RefuseChange('Busy - wait for the current operation'); Exit; end; - if FSyncPwd = '' then + // DEUX SECRETS, DEUX EXIGENCES. Un coffre ne ici n'ecrit que son conteneur + // local et n'a donc pas besoin du secret du depot ; un coffre publie n'a pas + // de conteneur local et n'a donc pas besoin du sien. + if HasLocalContainer then begin - RefuseChange('Master password missing - open the vault first'); + if FVaultPwd = '' then + begin + RefuseChange('Vault password missing - open the vault first'); + Exit; + end; + end + else if FSyncPwd = '' then + begin + RefuseChange('Sync password missing - open the vault first'); Exit; end; SetBusy(True); @@ -929,7 +951,7 @@ begin // donc le cache avant toute chose, et le depot suit quand il peut. // --------------------------------------------------------------- LSw := TStopwatch.StartNew; - if LLocalOnly then LPlain := OpenContainer(LoadLocalContainer, FSyncPwd) + if LLocalOnly then LPlain := OpenContainer(LoadLocalContainer, FVaultPwd) else LPlain := FPlain; if LPlain = '' then raise Exception.Create('no snapshot in hand - open the vault again'); @@ -1225,11 +1247,23 @@ begin Status('No local vault to reconcile'); Exit; end; - if FSyncPwd = '' then + // LES DEUX SONT REQUIS ICI, ET NULLE PART AILLEURS : c'est le seul moment ou + // le conteneur local et l'instantane du depot se rencontrent. + if FVaultPwd = '' then begin Status('Open the vault first'); Exit; end; + // CE QUI EST DANS LES REGLAGES FAIT FOI quand le coffre n'en porte pas encore. + // Un coffre ne ici n'a jamais vu le depot : son cache ne contient donc aucun + // secret de sync, et c'est le champ des reglages qui le donne. Meme + // precedence que DoSync, pour que les deux ne divergent pas. + if FSyncPwd = '' then FSyncPwd := FPwd; + if FSyncPwd = '' then + begin + Status('Set the sync password in Settings'); + Exit; + end; SetBusy(True); Status('Reconciling...'); @@ -1248,7 +1282,17 @@ begin LErr := ''; try try - LLocal := OpenContainer(LoadLocalContainer, FSyncPwd); + // 1. LE COFFRE LOCAL, sous SON mot de passe. + LLocal := OpenContainer(LoadLocalContainer, FVaultPwd); + + // 2. ON JETTE LA CLE QUI VIENT DE SERVIR. Elle appartient au conteneur + // local ; tout ce qui suit concerne le depot, scelle par un autre + // secret. La garder ferait resceller le depot sous le mot de passe du + // coffre local - c'est exactement la confusion qu'on defait ici, et + // elle rendrait l'instantane illisible pour le poste. + FKey := nil; + FKeySalt := nil; + FKeyIters := 0; for LAttempt := 1 to 3 do begin @@ -1268,6 +1312,8 @@ begin end else if LGet.Status = ssOK then begin + // Ouvrir le distant pose la cle DU DEPOT dans FKey : c'est elle + // qui servira a le resceller quelques lignes plus bas. LRemote := OpenContainer(LGet.Container, FSyncPwd); LMerged := MergeSnapshots(LLocal, LRemote); end @@ -1277,7 +1323,11 @@ begin Break; end; - LBody := EncryptContainerWithKey(LMerged, FKey, FKeySalt, FKeyIters); + // Depot vide : aucune cle n'a ete tiree de lui, il faut donc la + // deriver du mot de passe de sync. C'est le seul chemin qui paie les + // quelques secondes, et il n'arrive qu'une fois. + if FKey = nil then LBody := EncryptContainer(LMerged, FSyncPwd) + else LBody := EncryptContainerWithKey(LMerged, FKey, FKeySalt, FKeyIters); LPut := LClient.Put(LBody, LGet.ETag, 'reconciled from phone'); if LPut.Status = ssOK then begin @@ -1298,7 +1348,11 @@ begin // PUBLIE, DONC PLUS BESOIN DU CONTENEUR LOCAL. C'est ce geste qui // passe l'autorite au depot ; le faire avant la publication aurait // perdu le coffre. + // Le conteneur local n'existe plus : son mot de passe non plus. + // L'autorite est passee au depot, et c'est le secret de sync qui + // commande desormais. DropLocalContainer; + FVaultPwd := ''; try SaveVault(LMerged, FETag, FSyncPwd, BiometricAvailable, False, FPinSealed, FKey, FKeySalt, FKeyIters); @@ -1747,6 +1801,9 @@ begin FKeyIters := 0; FPlain := ''; FHistory := nil; + // Le mot de passe du coffre local part avec le clair : le garder ouvrirait + // le conteneur sans rien demander. + FVaultPwd := ''; // Le code aussi : le retenir apres un verrouillage reviendrait a ne pas // verrouiller. Le garde de SaveVault protege le cache d'ici la. FPinSealed := ''; @@ -1827,19 +1884,12 @@ begin begin SetBusy(False); FUser := AUser; - FSyncPwd := APwd; - // LE COFFRE QUI VIENT DE S'OUVRIR DIT LE MOT DE PASSE DE SYNC. - // - // Sans cette ligne, FPwd gardait la valeur de premier lancement - - // en debogage, une constante ; en release, du vide - et les - // reglages affichaient donc un mot de passe qui n'etait pas celui - // du coffre detenu. Pire, DoSync la PREFERE a celle du coffre au - // nom de "ce qui est tape l'emporte" : or rien n'avait ete tape. - // Les deux chemins de synchronisation travaillaient ainsi avec - // deux mots de passe differents sur le meme coffre. - FPwd := APwd; - WebCall(Format('PM.setConfig(%s, %s, %s, false)', - [JsArg(FUrl), JsArg(FToken), JsArg(FPwd)])); + // CE MOT DE PASSE NE TOUCHE PAS AU DEPOT. Il scelle le conteneur + // local, rien d'autre. Le secret du depot vit dans les reglages et + // doit etre le meme sur tous les appareils - le remplacer par + // celui-ci ferait publier un instantane que le poste ne saurait + // plus ouvrir. + FVaultPwd := APwd; Log('Vault created locally for ' + AUser); AdoptVault(LPlain); end); @@ -1887,6 +1937,7 @@ begin LDoc: TJSONObject; begin try + FVaultPwd := APwd; // avant l'ouverture : c'est lui qui la fait LPlain := OpenContainer(LoadLocalContainer, APwd); LOwner := ''; LDoc := TJSONObject.ParseJSONValue(LPlain) as TJSONObject; @@ -1910,19 +1961,9 @@ begin begin SetBusy(False); if LOwner <> '' then FUser := LOwner else FUser := AUser; - FSyncPwd := APwd; - // LE COFFRE QUI VIENT DE S'OUVRIR DIT LE MOT DE PASSE DE SYNC. - // - // Sans cette ligne, FPwd gardait la valeur de premier lancement - - // en debogage, une constante ; en release, du vide - et les - // reglages affichaient donc un mot de passe qui n'etait pas celui - // du coffre detenu. Pire, DoSync la PREFERE a celle du coffre au - // nom de "ce qui est tape l'emporte" : or rien n'avait ete tape. - // Les deux chemins de synchronisation travaillaient ainsi avec - // deux mots de passe differents sur le meme coffre. - FPwd := APwd; - WebCall(Format('PM.setConfig(%s, %s, %s, false)', - [JsArg(FUrl), JsArg(FToken), JsArg(FPwd)])); + // Meme regle qu'a la creation : ce mot de passe ouvre le conteneur + // local et s'arrete la. + FVaultPwd := APwd; AdoptVault(LPlain); end); @@ -2815,7 +2856,9 @@ begin ClearUnlockCode; Exit; end; - if (FPlain = '') or (FSyncPwd = '') then + // Le secret du depot n'entre pas ici : le code scelle le CACHE, et un coffre + // ne sur ce telephone n'a pas encore de depot. + if FPlain = '' then begin WebCall('PM.toast("Open the vault first")'); Exit; @@ -2855,7 +2898,9 @@ begin WebCall('PM.toast("No unlock code to remove")'); Exit; end; - if (FPlain = '') or (FSyncPwd = '') then + // Le secret du depot n'entre pas ici : le code scelle le CACHE, et un coffre + // ne sur ce telephone n'a pas encore de depot. + if FPlain = '' then begin WebCall('PM.toast("Open the vault first")'); Exit;