Live data from Hacker News

How I implemented my own crypto

loup-vaillant.fr

91–100 of 409 posts

Re: How I implemented my own crypto

#91

    found an error in the Argon2 reference implementation.
This is exactly why I like as many people writing crypto as possible[0]. Bugs like the one the writer found show up in reference implementations, and are found by absolutely no one unless someone writes an alternate implementation that behaves differently.

Edit: A further example, a lot of people write crypto as part of various CTFs. This is a case of "writing crypto" that poses no threat to the community.

[0] That doesn't mean they should use it in production.

Re: How I implemented my own crypto

#92
post #27

First let me say that I've followed your work a bit and I'm really impressed with the library. I'm currently planning on rolling my own crypto as well and your library is on my list of the things to look at. One question: > I was shifting a uint8_t, 24 bits to the left. I failed to realise that integer promotion means this unsigned byte would be converted to a signed integer, and overflow if the byte exceeded 127. Th…

I believe this[1] is the patch that fixes this bug. I tried to reproduce the behavior but couldn't succeed. Maybe I was doing something wrong. Would really appreciate it if someone here could show a test case where this matters. [1] https://github.com/LoupVaillant/Monocypher/commit/347189c50c...

Your failure to reproduce the behaviour is normal: on the compilers I have tested, this doesn't affect the generated binary.

To see the difference, you need to first modify the makefile to use UBSan instead of just GCC (just comment the active CC line, and uncomment the right one). You may want to tone down the optimisations for faster compilation as well. Then you can run `make clean` and `./test.sh`. You should have a warning on commits prior to this patch.

Re: How I implemented my own crypto

#94
Whenever I feel the need for a tin foil hat I start to wonder if there is a FUD campaign powered by the "establishment" to encourage people not to investigate this area of computer science so that security holes will remain unnoticed.

But, yes I wouldn't start out on writing a crypto library, then again I wouldn't attempt to build an OS or a 3D stack or even an web server either. All cases where a security breach could have devastating effects as well.

Re: How I implemented my own crypto

#95
post #27

First let me say that I've followed your work a bit and I'm really impressed with the library. I'm currently planning on rolling my own crypto as well and your library is on my list of the things to look at. One question: > I was shifting a uint8_t, 24 bits to the left. I failed to realise that integer promotion means this unsigned byte would be converted to a signed integer, and overflow if the byte exceeded 127. Th…

There's no sign-extension involved. Let's say the input is (uint8_t)128. This gets promoted to (int)128, which is then shifted 24 bits to the left. If the input was (int8_t)128, it would get sign-extended into (int)-128, but that is not the case here.

With 32-bit ints, this operation will result in 0x80000000, shifting a bit into the sign bit, which constitutes an overflow (and undefined behavior). Think about it in terms of multiplication: you're multiplying a positive integer by 2^24, and it turns out negative!

Re: How I implemented my own crypto

#96
post #79

Earlier quoted context omitted.

6.5.7 Bitwise shift operators > Each of the operands shall have integer type. > The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. 6.3.1.1 § 2 > If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called th…

is it doing a sign extension though? If it promotes without adding a bunch of 1s it should be fine.

It's probably the latter part (conversion to "whatever the expression's type ends up being) doing the sign-extension, see moefh's sibling comment with a uint64_t final destination, the int -> uint64_t is sign-extending.

I should have quoted the proper part I was replying to ("I don't think you're talking about integer promotion here")

Re: How I implemented my own crypto

#97
post #26

Earlier quoted context omitted.

> Haskell I think writing timing-attack resistant code in Haskell would be very hard to impossible, at least without writing very unidiomatic code (basically "C in Haskell"). I'm happy to be proven wrong, though.

Honest question: What makes you think you can't mitigate? A̶ ̶t̶y̶p̶e̶s̶a̶f̶e̶ ̶c̶r̶y̶p̶t̶o̶ ̶t̶h̶a̶t̶ ̶m̶e̶a̶s̶u̶r̶e̶s̶ ̶i̶t̶s̶ ̶e̶x̶e̶c̶u̶t̶i̶o̶n̶ ̶t̶i̶m̶e̶ ̶a̶p̶p̶e̶n̶d̶e̶d̶ ̶w̶i̶t̶h̶ ̶a̶ ̶f̶i̶n̶a̶l̶ ̶d̶e̶l̶a̶y̶ ̶t̶i̶m̶e̶ ̶r̶e̶a̶d̶ ̶f̶r̶o̶m̶ ̶/̶d̶e̶v̶/̶u̶r̶a̶n̶d̶o̶m̶ ̶c̶a̶n̶ ̶s̶t̶i̶l̶l̶ ̶b̶e̶ ̶i̶d̶i̶o̶m̶a̶t̶i̶c̶.̶ It has to be monadic, that is for sure but abstracting a crypto algorithm as IO is actually treating…

Random delays do not protect against timing attacks. Best thing it can do, is to force the attacker to collect a few more timing samples. (To the point where the the random noise averages itself out.)

Re: How I implemented my own crypto

#98
post #36

I'm amazed that the reference implementation of Argon2 had a bug. So that means anyone who deployed Argon2 today didn't really use Argon2 (I'm being pedantic), but something else? libsodium also got it wrong, so that brought down my opinion of it being a trusted and well-reviewed library. Now the question is, will they continue to use the same implementation or move to the fixed code?

Maybe the authors will fix the code in subsequent versions of Argon2. Right now, backward compatibility is deemed more important. The effects of this bug are practically negligible anyway. I bet a single bit of additional entropy in a password would compensate that a hundred fold.

I'm a bit disappointed however at their not updating the specs. I signalled the bug in January, and the latest version of the appear to have been published in March. I guess they had other priorities.

Don't be too hard on Libsodium: they only got it wrong because they reused the reference implementation. (Also, I don't see them breaking backward compatibility either.)

Re: How I implemented my own crypto

#99
post #31

Earlier quoted context omitted.

Curious about the other language. What other language that doesn't add another layer between the code and system instructions were you thinking about?

Most programming languages with compilers to native code (JIT/AOT), the myth of high level Assembler for C only applies if your computer is a PDP-11 or a basic 8-bit CPU like a 6502 or Z80. The ANSI C and C++ standards define the concept of abstract machine for the language semantics, just like in most languages. Additionally you have the concepts of sequence points, the new memory model semantics for multi-threaded…

The ARM Architecture Reference Manuals are full of "if you do X, the instruction is UNPREDICTABLE".

Re: How I implemented my own crypto

#100
post #51
post #14

Earlier quoted context omitted.

> Look at any mature C project and see the layers and layers of macros and hacks to make things portable. So.. it's portable, then?

We've had to wait till C99 to get stdint.h, clearly portability is kind of an afterthought in C. C is meant to map easily to a wide range of hardware without overhead, conceptually it's almost the opposite of portability since it precludes creating standard abstractions that would hold true across architectures as those could not map to native functionality across the board. It's easy to compile C programs on a diffe…

> We've had to wait till C99 to get stdint.h, clearly portability is kind of an afterthought in C.

C provided "at least N bits" guarantees for its integer types since its first standard (for the curious: char at least 8-bit, short at least 16-bit, long at least 32-bit; in C99, long long as least 64-bit). This is the most that you can get if you want absolute portability, because there are architectures out there where you simply can't address memory in, say, 8-bit chunks (see SHARC for an example).

Consequently, while stdint.h defines types like int32_t, they are "conditionally supported", and so a C program that has a hard dependency on them is not universally portable. Types like int32_least_t and int32_fast_t are unconditionally supported, but they don't give you anything that you didn't have before.

Post reply on HN