Compatibility between golang.org/x/crypto/argon2 and the legacy one

72 views
Skip to first unread message

Thomas Bruyelle

unread,
Oct 11, 2018, 12:37:07 PM10/11/18
to golang-nuts
Hi all,

I want to update my authentication code by using golang.org/x/crypto/argon2, as a replacement of github.com/tvdburgt/go-argon2 which uses the legacy C lib under the hood through CGO.
The main benefit is of course to drop the usage of CGO.

But I encounter a serious issue, with the same inputs (password, salt, times, threads, memory), the 2 libraries give me 2 different hashes. 
That means it's impossible for me to migrate, or else I have to ask all my users to regenerate their passwords, which is not acceptable for me.

I wonder if I did something wrong, to illustrate that I wrote a small test, runnable inside  github.com/tvdburgt/go-argon2 :

package argon2

import (
	"bytes"
	"encoding/base64"
	"testing"

	xargon2 "golang.org/x/crypto/argon2"
)

func TestCompat(t *testing.T) {
	salt := []byte("0123456789abcdef")
	pwd := []byte("some password")

	ctx := &Context{
		Iterations:  3,
		Memory:      1 << 16,
		Parallelism: 4,
		HashLen:     32,
		Mode:        ModeArgon2i,
	}
	hash, err := Hash(ctx, pwd, salt)
	if err != nil {
		t.Fatal(err)
	}

	xhash := xargon2.Key(pwd, salt, 3, 1<<16, 4, 32)

	if !bytes.Equal(hash, xhash) {
		t.Errorf("Compat failed:\n%s\n%s\n",
			base64.StdEncoding.EncodeToString(hash),
			base64.StdEncoding.EncodeToString(xhash),
		)
	}
}
And the result is :
$ go test .
--- FAIL: TestCompat (0.08s)
    compat_test.go:30: Compat failed:
        UgjfozCx6kU6vTNKoN8Ic2UTh7Ckphy0Dc79+1xlT/0=
        mf9LVGs+VH62cWpoLZVfCvtBWye6uMD7sWJfhYQk3fo=
FAIL
FAIL	github.com/tvdburgt/go-argon2	0.362s



Thanks in advance

Sam Whited

unread,
Oct 11, 2018, 1:10:45 PM10/11/18
to golan...@googlegroups.com
On Thu, Oct 11, 2018, at 11:37, Thomas Bruyelle wrote:
> I want to update my authentication code by using
> golang.org/x/crypto/argon2, as a replacement of
> github.com/tvdburgt/go-argon2 which uses the legacy C lib under the hood
> through CGO.
> The main benefit is of course to drop the usage of CGO.
>
> But I encounter a serious issue, with the same inputs (password, salt,
> times, threads, memory), the 2 libraries give me 2 different hashes.
> That means it's impossible for me to migrate, or else I have to ask all my
> users to regenerate their passwords, which is not acceptable for me.

The x/crypto/argon2 package implements version 13, if you add "Version: Version13," to your context they should be the same. The docs claim this is the default for the legacy version, but they appear to be wrong.

—Sam
Message has been deleted

Thomas Bruyelle

unread,
Oct 11, 2018, 2:57:44 PM10/11/18
to golang-nuts
Wow indeed Sam you're completely right, with Version13 the test passes. Thank you a lot for help.

Unfortunately, because of that version mismatch, all my users' hashes were created with a version not supported by golang.org/x/crypto/argon2, so I can't migrate :/

Sam Whited

unread,
Oct 11, 2018, 3:01:10 PM10/11/18
to golan...@googlegroups.com
On Thu, Oct 11, 2018, at 13:56, Thomas Bruyelle wrote:
> Unfortunately, because of that version mismatch, all my users' hashes were
> created with a version not supported by golang.org/x/crypto/argon2, so I
> can't migrate :/

I hope no problems are ever discovered in Argon2 then, it's generally a good idea to have some sort of system for migrating hashes :)

For example, when the user next logs in you could verify that he hash is correct, but also calculate the new hash and update it and set a prefix or a bit in the database somewhere saying that they're on "hash mechanism v2". There's no need to force reset every password all at once since this isn't a security issue.

—Sam

Thomas Bruyelle

unread,
Oct 11, 2018, 3:09:15 PM10/11/18
to Sam Whited, golan...@googlegroups.com
This is brillant, thanks again Sam.
I think I'll go for something like that. The argon2 hash can hold the version, just behind the mode, I could use that to distinguish old and new hash.

$argon2i$v=13$m=65536,t=3,p=4$SZ30vQfC522jpGssj92FkQ$xO4vPBrnd+DW/CbhiGjWW7u0s/nf7PcGUjS5bWQElYo



--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/Lx672zPwqSQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Thomas Bruyelle

unread,
Oct 11, 2018, 3:15:07 PM10/11/18
to Sam Whited, golan...@googlegroups.com
That say, the downside is I have to keep both hash system, until all users connect, which can take a long time, or can never happen!

Sam Whited

unread,
Oct 11, 2018, 3:28:32 PM10/11/18
to golan...@googlegroups.com
On Thu, Oct 11, 2018, at 14:14, Thomas Bruyelle wrote:
> That say, the downside is I have to keep both hash system, until all users
> connect, which can take a long time, or can never happen!

Or at least until enough users have updated that you don't mind forcing the rest to update their password if they ever log in again.

—Sam

Thomas Bruyelle

unread,
Oct 11, 2018, 3:31:44 PM10/11/18
to Sam Whited, golan...@googlegroups.com
Yes, that's acceptable.

Reply all
Reply to author
Forward
0 new messages