Tech
Implementation Flow
This should provide an overview of the spec we are formalizing and high-level look into the implementation of the web app. Refer to the open-sourced code itself for a low-level look.
The flowchart should be sufficient as is to re-implement how SrsPass works, as everything is quite standard, except for the password charset compressor function which will be additionally documented or can be inspected in the source-code for more details.
Legend
flowchart TD
subgraph Legend
l4([Function])
l3[Variable]
l2{{Constant}}
l1((Entropy))
l2 -- one-way op --> l4
l3 <-. reversible op .-> l4
end
Flowchart
flowchart TD
subgraph User Input
u[Unlock Passphrase]
end
subgraph Entropy Pool
r((CSPRNG))
end
subgraph Backup Phrase Generation
r --> e[128-bit entropy, account-unique]
e --> b39etm([BIP39 entropyToMnemonic]) --> b[12-word backup phrase]
end
subgraph Encryption Key
r --> ueks[256-bit salt, device-unique]
ueks -- salt --> haek([Argon2id KDF])
u -- pw -----> haek -- Heavy 256-bit --> uek[256-bit key]
end
subgraph Constants
csm{{Backup Seeding Salt}}
csg{{Unlock Pass Generator Salt}}
end
subgraph Backup Seed Derivation
hadm([Argon2id KDF])
hadm -- Heavy 256-bit --> bps[Backup Seed]
end
b -- pw --> hadm
csm -- salt -----> hadm
subgraph Seed Authenticated Encryption/Decryption
aes([AES256-GCM])
iv[96-bit entropy]
r -- 96-bit --> iv
bps <-. payload .-> aes
uek -- key ---> aes
iv -- iv --> aes
aes <-. auth encrypt/decrypt .-> es[encrypted seed]
es <-.-> eob([Encrypted Object Builder])
iv <-.-> eob
ueks <-.-> eob
aes <-. encrypt artifact .-> at[authentication tag]
at <-.-> eob
eob <-.-> eo[Encrypted Object]
end
subgraph Seed Blob Encoder
eo <-.-> cbor([CBOR])
cbor <-. encode/decode .-> bs58c([Base58check]) <-. checksum encode/decode .-> eb[Encrypted Blob]
end
subgraph Browser Local Storage
eb <-. save/load .-> lssb[(seedBlob)]
end
subgraph Password Generator Key - secure with user entropy
hagp([Argon2id KDF])
u -- pw -------------------> hagp
csg -- salt ------------------> hagp
hagp -- Heavy 256-bit --> gk[Generator Key]
end
subgraph User Input Pass Parameters
log[login]
uri[uri]
len[pass length * 8]
idx[pass index]
alp[alphabet]
fmt[pass format]
alp & fmt --> vc
vc[variable charset]
end
subgraph Final Password Generation
gk -- P --> hapg([Argon2id KDF])
len -- T --> hapg
hapg -->|Light Variable-bit| srskey[Pass Length x 64 bit Key]
srskey -- array ---> pce([64-bit array to variable charset compressor])
vc -- charset --> pce
pce --> fp[Final SrsPass Output]
end
subgraph SrsPass Account ad-hoc Salt
concf([seed + $idx? + $uri + $login])
concs[Concatenated Salt]
concs -- salt --> hapg
bps -----------> concf
idx & uri & log ---> concf --> concs
end
Footnotes
CSPRNG → Cryptographically Secure Pseudo-Random Number Generator
Heavy Argon2id parameters →
# used for the keys and seed
time cost = 12 iterations
memory cost = 32768 KiB
parallelism = 1 thread
Light Argon2id parameters →
# used for password generation
time cost = 19 iterations
memory cost = 512 KiB
parallelism = 1 thread
$ prefix → stringified
? suffix → only included if not nil or 0