Live data from Hacker News

Go Cryptography State of the Union

words.filippo.io

41–50 of 69 posts

Re: Go Cryptography State of the Union

#41
post #36

Earlier quoted context omitted.

> I don't know why the standard library crypto packages insist on passing around `[]byte` for things like a seed value These are actually very deliberate choices, based on maybe unintuitive experience. We use []byte instead of e.g. [32]byte because generally you start with a []byte that's coming from somewhere : the network, a file format, a KDF. Then you have two options to get a [32]byte: cast or copy. They both ha…

boggle I’m not a golang programmer, but I find this quite bizarre. Sure, C++ arrays are awful and even std::array may not be able to legally alias a vector. But Rust (no surprise) gets this right — there is a properly fallible conversion from slice reference to array reference. But I guess Go doesn’t. This seems silly to me.

[deleted]

Re: Go Cryptography State of the Union

#44

I agree with the author’s sentiment about FIPS 140. I find NIST to be incredibly slow. I understand there must be some stability, but they are too slow. For example, I think it's horrible that they are still recommending PBKDF2 in 2025.

A big part of the problem I have with it is that it's a "ceiling" on security. Things like electrical code or building code are a "floor" on quality, you have to be at least as good as the code requirements , but can freely be better. FIPS-140 bounds you both ways. If you could more easily do better it'd be much less of a problem that NIST are slow.

I don't love FIPS either, but cryptosystems don't work the same way as buildings and electrical codes. It's very easy to have "secure cryptosystem A" and "secure cryptosystem B", and then have massive security holes in "cryptosystem A + B". This happens all the time, and is one of the main reasons for the classic "don't roll your own crypto" admonition. The FIPS "whole system" mandate is meant to forestall this failure mode.

Re: Go Cryptography State of the Union

#45
post #36

Earlier quoted context omitted.

> I don't know why the standard library crypto packages insist on passing around `[]byte` for things like a seed value These are actually very deliberate choices, based on maybe unintuitive experience. We use []byte instead of e.g. [32]byte because generally you start with a []byte that's coming from somewhere : the network, a file format, a KDF. Then you have two options to get a [32]byte: cast or copy. They both ha…

boggle I’m not a golang programmer, but I find this quite bizarre. Sure, C++ arrays are awful and even std::array may not be able to legally alias a vector. But Rust (no surprise) gets this right — there is a properly fallible conversion from slice reference to array reference. But I guess Go doesn’t. This seems silly to me.

Right now, type casts (called conversions in the spec) always produce a single value. The idiomatic way to have checked casts would IMO be a two-value form, as this would be consistent with type assertions, channel receives, and map indexing, off the top of my head. End result would be something like:

  var x []byte
  y, ok := [32]byte(x)
  // ...
However, it feels like a relatively significant change to the language just for a niche use. Even the ability to cast from []T to [N]T or *[N]T is actually fairly new (Go 1.20 and 1.17, respectively). I don't think it's that hard to check the length before casting, though a checked cast would be convenient since you wouldn't have to repeat the length between the check and the cast.

Re: Go Cryptography State of the Union

#46
post #45
post #36

Earlier quoted context omitted.

boggle I’m not a golang programmer, but I find this quite bizarre. Sure, C++ arrays are awful and even std::array may not be able to legally alias a vector. But Rust (no surprise) gets this right — there is a properly fallible conversion from slice reference to array reference. But I guess Go doesn’t. This seems silly to me.

Right now, type casts (called conversions in the spec) always produce a single value. The idiomatic way to have checked casts would IMO be a two-value form, as this would be consistent with type assertions, channel receives, and map indexing, off the top of my head. End result would be something like: var x []byte y, ok := [32]byte(x) // ... However, it feels like a relatively significant change to the language just…

But it would be a subvariant of a much more common pattern in code - destructuring which is quite noisy now but could just be:

  a, b, rest := strings.Split(somestr, "/")
Which would be conventional for the whole thing, and the check would be for an empty type after rest.

I usually wind up using something like the samber/lo library to reduce the noise here. You wind up doing this all the time.

Re: Go Cryptography State of the Union

#47
post #38

Earlier quoted context omitted.

A big part of the problem I have with it is that it's a "ceiling" on security. Things like electrical code or building code are a "floor" on quality, you have to be at least as good as the code requirements , but can freely be better. FIPS-140 bounds you both ways. If you could more easily do better it'd be much less of a problem that NIST are slow.

In fairness, it's one thing for an implementation like a building to be as over-enginereed as possible in its own right, but it's another when a standard has to ensure that multiple implementations can interoperate. I'm not saying FIPS-140 has only that kind of limitation (far from it), just that this isn't the best analogy.

Is any of FIPS about ensuring interoperability?

Re: Go Cryptography State of the Union

#48
post #46
post #45

Earlier quoted context omitted.

Right now, type casts (called conversions in the spec) always produce a single value. The idiomatic way to have checked casts would IMO be a two-value form, as this would be consistent with type assertions, channel receives, and map indexing, off the top of my head. End result would be something like: var x []byte y, ok := [32]byte(x) // ... However, it feels like a relatively significant change to the language just…

But it would be a subvariant of a much more common pattern in code - destructuring which is quite noisy now but could just be: a, b, rest := strings.Split(somestr, "/") Which would be conventional for the whole thing, and the check would be for an empty type after rest. I usually wind up using something like the samber/lo library to reduce the noise here. You wind up doing this all the time.

I must disagree. Destructuring is nifty, but it is almost completely unrelated. The second value in any of the builtin two-value assignment forms is invariant on the type or size of RHS; it's always a boolean, and its meaning relates to the "kind" of RHS, not the exact type:

  msg, ok := 
This new operation would be similar:

  arr, ok := [N]T(s) // ok means "slice s has len(s) == N"
For all of these cases, ok being true indicates that the other value is safe to use.

Re: Go Cryptography State of the Union

#49
post #47
post #38

Earlier quoted context omitted.

In fairness, it's one thing for an implementation like a building to be as over-enginereed as possible in its own right, but it's another when a standard has to ensure that multiple implementations can interoperate. I'm not saying FIPS-140 has only that kind of limitation (far from it), just that this isn't the best analogy.

Is any of FIPS about ensuring interoperability?

Yeah, there's a ton of correctness testing involved. That's mostly at the algorithm, rather than the module level, so it'll fall under CAVP/ACVP rather than CMVP.

Re: Go Cryptography State of the Union

#50
post #49
post #47

Earlier quoted context omitted.

Is any of FIPS about ensuring interoperability?

Yeah, there's a ton of correctness testing involved. That's mostly at the algorithm, rather than the module level, so it'll fall under CAVP/ACVP rather than CMVP.

That's not for interop, that's for "are you actually doing the crypto you said you'd do". It's designed to prevent broken crypto, not to ensure coordination between parties.
Post reply on HN