Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
  • renovate/github.com-duo-labs-webauthn-digest
  • renovate/github.com-go-ldap-ldap-v3-3.x
  • renovate/github.com-go-webauthn-webauthn-0.x
  • renovate/github.com-google-go-cmp-0.x
  • renovate/github.com-lunixbochs-struc-digest
  • renovate/github.com-mattn-go-sqlite3-1.x
  • renovate/github.com-prometheus-client_golang-1.x
  • renovate/go-1.x
  • renovate/golang.org-x-crypto-0.x
  • renovate/golang.org-x-sync-0.x
  • renovate/opentelemetry-go-monorepo
12 results

Target

Select target project
  • ai3/go-common
1 result
Select Git revision
  • master
  • renovate/github.com-duo-labs-webauthn-digest
  • renovate/github.com-go-ldap-ldap-v3-3.x
  • renovate/github.com-go-webauthn-webauthn-0.x
  • renovate/github.com-google-go-cmp-0.x
  • renovate/github.com-lunixbochs-struc-digest
  • renovate/github.com-mattn-go-sqlite3-1.x
  • renovate/github.com-prometheus-client_golang-1.x
  • renovate/go-1.x
  • renovate/golang.org-x-crypto-0.x
  • renovate/golang.org-x-sync-0.x
  • renovate/opentelemetry-go-monorepo
