Just opened a PR hardening how Primal's web app encrypts key...

npub1m2jphmdkskgnvwl5gplksl9e0zwv2sldqf9mwlpz6tyymz84g9fsqr3wgu
hex
9f6add637266158ba1b60ffb4acdce7e2f415a0598465f68532225a82f6c6befnevent
nevent1qqsf76kavdexv9vt5xmql762eh88ut6ptgzes3jldpfjyfdg9akxhmcprpmhxue69uhhyetvv9ujuem4d36kwatvw5hx6mm9qgsd4fqmakmgtyfk806yqlmg0juh38x9g0ksyjah0s3d9jzd3r65z5cpsnu7zKind-1 (TextNote)
Just opened a PR hardening how Primal's web app encrypts keys at rest which is a bit meatier than the one I submitted this morning.
Previously the PIN encrypted an nsec with a single unsalted SHA-256 hash of the PIN and unauthenticated AES-CBC. The PR upgrades this to PBKDF2 (600k iterations, random salt) and AES-256-GCM, which makes brute-forcing a stored blob drastically more expensive and makes wrong PINs fail cleanly. Existing users are migrated automatically on their next unlock, so nobody has to re-enter anything.
It also encrypts the NIP-46 client transport key, which was previously plaintext in localStorage, using a non-extractable WebCrypto key.
https://github.com/PrimalHQ/primal-web-app/pull/211
Raw JSON
{
"kind": 1,
"id": "9f6add637266158ba1b60ffb4acdce7e2f415a0598465f68532225a82f6c6bef",
"pubkey": "daa41bedb68591363bf4407f687cb9789cc543ed024bb77c22d2c84d88f54153",
"created_at": 1785709919,
"tags": [],
"content": "Just opened a PR hardening how Primal's web app encrypts keys at rest which is a bit meatier than the one I submitted this morning.\r\n\r\nPreviously the PIN encrypted an nsec with a single unsalted SHA-256 hash of the PIN and unauthenticated AES-CBC. The PR upgrades this to PBKDF2 (600k iterations, random salt) and AES-256-GCM, which makes brute-forcing a stored blob drastically more expensive and makes wrong PINs fail cleanly. Existing users are migrated automatically on their next unlock, so nobody has to re-enter anything.\r\n\r\nIt also encrypts the NIP-46 client transport key, which was previously plaintext in localStorage, using a non-extractable WebCrypto key.\r\n\r\nhttps://github.com/PrimalHQ/primal-web-app/pull/211",
"sig": "7e39ba7a689803ad69333ebe4e6c259e00e66c03d9b20ccaba5493584d41b2aef13fd62ada287988ebba9f5bf22888fb92afed85940159ba0486481707571cb6"
}