upgrade deps, clean up (#83)

This commit is contained in:
Pierre Carrier
2025-02-07 23:48:54 +01:00
committed by GitHub
parent 5aeffe7a0c
commit 9adade7502
361 changed files with 19353 additions and 9076 deletions

1
vendor/github.com/creachadair/otp/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
.go-update

View File

@ -1,3 +0,0 @@
module github.com/creachadair/otp
go 1.18

View File

@ -146,6 +146,9 @@ func (c Config) format(v []byte, nd int) string {
// Truncate truncates the specified digest using the algorithm from RFC 4226.
// Only the low-order 31 bits of the value are populated; the rest are zero.
//
// Note that RFC 6238 stipulates the same truncation algorithm regardless of
// the length of the chosen digest.
func Truncate(digest []byte) uint64 {
offset := digest[len(digest)-1] & 0x0f
code := (uint64(digest[offset]&0x7f) << 24) |

164
vendor/github.com/creachadair/otp/otpauth/migration.go generated vendored Normal file
View File

@ -0,0 +1,164 @@
package otpauth
import (
"bytes"
"encoding/base64"
"encoding/binary"
"errors"
"fmt"
"io"
"net/url"
"strings"
"github.com/creachadair/wirepb"
)
// ParseMigrationURL parses an otpauth-migration URL in the format generated by
// the Google Authenticator for "exported" configurations. Typically these URLs
// are embedded as QR codes, encoding a proprietary URL in this format:
//
// otpauth-migration://offline?data=<content>
//
// The content is a protocol buffer message encoded as base64 in standard
// encoding. Note that a single migration URL may encode multiple OTP
// settings; on success this function returns all the otpauth URLs encoded by
// the content. It will always return at least one URL, or report an error.
func ParseMigrationURL(s string) ([]*URL, error) {
rest, ok := strings.CutPrefix(s, "otpauth-migration://")
if !ok {
return nil, errors.New("missing otpauth-migration schema prefix")
}
content, ok := strings.CutPrefix(rest, "offline?data=")
if !ok {
return nil, errors.New("unrecognized path format")
}
dec, err := url.QueryUnescape(content)
if err != nil {
return nil, fmt.Errorf("invalid data: %w", err)
}
bits, err := base64.StdEncoding.DecodeString(dec)
if err != nil {
return nil, fmt.Errorf("invalid base64: %w", err)
}
return parseMigrations(bits)
}
/*
The content of a migration URL is a wire-format protocol buffer message.
I don't want to take a dependency on protobuf, since that pulls in a lot of
other expensive Google nonsense, but fortunately the message structure is
fairly simple:
message Content {
repeated Params params = 1;
// ... other fields not of interest.
// If you're exporting more data than can fit in one QR code, the app may
// split up the export into multiple codes. There are some fields here to
// keep track of that, but they aren't relevant here.
}
message Params {
bytes secret = 1;
string account = 2;
string issuer = 3;
int32 algorithm = 4; // 0: unspec, 1: SHA1, 2: SHA256, 3: SHA512, 4: MD5
int32 digits = 5; // 0: unspec, 1: 6 digits, 2: 8 digits (typical Google)
int32 type = 6; // 0: unspec, 1: HOTP, 2: TOTP
uint64 counter = 7;
}
So here we just unpack the wire format directly.
*/
// parseMigrations parses data as a wire-format protobuf message in the Content
// format described above, and returns a single URL for each instance of the
// Params found therein. Other fields of the message are ignored.
func parseMigrations(data []byte) ([]*URL, error) {
const paramsField = 1
var out []*URL
s := wirepb.NewScanner(bytes.NewReader(data))
for s.Next() == nil {
if s.ID() == paramsField {
u, err := parseParams(s.Data())
if err != nil {
return nil, err
}
out = append(out, u)
}
}
if s.Err() != io.EOF {
return nil, s.Err()
} else if len(out) == 0 {
return nil, errors.New("no URLs found")
}
return out, nil
}
func parseParams(data []byte) (*URL, error) {
const (
secretField = 1 + iota
accountField
issuerField
algorithmField
digitsField
typeField
counterField
)
var out = URL{Algorithm: defaultAlgorithm, Digits: defaultDigits, Period: defaultPeriod}
s := wirepb.NewScanner(bytes.NewReader(data))
for s.Next() == nil {
switch s.ID() {
case secretField:
out.SetSecret(s.Data())
case accountField:
out.Account = string(s.Data())
case issuerField:
out.Issuer = string(s.Data())
case algorithmField:
switch v, _ := binary.Uvarint(s.Data()); v {
case 1:
out.Algorithm = "SHA1"
case 2:
out.Algorithm = "SHA256"
case 3:
out.Algorithm = "SHA512"
case 4:
out.Algorithm = "MD5"
default:
return nil, fmt.Errorf("unknown algorithm code %d", v)
}
case digitsField:
switch v, _ := binary.Uvarint(s.Data()); v {
case 1:
out.Digits = 6
case 2:
out.Digits = 8
default:
return nil, fmt.Errorf("unknown digits code %d", v)
}
case typeField:
switch v, _ := binary.Uvarint(s.Data()); v {
case 1:
out.Type = "hotp"
case 2:
out.Type = "totp"
default:
return nil, fmt.Errorf("unknown type code %d", v)
}
case counterField:
v, n := binary.Uvarint(s.Data())
if n <= 0 {
return nil, errors.New("invalid counter value")
}
out.Counter = v
}
}
if s.Err() != io.EOF {
return nil, s.Err()
}
return &out, nil
}

View File

@ -60,7 +60,7 @@ func (u *URL) String() string {
// Encode parameters if there are any non-default values.
var params []string
if a := strings.ToUpper(u.Algorithm); a != "" && a != "SHA1" {
params = append(params, "algorithm="+url.PathEscape(a))
params = append(params, "algorithm="+queryEscape(a))
}
if c := u.Counter; c > 0 || typ == "hotp" {
params = append(params, "counter="+strconv.FormatUint(c, 10))
@ -69,14 +69,14 @@ func (u *URL) String() string {
params = append(params, "digits="+strconv.Itoa(d))
}
if o := u.Issuer; o != "" {
params = append(params, "issuer="+url.PathEscape(o))
params = append(params, "issuer="+queryEscape(o))
}
if p := u.Period; p > 0 && p != defaultPeriod {
params = append(params, "period="+strconv.Itoa(p))
}
if s := u.RawSecret; s != "" {
enc := strings.ToUpper(strings.Join(strings.Fields(strings.TrimRight(s, "=")), ""))
params = append(params, "secret="+url.PathEscape(enc))
params = append(params, "secret="+queryEscape(enc))
}
if len(params) != 0 {
sb.WriteByte('?')
@ -182,7 +182,7 @@ func ParseURL(s string) (*URL, error) {
if len(ps) == 1 {
ps = append(ps, "") // check value below
}
value, err := url.PathUnescape(ps[1])
value, err := url.QueryUnescape(ps[1])
if err != nil {
return nil, fmt.Errorf("invalid value: %v", err)
}
@ -219,3 +219,7 @@ func ParseURL(s string) (*URL, error) {
}
return out, nil
}
func queryEscape(s string) string {
return strings.ReplaceAll(url.QueryEscape(s), "+", "%20")
}