Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 11, 19:45 UTC
basicauth: Implement argon2id (#7186)
* feat: add argon2id hash-password command * feat: ardon2id owasp safe value * feat: add argon2id compare method * chore: fmt argon2id * docs: more argon2id docs * chore: upgrade x/crypto dep * revert: remove golangci * refactor: argon2id decode * chore: update deps * refactor: simplify argon2id compare return * chore: upgrade dependencies * chore: upgrade dependencies
GreyXor committed
Oct 7, 2025 at 01:27 UTC
13a4ec7597f8e9ebe105b0ee89102ba521f21173
6 files changed
+303
-57
go.mod
+14
-14
@@ -37,12 +37,12 @@ require (
37
go.uber.org/automaxprocs v1.6.0
38
go.uber.org/zap v1.27.0
39
go.uber.org/zap/exp v0.3.0
40
- golang.org/x/crypto v0.41.0
41
- golang.org/x/crypto/x509roots/fallback v0.0.0-20250305170421-49bf5b80c810
42
- golang.org/x/net v0.43.0
43
- golang.org/x/sync v0.16.0
44
- golang.org/x/term v0.34.0
45
- golang.org/x/time v0.12.0
40
+ golang.org/x/crypto v0.42.0
41
+ golang.org/x/crypto/x509roots/fallback v0.0.0-20250927194341-2beaa59a3c99
42
+ golang.org/x/net v0.44.0
43
+ golang.org/x/sync v0.17.0
44
+ golang.org/x/term v0.35.0
45
+ golang.org/x/time v0.13.0
46
gopkg.in/natefinch/lumberjack.v2 v2.2.1
47
gopkg.in/yaml.v3 v3.0.1
48
)
@@ -90,11 +90,11 @@ require (
90
go.opentelemetry.io/contrib/propagators/jaeger v1.38.0 // indirect
91
go.opentelemetry.io/contrib/propagators/ot v1.38.0 // indirect
92
go.uber.org/mock v0.5.2 // indirect
93
- golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
93
+ golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect
94
golang.org/x/oauth2 v0.30.0 // indirect
95
google.golang.org/api v0.247.0 // indirect
96
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
97
- google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
97
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 // indirect
98
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 // indirect
99
)
100
@@ -153,11 +153,11 @@ require (
153
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
154
go.step.sm/crypto v0.70.0
155
go.uber.org/multierr v1.11.0 // indirect
156
- golang.org/x/mod v0.26.0 // indirect
157
- golang.org/x/sys v0.35.0
158
- golang.org/x/text v0.28.0 // indirect
159
- golang.org/x/tools v0.35.0 // indirect
160
- google.golang.org/grpc v1.75.0 // indirect
161
- google.golang.org/protobuf v1.36.8 // indirect
156
+ golang.org/x/mod v0.27.0 // indirect
157
+ golang.org/x/sys v0.36.0
158
+ golang.org/x/text v0.29.0 // indirect
159
+ golang.org/x/tools v0.36.0 // indirect
160
+ google.golang.org/grpc v1.75.1 // indirect
161
+ google.golang.org/protobuf v1.36.10 // indirect
162
howett.net/plist v1.0.0 // indirect
163
)
go.sum
+28
-28
@@ -502,13 +502,13 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
502
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
503
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
504
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
505
-golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
506
-golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
507
-golang.org/x/crypto/x509roots/fallback v0.0.0-20250305170421-49bf5b80c810 h1:V5+zy0jmgNYmK1uW/sPpBw8ioFvalrhaUrYWmu1Fpe4=
508
-golang.org/x/crypto/x509roots/fallback v0.0.0-20250305170421-49bf5b80c810/go.mod h1:lxN5T34bK4Z/i6cMaU7frUU57VkDXFD4Kamfl/cp9oU=
505
+golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
506
+golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
507
+golang.org/x/crypto/x509roots/fallback v0.0.0-20250927194341-2beaa59a3c99 h1:CH0o4/bZX6KIUCjjgjmtNtfM/kXSkTYlzTOB9vZF45g=
508
+golang.org/x/crypto/x509roots/fallback v0.0.0-20250927194341-2beaa59a3c99/go.mod h1:MEIPiCnxvQEjA4astfaKItNwEVZA5Ki+3+nyGbJ5N18=
509
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
510
-golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
511
-golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
510
+golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 h1:SbTAbRFnd5kjQXbczszQ0hdk3ctwYf3qBNH9jIsGclE=
511
+golang.org/x/exp v0.0.0-20250813145105-42675adae3e6/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
512
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
513
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
514
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -517,8 +517,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
517
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
518
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
519
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
520
-golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
521
-golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
520
+golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
521
+golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
522
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
523
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
524
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -535,8 +535,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
535
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
536
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
537
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
538
-golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
539
-golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
538
+golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
539
+golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
540
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
541
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
542
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -556,8 +556,8 @@ golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
556
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
557
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
558
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
559
-golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
560
-golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
559
+golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
560
+golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
561
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
562
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
563
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -582,8 +582,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
582
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
583
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
584
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
585
-golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
586
-golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
585
+golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
586
+golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
587
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
588
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
589
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -594,8 +594,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
594
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
595
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
596
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
597
-golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
598
-golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
597
+golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
598
+golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
599
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
600
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
601
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -607,12 +607,12 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
607
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
608
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
609
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
610
-golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
611
-golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
610
+golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
611
+golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
612
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
613
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
614
-golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
615
-golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
614
+golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI=
615
+golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
616
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
617
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
618
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -623,8 +623,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
623
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
624
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
625
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
626
-golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
627
-golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
626
+golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
627
+golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
628
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
629
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
630
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
@@ -646,18 +646,18 @@ google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuO
646
google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s=
647
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
648
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
649
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE=
650
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc=
649
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 h1:CirRxTOwnRWVLKzDNrs0CXAaVozJoR4G9xvdRecrdpk=
650
+google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ=
651
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
652
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
653
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
654
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
655
-google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
656
-google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
655
+google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
656
+google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
657
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A=
658
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA=
659
-google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
660
-google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
659
+google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
660
+google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
661
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
662
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
663
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
modules/caddyhttp/caddyauth/argon2id.go
new
+188
@@ -0,0 +1,188 @@
1
+// Copyright 2015 Matthew Holt and The Caddy Authors
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License");
4
+// you may not use this file except in compliance with the License.
5
+// You may obtain a copy of the License at
6
+//
7
+// http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS,
11
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+// See the License for the specific language governing permissions and
13
+// limitations under the License.
14
+
15
+package caddyauth
16
+
17
+import (
18
+ "crypto/rand"
19
+ "crypto/subtle"
20
+ "encoding/base64"
21
+ "fmt"
22
+ "strconv"
23
+ "strings"
24
+
25
+ "golang.org/x/crypto/argon2"
26
+
27
+ "github.com/caddyserver/caddy/v2"
28
+)
29
+
30
+func init() {
31
+ caddy.RegisterModule(Argon2idHash{})
32
+}
33
+
34
+const (
35
+ argon2idName = "argon2id"
36
+ defaultArgon2idTime = 1
37
+ defaultArgon2idMemory = 46 * 1024
38
+ defaultArgon2idThreads = 1
39
+ defaultArgon2idKeylen = 32
40
+ defaultSaltLength = 16
41
+)
42
+
43
+// Argon2idHash implements the Argon2id password hashing.
44
+type Argon2idHash struct {
45
+ salt []byte
46
+ time uint32
47
+ memory uint32
48
+ threads uint8
49
+ keyLen uint32
50
+}
51
+
52
+// CaddyModule returns the Caddy module information.
53
+func (Argon2idHash) CaddyModule() caddy.ModuleInfo {
54
+ return caddy.ModuleInfo{
55
+ ID: "http.authentication.hashes.argon2id",
56
+ New: func() caddy.Module { return new(Argon2idHash) },
57
+ }
58
+}
59
+
60
+// Compare checks if the plaintext password matches the given Argon2id hash.
61
+func (Argon2idHash) Compare(hashed, plaintext []byte) (bool, error) {
62
+ argHash, storedKey, err := DecodeHash(hashed)
63
+ if err != nil {
64
+ return false, err
65
+ }
66
+
67
+ computedKey := argon2.IDKey(
68
+ plaintext,
69
+ argHash.salt,
70
+ argHash.time,
71
+ argHash.memory,
72
+ argHash.threads,
73
+ argHash.keyLen,
74
+ )
75
+
76
+ return subtle.ConstantTimeCompare(storedKey, computedKey) == 1, nil
77
+}
78
+
79
+// Hash generates an Argon2id hash of the given plaintext using the configured parameters and salt.
80
+func (b Argon2idHash) Hash(plaintext []byte) ([]byte, error) {
81
+ if b.salt == nil {
82
+ s, err := generateSalt(defaultSaltLength)
83
+ if err != nil {
84
+ return nil, err
85
+ }
86
+ b.salt = s
87
+ }
88
+
89
+ key := argon2.IDKey(
90
+ plaintext,
91
+ b.salt,
92
+ b.time,
93
+ b.memory,
94
+ b.threads,
95
+ b.keyLen,
96
+ )
97
+
98
+ hash := fmt.Sprintf(
99
+ "$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s",
100
+ argon2.Version,
101
+ b.memory,
102
+ b.time,
103
+ b.threads,
104
+ base64.RawStdEncoding.EncodeToString(b.salt),
105
+ base64.RawStdEncoding.EncodeToString(key),
106
+ )
107
+
108
+ return []byte(hash), nil
109
+}
110
+
111
+// DecodeHash parses an Argon2id PHC string into an Argon2idHash struct and returns the struct along with the derived key.
112
+func DecodeHash(hash []byte) (*Argon2idHash, []byte, error) {
113
+ parts := strings.Split(string(hash), "$")
114
+ if len(parts) != 6 {
115
+ return nil, nil, fmt.Errorf("invalid hash format")
116
+ }
117
+
118
+ if parts[1] != argon2idName {
119
+ return nil, nil, fmt.Errorf("unsupported variant: %s", parts[1])
120
+ }
121
+
122
+ version, err := strconv.Atoi(strings.TrimPrefix(parts[2], "v="))
123
+ if err != nil {
124
+ return nil, nil, fmt.Errorf("invalid version: %w", err)
125
+ }
126
+ if version != argon2.Version {
127
+ return nil, nil, fmt.Errorf("incompatible version: %d", version)
128
+ }
129
+
130
+ params := strings.Split(parts[3], ",")
131
+ if len(params) != 3 {
132
+ return nil, nil, fmt.Errorf("invalid parameters")
133
+ }
134
+
135
+ mem, err := strconv.ParseUint(strings.TrimPrefix(params[0], "m="), 10, 32)
136
+ if err != nil {
137
+ return nil, nil, fmt.Errorf("invalid memory parameter: %w", err)
138
+ }
139
+
140
+ iter, err := strconv.ParseUint(strings.TrimPrefix(params[1], "t="), 10, 32)
141
+ if err != nil {
142
+ return nil, nil, fmt.Errorf("invalid iterations parameter: %w", err)
143
+ }
144
+
145
+ threads, err := strconv.ParseUint(strings.TrimPrefix(params[2], "p="), 10, 8)
146
+ if err != nil {
147
+ return nil, nil, fmt.Errorf("invalid parallelism parameter: %w", err)
148
+ }
149
+
150
+ salt, err := base64.RawStdEncoding.Strict().DecodeString(parts[4])
151
+ if err != nil {
152
+ return nil, nil, fmt.Errorf("decode salt: %w", err)
153
+ }
154
+
155
+ key, err := base64.RawStdEncoding.Strict().DecodeString(parts[5])
156
+ if err != nil {
157
+ return nil, nil, fmt.Errorf("decode key: %w", err)
158
+ }
159
+
160
+ return &Argon2idHash{
161
+ salt: salt,
162
+ time: uint32(iter),
163
+ memory: uint32(mem),
164
+ threads: uint8(threads),
165
+ keyLen: uint32(len(key)),
166
+ }, key, nil
167
+}
168
+
169
+// FakeHash returns a constant fake hash for timing attacks mitigation.
170
+func (Argon2idHash) FakeHash() []byte {
171
+ // hashed with the following command:
172
+ // caddy hash-password --plaintext "antitiming" --algorithm "argon2id"
173
+ return []byte("$argon2id$v=19$m=47104,t=1,p=1$P2nzckEdTZ3bxCiBCkRTyA$xQL3Z32eo5jKl7u5tcIsnEKObYiyNZQQf5/4sAau6Pg")
174
+}
175
+
176
+// Interface guards
177
+var (
178
+ _ Comparer = (*Argon2idHash)(nil)
179
+ _ Hasher = (*Argon2idHash)(nil)
180
+)
181
+
182
+func generateSalt(length int) ([]byte, error) {
183
+ salt := make([]byte, length)
184
+ if _, err := rand.Read(salt); err != nil {
185
+ return nil, fmt.Errorf("failed to generate salt: %w", err)
186
+ }
187
+ return salt, nil
188
+}
modules/caddyhttp/caddyauth/bcrypt.go
renamed
+4
-1
@@ -27,7 +27,10 @@ func init() {
27
}
28
29
// defaultBcryptCost cost 14 strikes a solid balance between security, usability, and hardware performance
30
-const defaultBcryptCost = 14
30
+const (
31
+ bcryptName = "bcrypt"
32
+ defaultBcryptCost = 14
33
+)
34
35
// BcryptHash implements the bcrypt hash.
36
type BcryptHash struct {
modules/caddyhttp/caddyauth/caddyfile.go
+4
-2
@@ -51,7 +51,7 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
51
var hashName string
52
switch len(args) {
53
case 0:
54
- hashName = "bcrypt"
54
+ hashName = bcryptName
55
case 1:
56
hashName = args[0]
57
case 2:
@@ -62,8 +62,10 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
62
}
63
64
switch hashName {
65
- case "bcrypt":
65
+ case bcryptName:
66
cmp = BcryptHash{}
67
+ case argon2idName:
68
+ cmp = Argon2idHash{}
69
default:
70
return nil, h.Errf("unrecognized hash algorithm: %s", hashName)
71
}
modules/caddyhttp/caddyauth/command.go
+65
-12
@@ -32,28 +32,55 @@ import (
32
func init() {
33
caddycmd.RegisterCommand(caddycmd.Command{
34
Name: "hash-password",
35
- Usage: "[--plaintext <password>] [--algorithm <name>] [--bcrypt-cost <difficulty>]",
35
+ Usage: "[--plaintext <password>] [--algorithm <argon2id|bcrypt>] [--bcrypt-cost <difficulty>] [--argon2id-time <iterations>] [--argon2id-memory <KiB>] [--argon2id-threads <n>] [--argon2id-keylen <bytes>]",
36
Short: "Hashes a password and writes base64",
37
Long: `
38
Convenient way to hash a plaintext password. The resulting
39
hash is written to stdout as a base64 string.
40
41
---plaintext, when omitted, will be read from stdin. If
42
-Caddy is attached to a controlling tty, the plaintext will
43
-not be echoed.
41
+--plaintext
42
+ The password to hash. If omitted, it will be read from stdin.
43
+ If Caddy is attached to a controlling TTY, the input will not be echoed.
44
45
---algorithm currently only supports 'bcrypt', and is the default.
45
+--algorithm
46
+ Selects the hashing algorithm. Valid options are:
47
+ * 'argon2id' (recommended for modern security)
48
+ * 'bcrypt' (legacy, slower, configurable cost)
49
47
---bcrypt-cost sets the bcrypt hashing difficulty.
48
-Higher values increase security by making the hash computation slower and more CPU-intensive.
49
-If the provided cost is not within the valid range [bcrypt.MinCost, bcrypt.MaxCost],
50
-the default value (defaultBcryptCost) will be used instead.
51
-Note: Higher cost values can significantly degrade performance on slower systems.
50
+bcrypt-specific parameters:
51
+
52
+--bcrypt-cost
53
+ Sets the bcrypt hashing difficulty. Higher values increase security by
54
+ making the hash computation slower and more CPU-intensive.
55
+ Must be within the valid range [bcrypt.MinCost, bcrypt.MaxCost].
56
+ If omitted or invalid, the default cost is used.
57
+
58
+Argon2id-specific parameters:
59
+
60
+--argon2id-time
61
+ Number of iterations to perform. Increasing this makes
62
+ hashing slower and more resistant to brute-force attacks.
63
+
64
+--argon2id-memory
65
+ Amount of memory to use during hashing.
66
+ Larger values increase resistance to GPU/ASIC attacks.
67
+
68
+--argon2id-threads
69
+ Number of CPU threads to use. Increase for faster hashing
70
+ on multi-core systems.
71
+
72
+--argon2id-keylen
73
+ Length of the resulting hash in bytes. Longer keys increase
74
+ security but slightly increase storage size.
75
`,
76
CobraFunc: func(cmd *cobra.Command) {
77
cmd.Flags().StringP("plaintext", "p", "", "The plaintext password")
55
- cmd.Flags().StringP("algorithm", "a", "bcrypt", "Name of the hash algorithm")
78
+ cmd.Flags().StringP("algorithm", "a", bcryptName, "Name of the hash algorithm")
79
cmd.Flags().Int("bcrypt-cost", defaultBcryptCost, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)")
80
+ cmd.Flags().Uint32("argon2id-time", defaultArgon2idTime, "Number of iterations for Argon2id hashing. Increasing this makes the hash slower and more resistant to brute-force attacks.")
81
+ cmd.Flags().Uint32("argon2id-memory", defaultArgon2idMemory, "Memory to use in KiB for Argon2id hashing. Larger values increase resistance to GPU/ASIC attacks.")
82
+ cmd.Flags().Uint8("argon2id-threads", defaultArgon2idThreads, "Number of CPU threads to use for Argon2id hashing. Increase for faster hashing on multi-core systems.")
83
+ cmd.Flags().Uint32("argon2id-keylen", defaultArgon2idKeylen, "Length of the resulting Argon2id hash in bytes. Longer hashes increase security but slightly increase storage size.")
84
cmd.RunE = caddycmd.WrapCommandFuncForCobra(cmdHashPassword)
85
},
86
})
@@ -115,8 +142,34 @@ func cmdHashPassword(fs caddycmd.Flags) (int, error) {
142
var hash []byte
143
var hashString string
144
switch algorithm {
118
- case "bcrypt":
145
+ case bcryptName:
146
hash, err = BcryptHash{cost: bcryptCost}.Hash(plaintext)
147
+ hashString = string(hash)
148
+ case argon2idName:
149
+ time, err := fs.GetUint32("argon2id-time")
150
+ if err != nil {
151
+ return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id time parameter: %w", err)
152
+ }
153
+ memory, err := fs.GetUint32("argon2id-memory")
154
+ if err != nil {
155
+ return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id memory parameter: %w", err)
156
+ }
157
+ threads, err := fs.GetUint8("argon2id-threads")
158
+ if err != nil {
159
+ return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id threads parameter: %w", err)
160
+ }
161
+ keyLen, err := fs.GetUint32("argon2id-keylen")
162
+ if err != nil {
163
+ return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id keylen parameter: %w", err)
164
+ }
165
+
166
+ hash, _ = Argon2idHash{
167
+ time: time,
168
+ memory: memory,
169
+ threads: threads,
170
+ keyLen: keyLen,
171
+ }.Hash(plaintext)
172
+
173
hashString = string(hash)
174
default:
175
return caddy.ExitCodeFailedStartup, fmt.Errorf("unrecognized hash algorithm: %s", algorithm)