12 results
Show changes
Commits on Source (4)
......@@ -86,7 +86,7 @@ func mkhash() (pwhash.PasswordHash, string, error) {
name := *algo
switch *algo {
case "argon2":
h = pwhash.NewArgon2WithParams(uint32(*argon2Time), uint32(*argon2Mem*1024), uint8(*argon2Threads))
h = pwhash.NewArgon2StdWithParams(uint32(*argon2Time), uint32(*argon2Mem*1024), uint8(*argon2Threads))
name = fmt.Sprintf("%s(%d/%d/%d)", *algo, *argon2Time, *argon2Mem, *argon2Threads)
case "scrypt":
h = pwhash.NewScryptWithParams(*scryptN, *scryptR, *scryptP)
......
module git.autistici.org/ai3/go-common
go 1.21.0
go 1.22.0
toolchain go1.23.1
toolchain go1.24.1
require (
github.com/NYTimes/gziphandler v1.1.1
......@@ -16,18 +16,18 @@ require (
github.com/go-ldap/ldap/v3 v3.4.8
github.com/go-webauthn/webauthn v0.10.2
github.com/gofrs/flock v0.12.1
github.com/google/go-cmp v0.6.0
github.com/google/go-cmp v0.7.0
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
github.com/mattn/go-sqlite3 v1.14.23
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75
github.com/prometheus/client_golang v1.20.3
github.com/russross/blackfriday/v2 v2.1.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.34.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0
go.opentelemetry.io/contrib/propagators/b3 v1.9.0
go.opentelemetry.io/otel v1.10.0
go.opentelemetry.io/otel v1.35.0
go.opentelemetry.io/otel/exporters/zipkin v1.9.0
go.opentelemetry.io/otel/sdk v1.10.0
go.opentelemetry.io/otel/trace v1.10.0
go.opentelemetry.io/otel/sdk v1.35.0
go.opentelemetry.io/otel/trace v1.35.0
golang.org/x/crypto v0.27.0
golang.org/x/sync v0.8.0
)
......@@ -36,8 +36,8 @@ require (
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-webauthn/x v0.1.9 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
......@@ -53,7 +53,8 @@ require (
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.opentelemetry.io/otel/metric v0.31.0 // indirect
golang.org/x/sys v0.25.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
golang.org/x/sys v0.30.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
)
......@@ -91,6 +91,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
......@@ -120,6 +122,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
......@@ -178,6 +182,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk=
github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
......@@ -347,20 +353,32 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.34.0 h1:9NkMW03wwEzPtP/KciZ4Ozu/Uz5ZA7kfqXJIObnrjGU=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.34.0/go.mod h1:548ZsYzmT4PL4zWKRd8q/N4z0Wxzn/ZxUE+lkEpwWQA=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
go.opentelemetry.io/contrib/propagators/b3 v1.9.0 h1:Lzb9zU98jCE2kyfCjWfSSsiQoGtvBL+COxvUBf7FNhU=
go.opentelemetry.io/contrib/propagators/b3 v1.9.0/go.mod h1:fyx3gFXn+4w5uWTTiqaI8oBNBW/6w9Ow5zxXf7NGixU=
go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4=
go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ=
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
go.opentelemetry.io/otel/exporters/zipkin v1.9.0 h1:06b/nt6xao6th00aue9WU3ZDTTe+InaMXA/vym6pLuA=
go.opentelemetry.io/otel/exporters/zipkin v1.9.0/go.mod h1:HyIvYIu37wV4Wx5azd7e05x9k/dOz9KB4x0plw2QNvs=
go.opentelemetry.io/otel/metric v0.31.0 h1:6SiklT+gfWAwWUR0meEMxQBtihpiEs4c+vL9spDTqUs=
go.opentelemetry.io/otel/metric v0.31.0/go.mod h1:ohmwj9KTSIeBnDBm/ZwH2PSZxZzoOaG2xZeekTRzL5A=
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
go.opentelemetry.io/otel/sdk v1.10.0 h1:jZ6K7sVn04kk/3DNUdJ4mqRlGDiXAVuIG+MMENpTNdY=
go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE=
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E=
go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM=
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
......@@ -523,6 +541,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
......
......@@ -6,15 +6,15 @@ import (
"encoding/hex"
"errors"
"fmt"
"log"
"strconv"
"strings"
"golang.org/x/crypto/argon2"
)
var (
argonKeyLen uint32 = 32
const (
argonLegacyKeySize = 32
argonDefaultKeySize = 16
argonSaltLen = 16
)
......@@ -29,9 +29,11 @@ type argon2PasswordHash struct {
// newArgon2PasswordHash returns an Argon2i-based PasswordHash using the
// specified parameters for time, memory, and number of threads.
func newArgon2PasswordHash(time, mem uint32, threads uint8, codec argon2Codec) PasswordHash {
func newArgon2PasswordHash(kind string, keySize int, time, mem uint32, threads uint8, codec argon2Codec) PasswordHash {
return &argon2PasswordHash{
params: argon2Params{
KeySize: keySize,
Kind: kind,
Time: time,
Memory: mem,
Threads: threads,
......@@ -41,8 +43,8 @@ func newArgon2PasswordHash(time, mem uint32, threads uint8, codec argon2Codec) P
}
// NewArgon2 returns an Argon2i-based PasswordHash using the default parameters.
func NewArgon2() PasswordHash {
return NewArgon2WithParams(
func NewArgon2Legacy() PasswordHash {
return NewArgon2LegacyWithParams(
defaultArgon2Params.Time,
defaultArgon2Params.Memory,
defaultArgon2Params.Threads,
......@@ -51,8 +53,8 @@ func NewArgon2() PasswordHash {
// NewArgon2WithParams returns an Argon2i-based PasswordHash using the
// specified parameters for time, memory, and number of threads.
func NewArgon2WithParams(time, mem uint32, threads uint8) PasswordHash {
return newArgon2PasswordHash(time, mem, threads, &a2Codec{})
func NewArgon2LegacyWithParams(time, mem uint32, threads uint8) PasswordHash {
return newArgon2PasswordHash(kindArgon2I, argonLegacyKeySize, time, mem, threads, &a2LegacyCodec{})
}
// NewArgon2Std returns an Argon2i-based PasswordHash that conforms
......@@ -65,12 +67,12 @@ func NewArgon2Std() PasswordHash {
)
}
// NewArgon2StdWithParams returns an Argon2i-based PasswordHash using
// NewArgon2StdWithParams returns an Argon2id-based PasswordHash using
// the specified parameters for time, memory, and number of
// threads. This will use the string encoding ("$argon2$") documented
// threads. This will use the string encoding ("$argon2id$") documented
// in the argon2 reference implementation.
func NewArgon2StdWithParams(time, mem uint32, threads uint8) PasswordHash {
return newArgon2PasswordHash(time, mem, threads, &argon2StdCodec{})
return newArgon2PasswordHash(kindArgon2ID, argonDefaultKeySize, time, mem, threads, &argon2StdCodec{})
}
// ComparePassword returns true if the given password matches the
......@@ -80,28 +82,53 @@ func (s *argon2PasswordHash) ComparePassword(encrypted, password string) bool {
if err != nil {
return false
}
dk2 := argon2.Key([]byte(password), salt, params.Time, params.Memory, params.Threads, argonKeyLen)
dk2 := params.hash(password, salt)
return subtle.ConstantTimeCompare(dk, dk2) == 1
}
// Encrypt the given password with the Argon2 algorithm.
func (s *argon2PasswordHash) Encrypt(password string) string {
salt := getRandomBytes(argonSaltLen)
dk := argon2.Key([]byte(password), salt, s.params.Time, s.params.Memory, s.params.Threads, argonKeyLen)
dk := s.params.hash(password, salt)
return s.codec.encodeArgon2Hash(s.params, salt, dk)
}
const (
kindArgon2I = "argon2i"
kindArgon2ID = "argon2id"
)
type argon2Params struct {
Kind string
KeySize int
Time uint32
Memory uint32
Threads uint8
}
func (p argon2Params) hash(password string, salt []byte) []byte {
if p.KeySize == 0 {
panic("key size is 0")
}
switch p.Kind {
case kindArgon2I:
return argon2.Key([]byte(password), salt, p.Time, p.Memory, p.Threads, uint32(p.KeySize))
case kindArgon2ID:
return argon2.IDKey([]byte(password), salt, p.Time, p.Memory, p.Threads, uint32(p.KeySize))
default:
panic("unknown argon2 hash kind")
}
}
// Default Argon2 parameters are tuned for a high-traffic
// authentication service (<1ms per operation).
var defaultArgon2Params = argon2Params{
Kind: kindArgon2ID,
KeySize: 16,
Time: 1,
Memory: 4 * 1024,
Memory: 64 * 1024,
Threads: 4,
}
......@@ -110,13 +137,14 @@ type argon2Codec interface {
decodeArgon2Hash(string) (argon2Params, []byte, []byte, error)
}
type a2Codec struct{}
// Argon2i legacy encoding, do not use.
type a2LegacyCodec struct{}
func (*a2Codec) encodeArgon2Hash(params argon2Params, salt, dk []byte) string {
func (*a2LegacyCodec) encodeArgon2Hash(params argon2Params, salt, dk []byte) string {
return fmt.Sprintf("$a2$%d$%d$%d$%x$%x", params.Time, params.Memory, params.Threads, salt, dk)
}
func (*a2Codec) decodeArgon2Hash(s string) (params argon2Params, salt []byte, dk []byte, err error) {
func (*a2LegacyCodec) decodeArgon2Hash(s string) (params argon2Params, salt []byte, dk []byte, err error) {
if !strings.HasPrefix(s, "$a2$") {
err = errors.New("not an Argon2 password hash")
return
......@@ -128,6 +156,8 @@ func (*a2Codec) decodeArgon2Hash(s string) (params argon2Params, salt []byte, dk
return
}
params.Kind = kindArgon2I
var i uint64
if i, err = strconv.ParseUint(parts[0], 10, 32); err != nil {
......@@ -149,16 +179,36 @@ func (*a2Codec) decodeArgon2Hash(s string) (params argon2Params, salt []byte, dk
if err != nil {
return
}
dk, err = hex.DecodeString(parts[4])
if err != nil {
return
}
params.KeySize = len(dk)
switch len(dk) {
case 16, 24, 32:
default:
err = errors.New("bad key size")
}
return
}
// Standard Argon2 encoding as per the reference implementation in
// https://github.com/P-H-C/phc-winner-argon2/blob/4ac8640c2adc1257677d27d3f833c8d1ee68c7d2/src/encoding.c#L242-L252
type argon2StdCodec struct{}
const argon2HashVersionStr = "v=19"
func (*argon2StdCodec) encodeArgon2Hash(params argon2Params, salt, dk []byte) string {
encSalt := base64.RawStdEncoding.EncodeToString(salt)
encDK := base64.RawStdEncoding.EncodeToString(dk)
return fmt.Sprintf("$argon2i$v=19$m=%d,t=%d,p=%d$%s$%s", params.Memory, params.Time, params.Threads, encSalt, encDK)
return fmt.Sprintf(
"$%s$%s$m=%d,t=%d,p=%d$%s$%s",
params.Kind, argon2HashVersionStr,
params.Memory, params.Time, params.Threads,
encSalt, encDK)
}
func parseArgon2HashParams(s string) (params argon2Params, err error) {
......@@ -182,7 +232,7 @@ func parseArgon2HashParams(s string) (params argon2Params, err error) {
i, err = strconv.ParseUint(kv[1], 10, 8)
params.Threads = uint8(i)
default:
err = errors.New("unknown parameter in hash")
err = fmt.Errorf("unknown parameter '%s' in hash", kv[0])
}
if err != nil {
return
......@@ -192,30 +242,46 @@ func parseArgon2HashParams(s string) (params argon2Params, err error) {
}
func (*argon2StdCodec) decodeArgon2Hash(s string) (params argon2Params, salt []byte, dk []byte, err error) {
if !strings.HasPrefix(s, "$argon2i$") {
var kind string
switch {
case strings.HasPrefix(s, "$argon2i$"):
kind = kindArgon2I
case strings.HasPrefix(s, "$argon2id$"):
kind = kindArgon2ID
default:
err = errors.New("not an Argon2 password hash")
return
}
parts := strings.SplitN(s[9:], "$", 4)
if len(parts) != 4 {
parts := strings.SplitN(s, "$", 6)
if len(parts) != 6 {
err = errors.New("bad encoding")
return
}
if parts[0] != "v=19" {
if parts[2] != argon2HashVersionStr {
err = errors.New("bad argon2 hash version")
return
}
params, err = parseArgon2HashParams(parts[1])
params, err = parseArgon2HashParams(parts[3])
if err != nil {
return
}
if salt, err = base64.RawStdEncoding.DecodeString(parts[2]); err != nil {
params.Kind = kind
if salt, err = base64.RawStdEncoding.DecodeString(parts[4]); err != nil {
return
}
if dk, err = base64.RawStdEncoding.DecodeString(parts[5]); err != nil {
return
}
dk, err = base64.RawStdEncoding.DecodeString(parts[3])
log.Printf("params: %+v", params)
params.KeySize = len(dk)
switch len(dk) {
case 16, 24, 32:
default:
err = errors.New("bad key size")
}
return
}
......@@ -4,7 +4,7 @@
// The format is the well-known dollar-separated field string,
// extended with optional algorithm-specific parameters:
//
// $id[$params...]$salt$encrypted
// $id[$params...]$salt$encrypted
//
// We extend 'id' beyond the values supported by the libc crypt(3)
// function with the following hashing algorithms:
......@@ -16,9 +16,8 @@
// the parameterized benchmarks are named with
// time/memory(MB)/threads. For nicer results:
//
// go test -bench=Argon2 -run=none . 2>&1 | \
// awk '/^Bench/ {ops=1000000000 / $3; print $1 " " ops " ops/sec"}'
//
// go test -bench=Argon2 -run=none . 2>&1 | \
// awk '/^Bench/ {ops=1000000000 / $3; print $1 " " ops " ops/sec"}'
package pwhash
import (
......@@ -49,12 +48,13 @@ func getRandomBytes(n int) []byte {
// A registry of default handlers for decoding passwords.
var prefixRegistry = map[string]PasswordHash{
"$1$": NewSystemCrypt(),
"$5$": NewSystemCrypt(),
"$6$": NewSystemCrypt(),
"$s$": NewScrypt(),
"$a2$": NewArgon2(),
"$argon2i$": NewArgon2Std(),
"$1$": NewSystemCrypt(),
"$5$": NewSystemCrypt(),
"$6$": NewSystemCrypt(),
"$s$": NewScrypt(),
"$a2$": NewArgon2Legacy(),
"$argon2i$": NewArgon2Std(),
"$argon2id$": NewArgon2Std(),
}
// ComparePassword returns true if the given password matches the
......@@ -65,6 +65,7 @@ func ComparePassword(encrypted, password string) bool {
return h.ComparePassword(encrypted, password)
}
}
return false
}
......@@ -73,7 +74,7 @@ func ComparePassword(encrypted, password string) bool {
var DefaultEncryptAlgorithm PasswordHash
func init() {
DefaultEncryptAlgorithm = NewArgon2()
DefaultEncryptAlgorithm = NewArgon2Std()
}
// Encrypt will encrypt a password with the default algorithm.
......
......@@ -5,8 +5,8 @@ import (
"testing"
)
func TestArgon2(t *testing.T) {
testImpl(t, NewArgon2())
func TestArgon2Legacy(t *testing.T) {
testImpl(t, NewArgon2Legacy())
}
func TestArgon2Std(t *testing.T) {
......@@ -65,7 +65,7 @@ func testImpl(t *testing.T, h PasswordHash) {
}
}
func TestStandardArgon2Password(t *testing.T) {
func TestStandardArgon2IPassword(t *testing.T) {
enc := "$argon2i$v=19$m=32768,t=4,p=1$DG0B56zlrrx+VMVaM6wvsw$8iV+HwTKmofjrb+q9I2zZGQnGXzXtiIXv8VdHdvbbX8"
pw := "idontmindbirds"
if !ComparePassword(enc, pw) {
......@@ -73,6 +73,15 @@ func TestStandardArgon2Password(t *testing.T) {
}
}
func TestStandardArgon2IDPassword(t *testing.T) {
// python3 -c 'from argon2 import PasswordHasher ; print(PasswordHasher().hash("idontmindbirds"))'
enc := "$argon2id$v=19$m=102400,t=2,p=8$7hQLBrHoxYxRO0R8km62pA$Dv5+BCctW4nCrxsy5C9JBg"
pw := "idontmindbirds"
if !ComparePassword(enc, pw) {
t.Fatal("comparison failed")
}
}
func BenchmarkArgon2(b *testing.B) {
var testParams []argon2Params
for iTime := 1; iTime <= 5; iTime++ {
......@@ -93,7 +102,7 @@ func BenchmarkArgon2(b *testing.B) {
for _, tp := range testParams {
name := fmt.Sprintf("%d/%d/%d", tp.Time, tp.Memory, tp.Threads)
b.Run(name, func(b *testing.B) {
h := NewArgon2WithParams(tp.Time, tp.Memory, tp.Threads)
h := NewArgon2StdWithParams(tp.Time, tp.Memory, tp.Threads)
encPw := h.Encrypt(goodPw)
b.ResetTimer()
......