Skip to content
Snippets Groups Projects
Commit 6435ac68 authored by ale's avatar ale
Browse files

Initial commit

parents
No related branches found
No related tags found
No related merge requests found
webauthn-cred
===
Small and compact command-line tool used to generate WebAuthN
registrations for external applications. Its primary use case is to
enlist hardware tokens in the file-based backend of
[id/auth](https://git.autistici.org/id/auth).
# Build
The tools uses the *libfido2* C library to talk to the hardware
devices, so you'll have to install the development packages for it:
```shell
sudo apt install build-essential libfido2-dev
```
Then it's possible to build the binary:
```shell
go build -o webauthn-cred main.go
```
Note that there seems to be no libfido2.a static library available in
Debian, so it's not possible to generate a fully static binary.
# Usage
Run the tool with the *--rpid* flag set to the WebAuthN Relying Party
ID that is used by the application you're registering for. The tool
will output the key handle and public key corresponding to the new
registration. Example:
```
$ webauthn-cred --rpid=login.example.com
autodetected device: Yubico YubiKey OTP+FIDO+CCID
touch the device (you may be asked for a pin first)......
PIN>
key handle: "m9fihYynTqp3GQzrOsJIwID3VThXw63Je6kD8T7W734SaY2gFPSJz4NYimZZa73Qygb/toZT4FSGvpF4HbFbZQ=="
public key: "pAECAyYhWCCt7/3iAJTqFJhwcIp3qHqxC2XfhQQbShOYhu41cB7QNSJYIDeIfO/IckpJctrFBARqxDX+hk32eY0Z4KLSzjJ6B2Fv"
```
Both the key handle and public key are base64-encoded, the public key
is additionally encoded in COSE format.
go.mod 0 → 100644
module git.autistici.org/ai3/tools/webauthn-cred
go 1.15
require (
github.com/duo-labs/webauthn v0.0.0-20210727191636-9f1b88ef44cc
github.com/fxamacker/cbor/v2 v2.2.0
github.com/keys-pub/go-libfido2 v1.5.2
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
)
go.sum 0 → 100644
github.com/cloudflare/cfssl v0.0.0-20190726000631-633726f6bcb7/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/duo-labs/webauthn v0.0.0-20210727191636-9f1b88ef44cc h1:mLNknBMRNrYNf16wFFUyhSAe1tISZN7oAfal4CZ2OxY=
github.com/duo-labs/webauthn v0.0.0-20210727191636-9f1b88ef44cc/go.mod h1:/X2OJiJxjQ7alqWZqX9EtBTmZc+4qQ0LvZ1k5wP67RM=
github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ=
github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
github.com/keys-pub/go-libfido2 v1.5.2 h1:YJVK9iMOMlfRZrEzZtnJBRNO+jYB+/sfNtO4ruV7BXI=
github.com/keys-pub/go-libfido2 v1.5.2/go.mod h1:P0V19qHwJNY0htZwZDe9Ilvs/nokGhdFX7faKFyZ6+U=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
main.go 0 → 100644
package main
import (
"encoding/base64"
"errors"
"flag"
"fmt"
"log"
"os"
"github.com/duo-labs/webauthn/protocol/webauthncose"
"github.com/fxamacker/cbor/v2"
"github.com/keys-pub/go-libfido2"
"golang.org/x/term"
)
var (
forceDevicePath = flag.String("device", "", "force usage of a specific HID device (default: autodetect)")
username = flag.String("username", os.Getenv("USER"), "username")
rpID = flag.String("rpid", "", "WebAuthN relying party identifier")
)
func readPIN() (string, error) {
fmt.Printf("\rPIN> ")
pw, err := term.ReadPassword(int(os.Stdin.Fd()))
fmt.Printf("\n")
return string(pw), err
}
func fido2ToCOSE(pk []byte) []byte {
var parsed webauthncose.EC2PublicKeyData
parsed.KeyType = int64(webauthncose.EllipticKey)
parsed.Algorithm = int64(webauthncose.AlgES256)
parsed.Curve = 0
parsed.XCoord = pk[:32]
parsed.YCoord = pk[32:]
data, _ := cbor.Marshal(&parsed)
return data
}
func main() {
log.SetFlags(0)
flag.Parse()
if *rpID == "" {
log.Fatal("must specify --rpid")
}
devicePath := *forceDevicePath
if devicePath == "" {
locs, err := libfido2.DeviceLocations()
if err != nil {
log.Fatal("error enumerating devices: %v", err)
}
if len(locs) == 0 {
log.Fatal("error: no FIDO2 devices found")
}
log.Printf("autodetected device: %s %s", locs[0].Manufacturer, locs[0].Product)
devicePath = locs[0].Path
}
device, err := libfido2.NewDevice(devicePath)
if err != nil {
log.Fatal("error opening device: %v", err)
}
// Generate pseudorandom challenge and user ID.
challenge := libfido2.RandBytes(32)
userID := libfido2.RandBytes(32)
fmt.Println("touch the device (you may be asked for a pin first)......")
var pin string
var attest *libfido2.Attestation
for {
attest, err = device.MakeCredential(
challenge,
libfido2.RelyingParty{
ID: *rpID,
Name: *rpID,
},
libfido2.User{
ID: userID,
Name: *username,
},
libfido2.ES256,
pin,
&libfido2.MakeCredentialOpts{
RK: libfido2.False,
UV: libfido2.False,
},
)
if errors.Is(err, libfido2.ErrPinRequired) {
pin, err = readPIN()
if err != nil {
log.Fatalf("error reading PIN: %v", err)
}
continue
}
if err != nil {
log.Fatal(err)
}
break
}
fmt.Printf(
"key handle: \"%s\"\npublic key: \"%s\"\n",
base64.StdEncoding.EncodeToString(attest.CredentialID),
base64.StdEncoding.EncodeToString(fido2ToCOSE(attest.PubKey)),
)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment