I have over 2,000 accounts. The majority of them have unique passwords. I can count the services that have passwords that I know on one hand, with quite a few spare fingers.
Passwords just don't provide a broad recoverability benefit once you commit to doing strong, unique passwords.
> Passkeys were created specifically to close that loophole.
Credential sharing? I have a family share with passwords and passkeys in it. Passkeys most certainly didn't stop this.
They did add friction to having a user being duped to share their password to someone claiming to be tech support, since you can no longer request plaintext secrets be sent over arbitrary channels.
> Plus, SMS didn't allow for vendor lock-in, which is arguably why they're so hated in security circles (SIM-jacking is real, but doesn't scale anywhere near enough to warrant deprecating it as mechanism for regular users).
SMS is an ugly user experience and more importantly is expensive. Now a lot of services do emailed codes when they don't have a regulatory reason to require SMS - an even worse user experience, but less expensive.
We have authenticator apps which use a standard OATH setup, and quite a few platforms which have integrated support to try to sand over the worst part of the UX. Unfortunately they just didn't become popular, and OATH fails the same regulatory requirements that emailed codes fail.
Passkeys are not meant to have a vendor lock-in story. Credential exchange allows for credentials stored in consumer credential managers to be imported into another credential managers. The platforms have added infrastructure specifically to make this easier for users.
The exceptions are when enterprises run their own passkey stores, or when the user explicitly picks a solution that doesn't allow export (like a physical Yubikey).
FWIW my break-the-glass actual use of backup codes is for access to my password manager.
Everything else which has ever given me a backup code... gets stored in a secure note in my password manager.
It is just another knowledge-based factor. It is one that they are reasonably sure you aren't spreading around the internet. It is one that the site gets to pick rather than the user. But in reality, they are a often just a way to try to reduce some support and identity verification costs.
The path to get to the password manager is the case where the backup codes truly matter, because without them there may not be a way for support to restore access. Those codes may be your only way of regaining the master encryption key.
But that also winds up being part of the trade-off of security vs user friendliness. Some password managers are way easier to get back into.
3. Communication (over websockets or a direct L2CAP channel)
The challenge is that a devices without bluetooth (at least today) don't have another common way to wirelessly judge proximity. A desktop/laptop without bluetooth likely either doesn't have NFC, or has bluetooth disabled by policy and would likely have cross-device passkeys disabled by policy as well.
Yes, the passkey flow QR code contains a public key, and a local key exchange is done over bluetooth to prove proximity. That is used to set up a confidential channel.
That means attackers need more than to display a QR code, they also need a local presence (radio).
> But this still breaks the login flow for a very common use case: how do I log in on a device that I don't own? With a password in a password manager I at least have the option of manually typing the password.
This is meant to be solved by the cross-device flow - a QR code pops up that you scan, and a secure channel is established from that with your other device.
[Disclosure: an editor of said standard]
> The biggest problem, though, is how users are pushed into it without any warning or knowledge of what they're signing up for.
On macOS/iOS, the system gives this prompt regardless of where your passkeys are being created/stored:
Save a passkey?
"<site>" supports passkeys, a stronger alternative to passwords that cannot be leaked or stolen. A passkey for "<username>" will be saved in "<provider>".
There is a transparent upgrade option though that sites can request - basically when a site supports passwords and passkeys, they can request a password manager supporting both create and return a new passkey on password sign-in.
> [...] and had to go back and figure out how to undo it after being blocked from login on another computer (which computer was I on again?).
That's unfortunate. A site/service should absolutely not replace other passkeys, nor should it remove other sign-in options like passwords, without explicit user consent.
The above credential upgrade flow makes that doubly so; even if someone relies on a password manager to manage and provide their credentials for a site, it very well may not be the singular piece of software that does so.
> it's a low level language - ergo you have to literally express more things about the code
That isn't really a comparison of the languages as much as the standard runtimes and ecosystems. It is important to consider that each have comparable components.
So you aren't comparing a no_std rust project against a comparable JavaCard, but say Diesel vs Hybernate code examples around ORM.
Comparable components, but almost every line of Rust code expresses information about the lifetime of objects - either implicitly (quite often), or explicitly.
Meanwhile in java it's a constant "Arc<JavaType>", and scopes don't mark "drop points"
Hmm? Java gets null dereferences all the time, that's what a NPE is. The VM takes on the extra plumbing to surface a dereference of a null pointer in a recoverable way to code. On Windows this is done using SEH, on Unix it is handling SIGFAULT - but each NPE corresponds to a null pointer dereference that java then tries to clean up.
That the language does not have a way to have compiler enforced "never null" is actually a huge productivity drain, specifically because you have to do your own defensive measures against null or attempt cleanup/recovery when it happens.
Even languages like Swift which use Optional (e.g. a maybe monad) to provide a concept of nilability still internally will hit null pointer dereferences on occasion with faulty bridged code/bindings. However, they treat this as a non-recoverable violation of invariants - a developer shouldn't be trying to recover from incorrect code at runtime.
I've found the challenge of running a non-existent version on a tree that was EOL 16 years ago is typically keeping it up with internal security standards, and not one of new collaborative development.
I have not yet done an actual test within Japan, however.
reply