mirror of
https://github.com/PR0M3TH3AN/bitlogin.git
synced 2026-11-10 15:31:27 +00:00
Fail closed on credential-generation rollback; fix NIP-44 extended-length payloads
Found during a real integration pass (embedding this widget in BitRoad, a separate Nostr commerce app): - Password rotation's old-locator tombstone (§18.1) is only advisory -- a relay that never processes it can keep serving the pre-rotation capsule indefinitely. loginWithPassword/changePassword previously accepted that stale capsule with only a non-blocking warning. A device that has already seen the newer generation now refuses it (RollbackDetectedError) unless the caller explicitly passes acknowledgeRollback: true for the narrower relay-lag case. The widget surfaces this as a blocking confirmation screen before claiming the signer, not a banner shown after the fact. - NIP-44 capped plaintext at 65535 bytes; added the extended-length prefix for payloads up to 2^32-1 bytes, verified byte-for-byte against the nostr-tools reference implementation (conversation keys, padding at every bucket boundary, round trips in both directions). - <bitlogin-auth> now exposes nip44Encrypt/nip44Decrypt directly on the element instance, alongside the existing getPublicKey/signEvent, so a host page can reach every capability without racing other providers for the single window.nostr slot. docs/spec.md bumped to v0.4 with the full writeup (§16.2, §29.7). 75/75 tests passing (14 new NIP-44 tests, 2 new rollback e2e tests). Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
1 parent
e17885d0e5
commit
1dc5e6802c
13 files changed
+430
-61
No files matched your search
@@ -132,7 +132,13 @@ async function handle(action: string, payload: unknown): Promise<unknown> {
|
||||
|
||||
case "login": {
|
||||
const p = payload as LoginPayload;
|
||||
const result = await loginWithPassword({ loginName: p.loginName, password: p.password, vaultRelayUrls, store });
|
||||
const result = await loginWithPassword({
|
||||
loginName: p.loginName,
|
||||
password: p.password,
|
||||
vaultRelayUrls,
|
||||
store,
|
||||
acknowledgeRollback: p.acknowledgeRollback
|
||||
});
|
||||
clearSession();
|
||||
session.signer = new NostrSigner(result.everydayPrivateKey);
|
||||
session.everydayPrivateKey = result.everydayPrivateKey;
|
||||
@@ -201,7 +207,8 @@ async function handle(action: string, payload: unknown): Promise<unknown> {
|
||||
oldPassword: p.oldPassword,
|
||||
newPassword: p.newPassword,
|
||||
vaultRelayUrls,
|
||||
store
|
||||
store,
|
||||
acknowledgeRollback: p.acknowledgeRollback
|
||||
});
|
||||
// Keep the session's capsule references current so a recovery export or replica
|
||||
// repair requested right after rotation (without an intervening re-login) still
|
||||
|
||||
@@ -44,6 +44,8 @@ export interface PreviewImportKeyResult {
|
||||
export interface LoginPayload {
|
||||
loginName: string;
|
||||
password: string;
|
||||
/** See `LoginParams.acknowledgeRollback` in `@bitlogin/core/account` (§16.2 step 6). */
|
||||
acknowledgeRollback?: boolean;
|
||||
}
|
||||
export interface LoginResult {
|
||||
everydayPublicKey: string;
|
||||
@@ -85,6 +87,8 @@ export interface ChangePasswordPayload {
|
||||
loginName: string;
|
||||
oldPassword: string;
|
||||
newPassword: string;
|
||||
/** See `ChangePasswordParams.acknowledgeRollback` in `@bitlogin/core/account` (§16.2 step 6). */
|
||||
acknowledgeRollback?: boolean;
|
||||
}
|
||||
export interface ChangePasswordResult {
|
||||
newLocatorPublicKey: string;
|
||||
|
||||
Reference in new issue
Block a user