Oh, hi! Somehow this surfaced again. I’ve since shrank it down to 445 bytes, which allows you to fit a partition table in. Quite important, as most UEFI firmware refuses to perform legacy boot without a valid partition table.
Over time I built a very barebones, but quite usable system on top of miniforth – rudimentary filesystem and vim clone, which allowed to comfortably develop more software on top of it. Well, Forth software, so maybe not that comfortably. Somewhere in the middle of it all I installed it on my main laptop, chainloading Linux from miniforth when I wanted to do something else – some assumptions about disk layout meant it didn’t really work the other way around.
In the end, I lost the momentum to work on the project when the police raided our flat. One day the urge to touch bare metal will come to me again…
Oh, it has been posted, actually. It’s just that since writing it, I’ve transitioned, and then moved the blog over to a different domain. I’d link to the old thread but it didn’t really generate much discussion at the time.
The authors of the linked paper are clearly cranks, as can be seen in section 4.2 (page 18):
Do infinite computations exist? There are two answers yes and no.
Yes: Imagine your computer system is (maliciously) handled by a hacker. This can
be done by preparing its hardware or software (e.g. someone modifies the class
Int in Java). To hide the damage from the user, the hacker may come with a
correct proof that all axioms of natural numbers (e.g. of Presburger’s system) are
valid. Yet, for many n execution of the Collatz algorithm will not terminate. See
subsections 4.4 and 6.1.
No: If argument of Collatz procedure is a standard (i.e. reachable) natural number
then the computation is finite.
Giving some benefit of doubt to the authors, I do find their comment somewhat sensible. There are different views in the TCS community about infinite computations, maybe this is what the authors had in mind.
Consider the following inclusion hierarchy:
the set of real numbers,
the set of real numbers which can be computed,
the set of rational numbers,
the set of integers,
the finite set of 32-bit integers, the integers modulo 2^32.
Surely, some set of axioms holds for any of these interpretations. The lowest in the hierarchy are the integers we store in computer memory. But then there is a maximum value, which is not the case for the mathematical integers where there is no maximum/minimum. In the mathematical integers, the notion of “immediate successor/predecessor” exists, but this property is dropped in the rational numbers. Suppose we see the rational numbers, in their decimal expansion, where we have a finite prefix and a finite sequence of digits that after the prefix repeats periodically. We could also drop that requirement, and allow more complex recurrence patterns in the binary expansion: those are real numbers in which the sequence of digits can be computed (e.g. the constants pi and e). Finally, we have the “free choice sequences,” which are real numbers in which one can not assume there is a known description of its behavior beforehand.
This concept of “free choice sequence” really captures the intuition that anything can happen, and you have no control over nor knowledge of any pattern. Whereas the real numbers which can be computed models the “known unknown”, the full real numbers could be used to model the “unknown unknown”. Some people use real numbers in computability theory to model cyber-physical systems (that model behavior of the overall system, in which the computer is just a subcomponent, that goes “beyond” Turing machines). This seems like a reasonable modeling approach, since the question whether our physical universe is computable is still not answered and probably will not for some time in the future.
In future, if Mozilla is doing official things on domains unrelated to any existing project domain, it would be helpful to:
Link to that domain from one of the official domains
Have a link in the thing on that domain pointing to the place Mozilla links from it.
Doing this would mean that, in two clicks, readers can validate that this really is Mozilla-endorsed and not someone impersonating Mozilla. Training Mozilla users that anyone who copies and pastes the Mozilla logo is a trusted source is probably not great for security, in the long term.
I, too, question whether this page was really written by Mozilla, but I did confirm that Mozilla and other companies really do oppose Article 45 of eIDAS.
Their calls have also been echoed by companies that help build and secure the Internet including the Linux Foundation, Mullvad, DNS0.EU and Mozilla who have put out their own statement.
Some other parties published blog posts against eIDAS Article 45 today:
And at the bottom, yet it’s not on a Mozilla domain, it doesn’t name any Mozilla folks as authors, and the domain it is hosted on has fully redacted WHOIS information and so could be registered to anyone. I can put up a web site with the Mozilla logo on it, that doesn’t make it a Mozilla-endorsed publication.
As is normal for any domain I order from inside the EU.
Edit: And the open letters are all hosted on the https://www.mpi-sp.org/ domain. That doesn’t have to make it more credible, but at least that’s another institute.
As is normal for any domain I order from inside the EU.
It is for any I do as an individual. Corporate ones typically don’t redact this, to provide some accountability. Though I note that mozilla.org does redact theirs.
I’ve found this to be inconstantly administrated. For instance, I believe that it is Nominet (.uk) policy that domain registrant information may be redacted only for registrants acting as an individual. But registration information is redacted by default for all domain contact types at the registry level and there is no enforcement of the written policy.
I’d say what most working mathematicians mean is “any system which is equipotent and equiconsistent with reasoning by way of a Hilbert-style predicate logic system together with the ZFC axioms”. Different mathematicians will have different preferences for the system they actually use, but I don’t know of any which are not equipotent and equiconsistent with ZFC + predicate logic.
This rules out finitary/intuitionist stuff, which is not super popular, and does rule out non-explosive things. Even those can be formulated in the language of ZFC, though, so in practice it’s not a problem.
The technical meaning of “explosive” is that “everything follows from a contradiction”, so if you ever hit a contradiction, the whole thing explodes. In general, it doesn’t matter, but in some AI applications, non-explosive logics are needed to prevent a failure cascade.
ETCS plus Replacement is equiconsistent with ZF. Note that Choice can be optionally added to both systems.
Those of us who work with computers are forced to limit ourselves to that which is realizable, and Choice is not realizable. This means that working with ZFC necessarily entails not working with what computers actually compute. This is all beside the point that intuitionistic approaches have finer detail than classical approaches, as stressed by Bauer 2017.
DNSSEC prevents the MITM from being able to spoof the CAA record which tells Let’s Encrypt what ACME validation methods are allowed. You can restrict ACME to an account with a private key under your control, and/or restrict it to DNS validation which is secured by DNSSEC. The spoofable traffic to the server’s IP address is no longer trusted by Let’s Encrypt as the only authentication.
DNSSEC provides a proof of non-existence for both DNS FQDNs and RRsets within FQDNs. DNSSEC verification thus enables an Issuer to determine whether the answer to a CAA record query (1) is empty because the RRset is empty or (2) is non-empty but the response has been suppressed.
https://datatracker.ietf.org/doc/html/rfc8659#section-5.1-2
This particular attack would have been frustrated, but had they used DNSSEC or CAA then presumably Hetzner or whoever put in the MITM would have used a different approach?
Unlike the traditional 3n+1 Collatz problem, this one looks amenable to a sort of “garden analysis,” where we look at families of polynomials in k under the inverted Collatz map. If there is a terminating trajectory, then it should be characterized by a polynomial in k which contains all possible terminating trajectories. But, that said, the construction of a garden family is kind of annoying and requires a lot of tricky algebra which neither I nor the author have the patience to carry out.
I don’t have a good writeup of gardens. Terry Tao has a great blogpost summarizing the current state of things, and gardens are covered by one of the footnotes.
Gogit doesn’t even support the index (staging area), so instead of gogit add, you just gogit commit with the list of paths you want to commit each time. As pygit’s code shows, dealing with the index is messy. It’s also unnecessary, and I wanted gogit to be an exercise in minimalism.
What a feature! Finally a stateless commit command! Believe it or not, but I have been wanting this for a decade. Thank you for making this, so I wouldn’t have to!
I keep saying that the staging area is a stumbling block that shouldn’t be obligatory to use. It is trivial to squash commits, so it’s not like anyone really needs it to assemble a big commit (modulo self-imposed commit hooks). Rather, this hidden state is a constant source of surprise for us all, since what you commit is not what you see in git diff – if you added, moved, removed or checked out a file yesterday, and didn’t immediately commit or unstage it before you forgot about it, it’s now hidden state, and tends to sneak into the commit that you amend today.
It is trivial to squash commits, so it’s not like anyone really needs it to assemble a big commit
I actually end up using it mostly to assemble small commits: committing parts of my current state at a time when they’re ready, but without having to commit e.g. testing code I still need locally or other changes elsewhere in the file.
I usually abort the git add -p to modify a file slightly before committing, so I don’t do it in one step. I also like to git diff --staged before doing the commit, rather than committing and them amending several times to get it right.
It sounds like what you like about the staging area is that it gives you a notion of draft/private vs. final/public, is that right?
I use that distinction a bit less, or rather more: instead of one staging area in flux, I feel free to edit any commit that hasn’t been pushed/merged yet.
The draft/public distinction doesn’t require an index/staging area: Mercurial attaches it to commits, instead of to exactly one not-a-commit.
Specifically, Mercurial lets you mark commits as being in phase secret (won’t be pushed/pulled), draft (unpushed), or public (has been pushed/pulled).
[Edit because I submitted too soon:]
As for git diff --staged: See how the index concept forces Git to have a separate command? There is git diff for the working directory (but staged changes aren’t really in the working dir); and git log -p for any commit (but the index is not a real commit), so now you need a third invocation. If you sculpt the latest commit instead of an index, git log -p can run on HEAD no problem. (And in my daily work I do exactly this, many times per hour.)
For me, the difference is typically in when I want to remove some diff from my staged changes. It’s pretty easy to git reset the file and redo the git add. I’m not aware of a comparable “remove this file from the commit” command, so if I really need to do that, what I have to do is revert the commit, uncommit the revert-commit to get a negative diff of the commit, remove everything but the change I want to remove, then amend the commit with that change.
Splitting a commit is indeed a missing feature of git rebase, but git-revise has it, and there is a PR to support specifying paths while doing so (rather than answering yes/no to every hunk).
Before that, I also used to do the double-revert dance.
Tip: You can git commit --patch, just like git add --patch. Even with multiple paths if you have. Is that what you mean? It’s not much git add can do that git commit can’t, and it saves a step. Only one thing – committing previously untracked files – which Gogit has now solved.
I also use --amend a lot, or commit many small commits and then squash the related ones. Or if I have no idea to begin with, I just make one big commit at the end and iteratively split out pieces of it with git revise. Which is just as easy as staging out the same small commit from the same set of unstaged changes, with the benefit that it also works with commits that aren’t the last.
I don’t find it that big of an issue. Perhaps it is because I learned to do git status to orient myself, much like sysadmins habitually type ls like muscle memory.
(well, I have alias gs="git status", so it’s not as much typing as you’d think)
Most certainly. I never (intentionally) use the staging area, which is why I have no use for git status. Other than to assert that nothing is staged before I commit. I do that if I’m unsure, but it’s not a habit, which is how it surprises me again and again.
The ls thing is a reason that you shouldn’t actually use the command line for managing novel filespaces. It’s only good for filespaces you already roughly know.
In the manually vectorized version, the author has:
// Process leftovers
res + baseline(&input[n_simd_elems..])
Which does the right thing, it processes the leftovers without vectorization. But what if you wanted to use functions written like opt1_idiomatic or opt2_count_s to process the remainder? Is there an annotation like #[inline(never)] for vectorization to tell Rust to not vectorize some bit of code? Obviously you don’t want the compiler to generate the 165 instruction version of opt1_idiomatic for just the tail of the array.
If Quad9 and friends redirected users to a page with a “malicious website blocked” message, users could understand what was going on and try to contact the owners, but those services choose to keep them in the dark by returning a SERVFAIL.
How would this be accomplished? A DNS provider can’t hijack the A record and point to their own error page. At least not without horrible consequences.
Citation needed. Unlike with CAs, there’s no official requirement list for serving DNS. It all boils down to end user trust, and that follows from the intent inferred by users from your actions, and not technicalities. If you advertise malware blocking as a feature, users will likely see the serving of such an A record as expected behavior.
My point is, when they receive responses with A/AAAA records but send NXDOMAIN or SERVFAIL to the requester, that’s already tampering with responses. I can’t see how returning a different address is any more of a hijacking. If they think hijacking for the sake of security is acceptable, at least they should make it clear to the users what’s going on and not pretend that the upstream DNS server has a problem.
It’s so much more of a hijacking to return a different address. If a user is in a browser they might turn around and send a GET request with sensitive information in the request headers. If they’re not in a browser who knows what they are doing with that bad ip.
There’s a world of difference between “blocks bad dns entries completely” and “hijacks dns entries and masquerades as various parts of the internet”
This is making me think that the real problem is that the DNS protocol doesn’t have a way to cleanly indicate something is blocked. All you can do is send SERVFAIL/NXDOMAIN, or forge an A response.
I’m imagining some DNS responses similar to HTTP 451 except not specific to legal reasons.
DNSSEC is the biggest technical hurdle here, but I think we can all agree that tampering with authoritative DNS responses is pretty gross even if it maybe sort of does work most of the time.
I recall that one reason that — formerly? — often was cited for switching away from one’s ISP’s DNS service to Google Public DNS and OpenDNS (I’m not sure Quad9 existed) was to get actual “domain not found” DNS responses rather than the pages of Web search results and ads that ISPs would serve, so I would think it is possible for a DNS provider to give an informative error page if it blocks a domain.
I’m not saying it isn’t technically possible†, I’m saying it is extremely undesirable from a security perspective. And just technically gross.
† In those days we didn’t have ubiquitous HTTPS, and DNSSEC (as /u/strugee pointed out) wasn’t a thing, so it is now actually technically much harder / sometimes impossible to takeover a domain like this. But I’m not objecting to the feasibility so I didn’t originally bring it up.
I’m having trouble understanding what the AMD SMU is. From the context I guess it is somewhat like the Intel ME? Though AMD PSP is the direct equivalent for that. I am confused.
This HN comment explains what’s wrong with the proof. Having read the paper, I agree with the analysis:
Unsurprisingly, there’s nothing here. Most of the paper describes a brute force search across all possible variable assignments in the form of a graph (with some pointless polynomial improvements like making it a trie), where you build a path of vertices representing each set of truth values that satisfies a given expression. This clearly has exponential size, which the author alludes to in the “improvements” section by noting it does “redundant work”. This is addressed by collapsing the exponential graph down to have only one vertex for each variable*expression pair (if you ignore the trie) and adding exponentially many labels for the different paths to reach a given vertex. (incidentally, to the extent that it’s described clearly, it seems like the improved layered graph would basically be the same as the original non-layered graph)
The final complexity discussion uses the graph size constraint gained by the “improvement” but doesn’t consider how to handle the extra labeling meaningfully. Basically, the pre- and post-improvement algorithms put the exponential work in different spots, and the sloppiness of the algorithm description (I mean, really, why tell us you’re using a stack for BFS and then have “determine the subset of satisfied constraints” as a step) makes it easy to ignore.
I’m also being a little generous with the algorithm itself. As described, some of the trie optimizations seem to make certain combinations of satisfied expressions impossible to notice, but I think it’s not a big deal to make this part work. The properties of the trie structure (and of sorting the variables by occurrence, for that matter) don’t seem to be used.
Yeah, I think this is pretty confusing unless you’re already very guix-savvy; it claims to be fully bootstrapped from source, but then in the middle of the article it says:
There are still some daunting tasks ahead. For example, what about the Linux kernel?
So what it is that was bootstrapped if it doesn’t include Linux? Is this a feature that only works for like … Hurd users or something?
They bootstrapped the userspace only, and with the caveat that the bootstrap is driven by Guix itself, which requires a Guile binary much larger than the bootstrap seeds, and there are still many escape hatches used for stuff like GHC.
reading the hex0 thing, it looks like this means that if you are on a Linux system, then you could build all of your packages with this bootstrapped thing, and you … basically just need to show up with an assembler for this hex0 file?
One thing about this is that hex0 calls out to a syscall to open() a file. Ultimately in a bootstrappable system you still likely have some sort of spec around file reading/writing that needs to be conformed to, and likely drivers to do it. There’s no magic to cross the gap of system drivers IMO
Hex0 is a language specification (like brainf#ck but more useful)
no, you don’t even need an assembler.
hex0.hex0 is and example of a self-hosting hex0 implementation.
hex0 can be approximated with: sed ‘s/[;#].*$//g’ $input_file | xxd -r -p > $output_file
there are versions written in C, assembly, various shells and as it is only 255bytes it is something that can be hand toggled into memory or created directly in several text editors or even via BootOS.
It exists for POSIX, UEFI, DOS, BIOS and bare metal.
I had a look around to see how Tree Borrows relates to Stacked Borrows. Looks like there are some problems with Stacked Borrows that Tree Borrows aims to fix. Tree Borrows comes from Ralf Jung’s team; Ralf developed Stacked Borrows.
I haven’t found a concise outline of the problems with Stacked Borrows and how Tree Borrows addresses them.
Having read the stacked borrows paper, my main beef with them is that the rules for raw pointers are hard to think about. Said paper pointed out that a tree-based model would probably work better here, and I am happy to see this research being done.
It could be worse, the user has the old rsa host key present alongside newer ed / ecdsa keys, they may never rotate out the rsa one. A future mitm simply only advertises the rsa key, and mitm passes.
Users will need to actively remove the old rsa key in order to be safe.
Okay, I tested this and on a new enough OpenSSH client, the RSA key gets replaced using the mechanism described here: https://lwn.net/Articles/637156/ (if you connect using a key other than RSA).
But this is also a very bad thing in the other direction. If you are MITM’d first, they can “update” the other keys if you connect with RSA first, right?
I mean, it doesn’t really make any difference? The only situation where this makes any difference is if the user takes no action to update the keys manually, and in that case the MITM will continue as long as the man is in the middle, whether this mechanism exists or not. And then once you connect to actual GitHub, the fact that you got MITMed will be more noticeable.
I would hesitate to call the implementation of PhantomData pristine – it’s a lang item, which means it gets special-cased in the compiler, very much unlike std::mem::drop.
Really enjoying this article for its historical analysis of the earlier research languages that inspired Rust’s ownership & borrowing rules. Also there are some great quotes from Rust users, like
“Learning Rust Ownership is like navigating a maze where the walls are made of asbestos and frustration, and the maze has no exit, and every time you hit a dead end you get an aneurysm and die.”
and
“I can teach the three rules [of Ownership] in a single lecture to a room of undergrads. But the vagaries of the borrow checker still trip me up every time I use Rust!”
But the really interesting quote, to me, is
They randomly assigned students to two groups, one having to complete the assignment using the Rust standard library data types, and one using a garbage-collected wrapper type (called “Bronze”) which enabled a number of additional aliasing patterns to pass the borrow-checker, thus removing the needs for more complex aliasing patterns and datatypes.
They found a significant difference in the rate of completion and the self-reported time to completing the assignment. The students who used Bronze on average took only a third as much time as the control group, and were approximately 2.44 times more likely to complete the assignment.
This reflects my own opinion that I would prefer some lifetime “violations” to be addressed by using ref-counting or GC, rather than turning them into errors. An example of this is the way Go will allocate structs on the stack when possible but promote them to GC objects when escape analysis shows that would cause use-after-return bugs. Or the way Lobster/Swift/ObjC/Nim use ref-counting but are able to eliminate many of the retain/release operations based on static analysis. Essentially this turns a lifetime-checker into a performance optimization tool, not a gatekeeper from being able to build at all.
Lifetimes aren’t just about memory management. Iterator invalidation is also a common category of bugs that the borrow checker prevents. Pretty sure the thread safety guarantees also make use of it, to make sure you don’t have any lingering references to data owned by a mutex once you lock it.
Performance isn’t the only part of Rust’s value proposition, and it’s the easiest one to catch up with.
I presume that in the context of this experiment they would write some iterator implementations which don’t become invalid. In a single threaded context this should almost always be possible with some slowdown.
e.g. for a Vec analogue, your iterator keeps an Rc pointer to the Vec, and a current index, and it re checks that the index is still in range on every call to get the next item.
e.g. for a btree analogue, the iterator stores the last retrieved key and the call to get the next item asks the underlying btree for the first item > the last retrived key. Makes iterating a btree O(n*log(n)) instead of O(n) which is a little bit dramatic.
This is kind-of what Objective-C fast enumeration does and it isn’t great for usability. Code will now throw an exception on mutation of the underlying collection and you can’t statically verify that it won’t. Checking that the index is in bounds isn’t sufficient, this can lead to TOCTOU bugs if you check a property of the current element, insert something before it, and then operate on a different object by mistake.
I’ve wondered what an “easy mode” rust would look like.
I don’t feel like cloning and the borrow rules were my main barriers though. If you don’t care about allocations you can approximate a GC-ish approach by cloning all over the place.
The problem with making everything mutable and cloning everywhere all the time is that you lose guarantees. Part of the feedback that I like about rust (after having used it for awhile) is that my type signatures for functions and structs help inform me about the impacts of my design decisions.
Right — I said recently in some other thread that once you start using Rust’s escape hatches like Rc you lose the compile-time checking, which is such an important part of the value proposition.
But if we want GC or RC everywhere we have that already and don’t need rust? Rust is for when you want the control to decide for yourself when that is ok or if it is not
You’d still have a choice — the compiler would only use RC if it couldn’t determine the object’s lifetime statically. There could be an optional compiler flag that raises a warning (or error) when this happens, exactly like those verbose borrow-checker warnings, if you don’t want that to occur.
Or alternatively, the warning/error is on by default but there’s a notation you put in the source code at that spot to say “it’s OK to promote this to RC here if necessary.” (A simple notation that doesn’t require you to change the object’s type or calling convention everywhere!)
This is hand-wavey and maybe impossible, but it’s Sunday morning and a boy can dream.
I am pretty sure that it is not merely possible, but already done 25..30 years ago in Jeffery Mark Suskind’s Stalin - IIRC, his fall back was Boehm-Wiser not RC. (EDIT: His early impls were in the very early 90s as a concept fork from the Dylan effort; “Sta-lin” sort of referenced “static language” or “brutally optimizing” or etc.)
I don’t see why one would ever need to get an encrypted message that they are unable to decrypt, while getting ensured that it got encrypted correctly. The article desperately needs a motivation section.
I agree that it’s difficult to think about concrete uses cases, but we do have them! One small correction to your message: you do need to be able to decrypt the message but you don’t want to do that unless it’s an emergency. For example you don’t want to decrypt it since it can be a potential security problem. At the same time you want to be sure that the encryption was correctly done so that when you need to access the message you know it’s there waiting for you.
We will share them it in the future, we need to get approval from one customer.
Does the verifier get the prover’s DH share? If not, that then becomes the new key - what happens to that? Otherwise, the verifier is just choosing not to perform the decryption at the moment, and I don’t see how that gives you any security.
The important part is to make sure that the message is there when you need it. Opening it if it’s not an emergency isn’t an issue but you don’t gain anything doing that. What you want is to verify that the message was encrypted so that you can open when needed.
As with most cryptographic primitives, they don’t have many uses cases at the beginning until somebody starts using it and shows why they are useful. We already have two uses cases where this will be used in a product. One for a client and another for a product we’re building.
I’d assume bcrypt and scrypt, which with most implementations setting good input costs per default or as a lower bound (and higher depending on CPU speed). Both bcrypt and scrypt have memory requirements in addition to CPU requirements, making it more costly to use certain hardware such as ASICs and GPUs.
No, bcrypt/scrypt/etc are still fundamentally solving a different problem, and would essentially just be a PBKDF if used as I think you’re suggesting. Obviously using either of these options would be superior to not doing so, but the actual secure solution here is policy-gating via HSM.
the only problem is that the HSM is something you can physically lose, and a passphrase is in your brain forever (modulo amnesia…)
with how Apple/Google sync FIDO2 passkeys between devices, it is a multi-device system that gets the same keys decryptable by multiple HSMs, but (I’m not sure which option they picked tbh, probably the first one?) such a system either is completely non-recoverable if you lose all devices simultaneously, or is doing “normally” (non-HSM) encrypted “cloud” backup.
the only problem is that the HSM is something you can physically lose, and a passphrase is in your brain forever (modulo amnesia…)
If you are a company providing a service like last pass, you should not be in a position to lose the HSM
with how Apple/Google sync FIDO2 passkeys between devices, it is a multi-device system that gets the same keys decryptable by multiple HSMs
I can’t speak for how google’s passkey syncing works, but I would assume/hope the same as what I’m about to say. Apple’s works over the synchronized keychain mechanism, which is fully end-to-end encrypted with actual random keys, not HSM based (we’ll circle back in a bit). When you add a new device to your apple account, that device has to be approved by one of your other existing devices, and it is that approval that results in your existing device wrapping the account key material to the new device’s keys and sending those wrapped keys to the new device. Once the new device gets that packet it can decrypt the remainder of the keychain material. Each device keeps its own private keys and the account key material protected by the local secure environment.
Note that even the old non-e2e encrypted iCloud backups did not backup keychain material, so compromising the backup infrastructure would not provide access to passwords, passkeys, etc. The concern of course is that for many governments/organisations trawling your back ups is pretty much all that’s wanted, as it just means they have to wait for a backup to happen rather than being able to decrypt in real time. Happily e2e for everything is now an option for apple’s cloud services.
Historically losing your account password (and so resetting the account password is required) would as a byproduct mean losing your synced keychain, so if you didn’t have them locally the data is gone. There is a final ditch backup called something like “iCloud Key Vault” or some such which is the marketing name for large scale and robust HSM setups required given the data being protected. These are policy gated HSMs that devices can back up some core key material to (Ivan Krstic has a blackhat talk from a few years ago that goes over them, but essentially you take a bunch of hsms, get them to all synchronize with each other, then blend the admin cards and have them all roll their internal keys so there is no way to install new software, rely on previously recorded key material, or install compromised hardware into an existing vault).
a company providing a service like last pass, you should not be in a position to lose the HSM
Oh… you weren’t talking about having the HSM local to the user?? Server side HSM doesn’t seem to make sense to me for a password manager where decryption MUST happen on the client?
Recovery path - this is an HSM + policy system where the user key material is protected by HSM policy. This is dependent on the HSMs being configured to ensure that the HSM owner does not have access to the HSM’s key material. This is why we talk about an HSM’s security model having to include physical access to the HSM.
Protecting user data: PBKDFs are weak due to generally terrible user provided entropy, so what you do is you receive the user’s data encrypted by the user’s relatively poor entropy. Rather than just storing that, you ask your HSMs to encrypt it with an actual key gated by policy on something like the user’s account password.
The recovery path is obviously optional, but the latter is needed to defend against “hackers downloaded all our user data and that data is protected only by relatively weak entropy”.
The ideal case is a user having multiple devices, and then having new devices receive decryption keys from the existing ones. That means the data that gets uploaded to the servers for syncing are always encrypted with a true random key, and the concept of a “master key” ceases to be relevant.
The correct thing to do is to use the password + hsm to policy gate access to the encryption keys, This is how modern devices protect your data.
Your passcode (phone), or password (decent computer/hardcore phone :D), includes an HSM that google calls a hardware backed keystore, and apple calls a Secure Enclave (there’s also the similarly named “Secure Element”, but this is actually another coprocessor that runs a cut down JVM for payments :D).
Anyway, in all implementations the HSMs use internal [generally to the cpu itself] keys. These keys are then used to encrypt all data being stored via the HSM. Retrieving the data is done by providing credentials (your password, etc) to the HSM, the HSM then policy gates access, for example the HSM itself counts attempts and enforces time outs. Because the HSM is performing this gating itself, it doesn’t matter how much cpu power the attacker has: there’s no precomputation, hashing, etc they can do, and having access to the HSM-encrypted data is not brute forceable because the HSM is encrypting with a true random key, not something derived from some kind of guessable password.
If LastPass folk had done this, then downloading the data would have been useless, and a fully local compromise would have still not been able get raw data as the attacker would still be forced to ask the HSM for data by providing username+password combos, and so be subject to the same attempt count and timeout restrictions of a non-local attacker.
You really want to avoid cheap ham as It may have parasites :D (Sorry, I recognize the suffering of autocorrect vs. “hsm” :D)
There are two aspects to a commercial HSM (vs say a yubikey):
The first is the software. For this what you want is a very small, very simple OS as an HSM is something where the trade off between entirely verifiable software vs. extra features (you don’t want any software on an HSM that isn’t directly tied to the functions the HSM provides).
Next there’s the hardware. Now this is where things get hard, as an HSM is expected to be secure against a person with physical access, so you have both the electronic design to be aware of, as well as the physical design. Even if someone does have an open source design, the actual manufacture is expensive.- many HSM chips are hardened at a silicon level, with layout and patterning stuff such that the even decapping the chip and then using an electron microscope does not expose the on die data. Suffice to say this means you can’t use an fpga or some generic asic manufacturing, which ramps up the price.
The HSMs are then generally wrapped in many layers of plate steel, etc that can be adhered to various parts of the board so that removing the plates also breaks things (for example cracking various dies, etc).
While writing this I discovered that yubico have started making an “affordable” hsm product at only $650, or $950 with fips certification, which looks like it fulfills the core cryptographic primitives and you’d only have to manage the storage of secured data.
The mention of Intel ME including a JVM got me curious, and following the links seems to lead to some kind of an incomplete archived copy of the relevant website – only the first two slides can be seen.
DRM failing, as it always eventually will, is music to my heart <3
Oh, hi! Somehow this surfaced again. I’ve since shrank it down to 445 bytes, which allows you to fit a partition table in. Quite important, as most UEFI firmware refuses to perform legacy boot without a valid partition table.
Over time I built a very barebones, but quite usable system on top of miniforth – rudimentary filesystem and vim clone, which allowed to comfortably develop more software on top of it. Well, Forth software, so maybe not that comfortably. Somewhere in the middle of it all I installed it on my main laptop, chainloading Linux from miniforth when I wanted to do something else – some assumptions about disk layout meant it didn’t really work the other way around.
In the end, I lost the momentum to work on the project when the police raided our flat. One day the urge to touch bare metal will come to me again…
I have a long backlog of posts shared by others and was finally getting to it, and noticed this nice piece hadn’t been posted to lobsters yet :P
I really enjoy stuff like this! Hope you’re all staying safe out there.
Oh, it has been posted, actually. It’s just that since writing it, I’ve transitioned, and then moved the blog over to a different domain. I’d link to the old thread but it didn’t really generate much discussion at the time.
The authors of the linked paper are clearly cranks, as can be seen in section 4.2 (page 18):
Giving some benefit of doubt to the authors, I do find their comment somewhat sensible. There are different views in the TCS community about infinite computations, maybe this is what the authors had in mind.
Consider the following inclusion hierarchy:
Surely, some set of axioms holds for any of these interpretations. The lowest in the hierarchy are the integers we store in computer memory. But then there is a maximum value, which is not the case for the mathematical integers where there is no maximum/minimum. In the mathematical integers, the notion of “immediate successor/predecessor” exists, but this property is dropped in the rational numbers. Suppose we see the rational numbers, in their decimal expansion, where we have a finite prefix and a finite sequence of digits that after the prefix repeats periodically. We could also drop that requirement, and allow more complex recurrence patterns in the binary expansion: those are real numbers in which the sequence of digits can be computed (e.g. the constants pi and e). Finally, we have the “free choice sequences,” which are real numbers in which one can not assume there is a known description of its behavior beforehand.
This concept of “free choice sequence” really captures the intuition that anything can happen, and you have no control over nor knowledge of any pattern. Whereas the real numbers which can be computed models the “known unknown”, the full real numbers could be used to model the “unknown unknown”. Some people use real numbers in computability theory to model cyber-physical systems (that model behavior of the overall system, in which the computer is just a subcomponent, that goes “beyond” Turing machines). This seems like a reasonable modeling approach, since the question whether our physical universe is computable is still not answered and probably will not for some time in the future.
no date, no author, no reference. Looks fishy.
This is legitimately from Mozilla.
In future, if Mozilla is doing official things on domains unrelated to any existing project domain, it would be helpful to:
Doing this would mean that, in two clicks, readers can validate that this really is Mozilla-endorsed and not someone impersonating Mozilla. Training Mozilla users that anyone who copies and pastes the Mozilla logo is a trusted source is probably not great for security, in the long term.
There’s literally a date, references at the bottom, and it says Mozilla both at the top and bottom.
date acknowledged, but placing a mozilla logo is too easy faked.
IMO would be ok on their own domain. But not on a vanity domain.
I, too, question whether this page was really written by Mozilla, but I did confirm that Mozilla and other companies really do oppose Article 45 of eIDAS.
This Mozilla URL hosts a 3-page open letter against Article 45 of eIDAS: https://blog.mozilla.org/netpolicy/files/2023/11/eIDAS-Industry-Letter.pdf. It’s a completely different letter from the 18-page letter linked by this story, though both letters are dated 2 November 2023. This story references Mozilla’s letter as if it’s by someone else:
Some other parties published blog posts against eIDAS Article 45 today:
This convinced me https://techpolicy.social/@mnot/111339245119669445
There’s a very big Mozilla logo at the top.
And at the bottom, yet it’s not on a Mozilla domain, it doesn’t name any Mozilla folks as authors, and the domain it is hosted on has fully redacted WHOIS information and so could be registered to anyone. I can put up a web site with the Mozilla logo on it, that doesn’t make it a Mozilla-endorsed publication.
As is normal for any domain I order from inside the EU.
Edit: And the open letters are all hosted on the https://www.mpi-sp.org/ domain. That doesn’t have to make it more credible, but at least that’s another institute.
It is for any I do as an individual. Corporate ones typically don’t redact this, to provide some accountability. Though I note that mozilla.org does redact theirs.
Good to know. The company domains I dealt with all have this enabled. (Some providers don’t even give you the option to turn it off.)
I’ve found this to be inconstantly administrated. For instance, I believe that it is Nominet (.uk) policy that domain registrant information may be redacted only for registrants acting as an individual. But registration information is redacted by default for all domain contact types at the registry level and there is no enforcement of the written policy.
This is the link that was shared by Stephen Murdoch, who is one of the authors of the open letter: https://nce.mpi-sp.org/index.php/s/cG88cptFdaDNyRr
I’d trust his judgement on anything in this space.
I’d say what most working mathematicians mean is “any system which is equipotent and equiconsistent with reasoning by way of a Hilbert-style predicate logic system together with the ZFC axioms”. Different mathematicians will have different preferences for the system they actually use, but I don’t know of any which are not equipotent and equiconsistent with ZFC + predicate logic.
This rules out finitary/intuitionist stuff, which is not super popular, and does rule out non-explosive things. Even those can be formulated in the language of ZFC, though, so in practice it’s not a problem.
I’d say intuitionism is quite popular among people looking into math foundations.
That’s an exciting sounding term. What do you mean by this, please? :)
I believe GP referred to what is officially known as “paraconsistent logics”
Thanks, this was the term that I needed to look up more details.
The technical meaning of “explosive” is that “everything follows from a contradiction”, so if you ever hit a contradiction, the whole thing explodes. In general, it doesn’t matter, but in some AI applications, non-explosive logics are needed to prevent a failure cascade.
ETCS plus Replacement is equiconsistent with ZF. Note that Choice can be optionally added to both systems.
Those of us who work with computers are forced to limit ourselves to that which is realizable, and Choice is not realizable. This means that working with ZFC necessarily entails not working with what computers actually compute. This is all beside the point that intuitionistic approaches have finer detail than classical approaches, as stressed by Bauer 2017.
Wow.
This could have been prevented by:
I don’t know if other CAs have a way to prevent mis-issuance to a MITM.
I don’t see how DNSSEC helps. The MitM-ing machine responds to the same IP as the actual server.
DNSSEC prevents the MITM from being able to spoof the CAA record which tells Let’s Encrypt what ACME validation methods are allowed. You can restrict ACME to an account with a private key under your control, and/or restrict it to DNS validation which is secured by DNSSEC. The spoofable traffic to the server’s IP address is no longer trusted by Let’s Encrypt as the only authentication.
ah, those acme CAA extensions look very useful! https://datatracker.ietf.org/doc/html/rfc8657
This particular attack would have been frustrated, but had they used DNSSEC or CAA then presumably Hetzner or whoever put in the MITM would have used a different approach?
They do control the server, after all.
Yes, different attacks need different defences, but I dunno what the attackers might have done against a stronger defensive posture.
Unlike the traditional
3n+1
Collatz problem, this one looks amenable to a sort of “garden analysis,” where we look at families of polynomials ink
under the inverted Collatz map. If there is a terminating trajectory, then it should be characterized by a polynomial ink
which contains all possible terminating trajectories. But, that said, the construction of a garden family is kind of annoying and requires a lot of tricky algebra which neither I nor the author have the patience to carry out.Do you have a link to some relevant literature on the topic?
I don’t have a good writeup of gardens. Terry Tao has a great blogpost summarizing the current state of things, and gardens are covered by one of the footnotes.
Are you sure this is the right link? I am having trouble finding any footnotes, and ctrl+F garden also doesn’t yield anything.
What a feature! Finally a stateless commit command! Believe it or not, but I have been wanting this for a decade. Thank you for making this, so I wouldn’t have to!
I keep saying that the staging area is a stumbling block that shouldn’t be obligatory to use. It is trivial to squash commits, so it’s not like anyone really needs it to assemble a big commit (modulo self-imposed commit hooks). Rather, this hidden state is a constant source of surprise for us all, since what you commit is not what you see in git diff – if you added, moved, removed or checked out a file yesterday, and didn’t immediately commit or unstage it before you forgot about it, it’s now hidden state, and tends to sneak into the commit that you amend today.
I actually end up using it mostly to assemble small commits: committing parts of my current state at a time when they’re ready, but without having to commit e.g. testing code I still need locally or other changes elsewhere in the file.
I, too, make small commits from a larger uncommitted change, but you don’t need a staging area for that.
Instead of sculpting a staging area and then committing, I sculpt the commit directly.
I usually abort the
git add -p
to modify a file slightly before committing, so I don’t do it in one step. I also like togit diff --staged
before doing the commit, rather than committing and them amending several times to get it right.It sounds like what you like about the staging area is that it gives you a notion of draft/private vs. final/public, is that right?
I use that distinction a bit less, or rather more: instead of one staging area in flux, I feel free to edit any commit that hasn’t been pushed/merged yet.
The draft/public distinction doesn’t require an index/staging area: Mercurial attaches it to commits, instead of to exactly one not-a-commit.
Specifically, Mercurial lets you mark commits as being in phase secret (won’t be pushed/pulled), draft (unpushed), or public (has been pushed/pulled).
[Edit because I submitted too soon:]
As for
git diff --staged
: See how the index concept forces Git to have a separate command? There isgit diff
for the working directory (but staged changes aren’t really in the working dir); andgit log -p
for any commit (but the index is not a real commit), so now you need a third invocation. If you sculpt the latest commit instead of an index,git log -p
can run on HEAD no problem. (And in my daily work I do exactly this, many times per hour.)For me, the difference is typically in when I want to remove some diff from my staged changes. It’s pretty easy to
git reset
the file and redo thegit add
. I’m not aware of a comparable “remove this file from the commit” command, so if I really need to do that, what I have to do is revert the commit, uncommit the revert-commit to get a negative diff of the commit, remove everything but the change I want to remove, then amend the commit with that change.Splitting a commit is indeed a missing feature of git rebase, but git-revise has it, and there is a PR to support specifying paths while doing so (rather than answering yes/no to every hunk).
Before that, I also used to do the double-revert dance.
darcs record
&pijul record
continue amending the current commit in this fashion.unrecord
allows “uncommiting”.Tip: You can
git commit --patch
, just likegit add --patch
. Even with multiple paths if you have. Is that what you mean? It’s not muchgit add
can do thatgit commit
can’t, and it saves a step. Only one thing – committing previously untracked files – which Gogit has now solved.I also use
--amend
a lot, or commit many small commits and then squash the related ones. Or if I have no idea to begin with, I just make one big commit at the end and iteratively split out pieces of it with git revise. Which is just as easy as staging out the same small commit from the same set of unstaged changes, with the benefit that it also works with commits that aren’t the last.I’m aware, but I usually need to
q
thegit add -p
to edit a file, so my workflow isn’t amenable to doinggit commit -p
up front.I don’t find it that big of an issue. Perhaps it is because I learned to do
git status
to orient myself, much like sysadmins habitually typels
like muscle memory.(well, I have
alias gs="git status"
, so it’s not as much typing as you’d think)Most certainly. I never (intentionally) use the staging area, which is why I have no use for git status. Other than to assert that nothing is staged before I commit. I do that if I’m unsure, but it’s not a habit, which is how it surprises me again and again.
The ls thing is a reason that you shouldn’t actually use the command line for managing novel filespaces. It’s only good for filespaces you already roughly know.
If you’re after that, you could try jujutsu
In the manually vectorized version, the author has:
Which does the right thing, it processes the leftovers without vectorization. But what if you wanted to use functions written like
opt1_idiomatic
oropt2_count_s
to process the remainder? Is there an annotation like#[inline(never)]
for vectorization to tell Rust to not vectorize some bit of code? Obviously you don’t want the compiler to generate the 165 instruction version ofopt1_idiomatic
for just the tail of the array.#[cold]
might have the effect you want.Good tip! But it doesn’t seem to work.
I know it doesn’t actually matter in any measurable way, but it would make me feel a tiny bit better.
Great write-up.
How would this be accomplished? A DNS provider can’t hijack the A record and point to their own error page. At least not without horrible consequences.
Citation needed. Unlike with CAs, there’s no official requirement list for serving DNS. It all boils down to end user trust, and that follows from the intent inferred by users from your actions, and not technicalities. If you advertise malware blocking as a feature, users will likely see the serving of such an A record as expected behavior.
My point is, when they receive responses with A/AAAA records but send NXDOMAIN or SERVFAIL to the requester, that’s already tampering with responses. I can’t see how returning a different address is any more of a hijacking. If they think hijacking for the sake of security is acceptable, at least they should make it clear to the users what’s going on and not pretend that the upstream DNS server has a problem.
It’s so much more of a hijacking to return a different address. If a user is in a browser they might turn around and send a GET request with sensitive information in the request headers. If they’re not in a browser who knows what they are doing with that bad ip.
There’s a world of difference between “blocks bad dns entries completely” and “hijacks dns entries and masquerades as various parts of the internet”
This is making me think that the real problem is that the DNS protocol doesn’t have a way to cleanly indicate something is blocked. All you can do is send SERVFAIL/NXDOMAIN, or forge an A response.
I’m imagining some DNS responses similar to HTTP 451 except not specific to legal reasons.
DNSSEC is the biggest technical hurdle here, but I think we can all agree that tampering with authoritative DNS responses is pretty gross even if it maybe sort of does work most of the time.
I recall that one reason that — formerly? — often was cited for switching away from one’s ISP’s DNS service to Google Public DNS and OpenDNS (I’m not sure Quad9 existed) was to get actual “domain not found” DNS responses rather than the pages of Web search results and ads that ISPs would serve, so I would think it is possible for a DNS provider to give an informative error page if it blocks a domain.
2009: https://superuser.com/questions/50922/isps-hijacking-dns-errors-on-the-web
2020: https://superuser.com/questions/1521827/how-can-i-block-my-isps-search-engine
I’m not saying it isn’t technically possible†, I’m saying it is extremely undesirable from a security perspective. And just technically gross.
† In those days we didn’t have ubiquitous HTTPS, and DNSSEC (as /u/strugee pointed out) wasn’t a thing, so it is now actually technically much harder / sometimes impossible to takeover a domain like this. But I’m not objecting to the feasibility so I didn’t originally bring it up.
Unrelated: Lobsters supports @ mention syntax, though there’s no notification mechanism. @altano
Neat, thanks for the tip
I’m having trouble understanding what the AMD SMU is. From the context I guess it is somewhat like the Intel ME? Though AMD PSP is the direct equivalent for that. I am confused.
Looks like the SMU is more of a power/thermal management controller, according to https://fuse.wikichip.org/news/1177/amds-zen-cpu-complex-cache-and-smu/2/
This HN comment explains what’s wrong with the proof. Having read the paper, I agree with the analysis:
What is this hex0 program that they are talking about? I don’t understand how that is the starting point, could someone expand?
The program is here: https://github.com/oriansj/bootstrap-seeds/blob/master/POSIX/x86/hex0_x86.hex0
It’s a program that reads ASCII hex bytes from one file and outputs their binary form to the second file.
Yeah, I think this is pretty confusing unless you’re already very guix-savvy; it claims to be fully bootstrapped from source, but then in the middle of the article it says:
So what it is that was bootstrapped if it doesn’t include Linux? Is this a feature that only works for like … Hurd users or something?
They bootstrapped the userspace only, and with the caveat that the bootstrap is driven by Guix itself, which requires a Guile binary much larger than the bootstrap seeds, and there are still many escape hatches used for stuff like GHC.
reading the
hex0
thing, it looks like this means that if you are on a Linux system, then you could build all of your packages with this bootstrapped thing, and you … basically just need to show up with an assembler for thishex0
file?One thing about this is that
hex0
calls out to a syscall toopen()
a file. Ultimately in a bootstrappable system you still likely have some sort of spec around file reading/writing that needs to be conformed to, and likely drivers to do it. There’s no magic to cross the gap of system drivers IMOHex0 is a language specification (like brainf#ck but more useful)
no, you don’t even need an assembler.
hex0.hex0 is and example of a self-hosting hex0 implementation.
hex0 can be approximated with: sed ‘s/[;#].*$//g’ $input_file | xxd -r -p > $output_file
there are versions written in C, assembly, various shells and as it is only 255bytes it is something that can be hand toggled into memory or created directly in several text editors or even via BootOS.
It exists for POSIX, UEFI, DOS, BIOS and bare metal.
I have no existing insight, but it looks like https://bootstrapping.miraheze.org/wiki/Stage0 at least tries to shed some light on this :)
I had a look around to see how Tree Borrows relates to Stacked Borrows. Looks like there are some problems with Stacked Borrows that Tree Borrows aims to fix. Tree Borrows comes from Ralf Jung’s team; Ralf developed Stacked Borrows.
I haven’t found a concise outline of the problems with Stacked Borrows and how Tree Borrows addresses them.
The main sales pitch, at least for me, is the copy_nonoverlapping example. This fixes a particular nasty problem with stacked borrows (the best example I know is this: https://github.com/rust-lang/rust/issues/60847#issuecomment-492558787). I personally hit that more or less every time when I write non-trivial
unsafe
code.Having read the stacked borrows paper, my main beef with them is that the rules for raw pointers are hard to think about. Said paper pointed out that a tree-based model would probably work better here, and I am happy to see this research being done.
As raggi points out on the orange website:
Okay, I tested this and on a new enough OpenSSH client, the RSA key gets replaced using the mechanism described here: https://lwn.net/Articles/637156/ (if you connect using a key other than RSA).
But this is also a very bad thing in the other direction. If you are MITM’d first, they can “update” the other keys if you connect with RSA first, right?
I mean, it doesn’t really make any difference? The only situation where this makes any difference is if the user takes no action to update the keys manually, and in that case the MITM will continue as long as the man is in the middle, whether this mechanism exists or not. And then once you connect to actual GitHub, the fact that you got MITMed will be more noticeable.
I would hesitate to call the implementation of
PhantomData
pristine – it’s a lang item, which means it gets special-cased in the compiler, very much unlikestd::mem::drop
.I was curious, so I looked up where the special case happens:
Really enjoying this article for its historical analysis of the earlier research languages that inspired Rust’s ownership & borrowing rules. Also there are some great quotes from Rust users, like
and
But the really interesting quote, to me, is
This reflects my own opinion that I would prefer some lifetime “violations” to be addressed by using ref-counting or GC, rather than turning them into errors. An example of this is the way Go will allocate structs on the stack when possible but promote them to GC objects when escape analysis shows that would cause use-after-return bugs. Or the way Lobster/Swift/ObjC/Nim use ref-counting but are able to eliminate many of the retain/release operations based on static analysis. Essentially this turns a lifetime-checker into a performance optimization tool, not a gatekeeper from being able to build at all.
Lifetimes aren’t just about memory management. Iterator invalidation is also a common category of bugs that the borrow checker prevents. Pretty sure the thread safety guarantees also make use of it, to make sure you don’t have any lingering references to data owned by a mutex once you lock it.
Performance isn’t the only part of Rust’s value proposition, and it’s the easiest one to catch up with.
I presume that in the context of this experiment they would write some iterator implementations which don’t become invalid. In a single threaded context this should almost always be possible with some slowdown.
e.g. for a Vec analogue, your iterator keeps an Rc pointer to the Vec, and a current index, and it re checks that the index is still in range on every call to get the next item.
e.g. for a btree analogue, the iterator stores the last retrieved key and the call to get the next item asks the underlying btree for the first item > the last retrived key. Makes iterating a btree O(n*log(n)) instead of O(n) which is a little bit dramatic.
This is kind-of what Objective-C fast enumeration does and it isn’t great for usability. Code will now throw an exception on mutation of the underlying collection and you can’t statically verify that it won’t. Checking that the index is in bounds isn’t sufficient, this can lead to TOCTOU bugs if you check a property of the current element, insert something before it, and then operate on a different object by mistake.
I’ve wondered what an “easy mode” rust would look like.
I don’t feel like cloning and the borrow rules were my main barriers though. If you don’t care about allocations you can approximate a GC-ish approach by cloning all over the place.
The problem with making everything mutable and cloning everywhere all the time is that you lose guarantees. Part of the feedback that I like about rust (after having used it for awhile) is that my type signatures for functions and structs help inform me about the impacts of my design decisions.
Right — I said recently in some other thread that once you start using Rust’s escape hatches like Rc you lose the compile-time checking, which is such an important part of the value proposition.
But if we want GC or RC everywhere we have that already and don’t need rust? Rust is for when you want the control to decide for yourself when that is ok or if it is not
You’d still have a choice — the compiler would only use RC if it couldn’t determine the object’s lifetime statically. There could be an optional compiler flag that raises a warning (or error) when this happens, exactly like those verbose borrow-checker warnings, if you don’t want that to occur.
Or alternatively, the warning/error is on by default but there’s a notation you put in the source code at that spot to say “it’s OK to promote this to RC here if necessary.” (A simple notation that doesn’t require you to change the object’s type or calling convention everywhere!)
This is hand-wavey and maybe impossible, but it’s Sunday morning and a boy can dream.
I am pretty sure that it is not merely possible, but already done 25..30 years ago in Jeffery Mark Suskind’s Stalin - IIRC, his fall back was Boehm-Wiser not RC. (EDIT: His early impls were in the very early 90s as a concept fork from the Dylan effort; “Sta-lin” sort of referenced “static language” or “brutally optimizing” or etc.)
For the annotation version, I guess “just” making Arc<T> more compatible with &mut T basically is this?
I don’t see why one would ever need to get an encrypted message that they are unable to decrypt, while getting ensured that it got encrypted correctly. The article desperately needs a motivation section.
I agree that it’s difficult to think about concrete uses cases, but we do have them! One small correction to your message: you do need to be able to decrypt the message but you don’t want to do that unless it’s an emergency. For example you don’t want to decrypt it since it can be a potential security problem. At the same time you want to be sure that the encryption was correctly done so that when you need to access the message you know it’s there waiting for you.
We will share them it in the future, we need to get approval from one customer.
Is the key getting transmitted or stored through a different channel, then?
Diffie hellman and you can verify the text was encrypted with it
Does the verifier get the prover’s DH share? If not, that then becomes the new key - what happens to that? Otherwise, the verifier is just choosing not to perform the decryption at the moment, and I don’t see how that gives you any security.
Then what guarantees does anyone have that if you decrypted the message, it was indeed an emergency? I don’t see the point.
The important part is to make sure that the message is there when you need it. Opening it if it’s not an emergency isn’t an issue but you don’t gain anything doing that. What you want is to verify that the message was encrypted so that you can open when needed.
As with most cryptographic primitives, they don’t have many uses cases at the beginning until somebody starts using it and shows why they are useful. We already have two uses cases where this will be used in a product. One for a client and another for a product we’re building.
Why even encrypt the message at rest then?
In todays episode of why PBKDF and similar are bad and should be avoided at all costs :-/
What do you consider to be a better alternative?
I’d assume bcrypt and scrypt, which with most implementations setting good input costs per default or as a lower bound (and higher depending on CPU speed). Both bcrypt and scrypt have memory requirements in addition to CPU requirements, making it more costly to use certain hardware such as ASICs and GPUs.
No, bcrypt/scrypt/etc are still fundamentally solving a different problem, and would essentially just be a PBKDF if used as I think you’re suggesting. Obviously using either of these options would be superior to not doing so, but the actual secure solution here is policy-gating via HSM.
the only problem is that the HSM is something you can physically lose, and a passphrase is in your brain forever (modulo amnesia…)
with how Apple/Google sync FIDO2 passkeys between devices, it is a multi-device system that gets the same keys decryptable by multiple HSMs, but (I’m not sure which option they picked tbh, probably the first one?) such a system either is completely non-recoverable if you lose all devices simultaneously, or is doing “normally” (non-HSM) encrypted “cloud” backup.
If you are a company providing a service like last pass, you should not be in a position to lose the HSM
I can’t speak for how google’s passkey syncing works, but I would assume/hope the same as what I’m about to say. Apple’s works over the synchronized keychain mechanism, which is fully end-to-end encrypted with actual random keys, not HSM based (we’ll circle back in a bit). When you add a new device to your apple account, that device has to be approved by one of your other existing devices, and it is that approval that results in your existing device wrapping the account key material to the new device’s keys and sending those wrapped keys to the new device. Once the new device gets that packet it can decrypt the remainder of the keychain material. Each device keeps its own private keys and the account key material protected by the local secure environment.
Note that even the old non-e2e encrypted iCloud backups did not backup keychain material, so compromising the backup infrastructure would not provide access to passwords, passkeys, etc. The concern of course is that for many governments/organisations trawling your back ups is pretty much all that’s wanted, as it just means they have to wait for a backup to happen rather than being able to decrypt in real time. Happily e2e for everything is now an option for apple’s cloud services.
Historically losing your account password (and so resetting the account password is required) would as a byproduct mean losing your synced keychain, so if you didn’t have them locally the data is gone. There is a final ditch backup called something like “iCloud Key Vault” or some such which is the marketing name for large scale and robust HSM setups required given the data being protected. These are policy gated HSMs that devices can back up some core key material to (Ivan Krstic has a blackhat talk from a few years ago that goes over them, but essentially you take a bunch of hsms, get them to all synchronize with each other, then blend the admin cards and have them all roll their internal keys so there is no way to install new software, rely on previously recorded key material, or install compromised hardware into an existing vault).
Oh… you weren’t talking about having the HSM local to the user?? Server side HSM doesn’t seem to make sense to me for a password manager where decryption MUST happen on the client?
There are two levels:
Recovery path - this is an HSM + policy system where the user key material is protected by HSM policy. This is dependent on the HSMs being configured to ensure that the HSM owner does not have access to the HSM’s key material. This is why we talk about an HSM’s security model having to include physical access to the HSM.
Protecting user data: PBKDFs are weak due to generally terrible user provided entropy, so what you do is you receive the user’s data encrypted by the user’s relatively poor entropy. Rather than just storing that, you ask your HSMs to encrypt it with an actual key gated by policy on something like the user’s account password.
The recovery path is obviously optional, but the latter is needed to defend against “hackers downloaded all our user data and that data is protected only by relatively weak entropy”.
The ideal case is a user having multiple devices, and then having new devices receive decryption keys from the existing ones. That means the data that gets uploaded to the servers for syncing are always encrypted with a true random key, and the concept of a “master key” ceases to be relevant.
I’m not suggesting anything. I merely pointed out what I think the person responding probably referred to.
The correct thing to do is to use the password + hsm to policy gate access to the encryption keys, This is how modern devices protect your data.
Your passcode (phone), or password (decent computer/hardcore phone :D), includes an HSM that google calls a hardware backed keystore, and apple calls a Secure Enclave (there’s also the similarly named “Secure Element”, but this is actually another coprocessor that runs a cut down JVM for payments :D).
Anyway, in all implementations the HSMs use internal [generally to the cpu itself] keys. These keys are then used to encrypt all data being stored via the HSM. Retrieving the data is done by providing credentials (your password, etc) to the HSM, the HSM then policy gates access, for example the HSM itself counts attempts and enforces time outs. Because the HSM is performing this gating itself, it doesn’t matter how much cpu power the attacker has: there’s no precomputation, hashing, etc they can do, and having access to the HSM-encrypted data is not brute forceable because the HSM is encrypting with a true random key, not something derived from some kind of guessable password.
If LastPass folk had done this, then downloading the data would have been useless, and a fully local compromise would have still not been able get raw data as the attacker would still be forced to ask the HSM for data by providing username+password combos, and so be subject to the same attempt count and timeout restrictions of a non-local attacker.
Any open source or cheap ham out there?
You really want to avoid cheap ham as It may have parasites :D (Sorry, I recognize the suffering of autocorrect vs. “hsm” :D)
There are two aspects to a commercial HSM (vs say a yubikey):
The first is the software. For this what you want is a very small, very simple OS as an HSM is something where the trade off between entirely verifiable software vs. extra features (you don’t want any software on an HSM that isn’t directly tied to the functions the HSM provides).
Next there’s the hardware. Now this is where things get hard, as an HSM is expected to be secure against a person with physical access, so you have both the electronic design to be aware of, as well as the physical design. Even if someone does have an open source design, the actual manufacture is expensive.- many HSM chips are hardened at a silicon level, with layout and patterning stuff such that the even decapping the chip and then using an electron microscope does not expose the on die data. Suffice to say this means you can’t use an fpga or some generic asic manufacturing, which ramps up the price.
The HSMs are then generally wrapped in many layers of plate steel, etc that can be adhered to various parts of the board so that removing the plates also breaks things (for example cracking various dies, etc).
While writing this I discovered that yubico have started making an “affordable” hsm product at only $650, or $950 with fips certification, which looks like it fulfills the core cryptographic primitives and you’d only have to manage the storage of secured data.
The mention of Intel ME including a JVM got me curious, and following the links seems to lead to some kind of an incomplete archived copy of the relevant website – only the first two slides can be seen.