u2f

package module
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 3, 2016 License: MIT Imports: 16 Imported by: 0

README

Go FIDO U2F Library

A server side implementation of the FIDO U2F specification in GO, based on tstranex/u2f.

This fork alters the API to simplify implementation, handle multiple tokens, and to correspond better to the U2F JavaScript specification.

This also includes a virtual token implementation for integration testing, see virtualkey_test.go for an example.

Features

  • Native Go implementation
  • No dependencies other than the Go standard library
  • Token attestation certificate verification

Status

Build Status

Components working, API subject to change as better interfaces are realised. Suggest installation with gopkg.in/ryankurte/go-u2f.v1.

Usage

Please visit http://godoc.org/github.com/ryankurte/go-u2f for the full documentation.

Request Enrolment
// Fetch registration entries from the database
var registeredKeys []u2f.Registration

app_id := "http://localhost"

// Generate registration request
c1, _ := u2f.NewChallenge(app_id, []string{app_id}, registeredKeys)
req, _ := c1.RegisterRequest()

// Send request to browser
...

// Save challenge to session
...
Check Enrolment
// Read challenge from session
var c1 u2f.Challenge

// Read response from the browser
var resp u2f.RegisterResponse

// Perform registration
reg, err := c1.Register(resp)
if err != nil {
    // Registration failed.
}

// Store registration in the database against a user
...
Request Authentication
// Fetch registration entries for a user from the database
var registeredKeys []Registration

app_id := "http://localhost"

// Generate authentication request
c2, _ := u2f.NewChallenge(app_id, []string{app_id}, registeredKeys)
req, _ := c2.SignRequest()

// Send request to browser
...

// Save challenge to session
...
Check Authentication
// Read challenge from session
var c2 u2f.Challenge

// Read response from the browser
var resp SignResponse

// Perform authentication
reg, err := c2.Authenticate(resp)
if err != nil {
    // Authentication failed.
}

// Store updated registration (usage count) in the database
...

Client side usage

The u2f.RegisterRequestMessage and u2f.SignRequestMessage structures are directly serialisable, giving the following:

u2f.register(req.appId, req.registerRequests, req.registeredKeys, registerCallback, timeout);
u2f.sign(req.appId, req.challenge, req.registeredKeys, signCallback, timeout);

See u2fdemo/main.go for an example.

Installation

$ go get github.com/ryankurte/go-u2f

Example

See u2fdemo/main.go for an full example server. To run it:

$ go install github.com/ryankurte/go-u2f/u2fdemo
$ ./bin/u2fdemo

Or with from the repository:

$ go run u2fdemo/*

Open https://localhost:3483 in Chrome. Ignore the SSL warning (due to the self-signed certificate for localhost). You can then test registering and authenticating using your token.

License

The Go FIDO U2F Library is licensed under the MIT License.

Documentation

Overview

Package u2f implements the server-side parts of the FIDO Universal 2nd Factor (U2F) specification.

Applications will need to persist Challenge and Registration objects.

Request Enrolment

// Fetch registration entries from the database
var registeredKeys []u2f.Registration

app_id := "http://localhost"

// Generate registration request
c1, _ := u2f.NewChallenge(app_id, []string{app_id}, registeredKeys)
req, _ := c1.RegisterRequest()

// Send request to browser
...

// Save challenge to session
...

Check Enrolment

// Read challenge from session
var c1 u2f.Challenge

// Read response from the browser
var resp u2f.RegisterResponse

// Perform registration
reg, err := c1.Register(resp)
if err != nil {
    // Registration failed.
}

// Store registration in the database against a user
...

Request Authentication

// Fetch registration entries for a user from the database
var registeredKeys []Registration

app_id := "http://localhost"

// Generate authentication request
c2, _ := u2f.NewChallenge(app_id, []string{app_id}, registeredKeys)
req, _ := c2.SignRequest()

// Send request to browser
...

// Save challenge to session
...

Check Authentication

// Read challenge from session
var c1 u2f.Challenge

// Read response from the browser
var resp SignResponse

// Perform authentication
reg, err := c2.Authenticate(resp)
if err != nil {
    // Authentication failed.
}

// Store updated registration (use counter) in the database
...

The FIDO U2F specification can be found here: https://fidoalliance.org/specifications/download

Index

Constants

View Source
const U2FTransportBLE string = "ble"
View Source
const U2FTransportBT string = "bt"

U2F message transport types

View Source
const U2FTransportNFC string = "nfc"
View Source
const U2FTransportUSB string = "usb"

Variables

View Source
var (
	// Authentication errors
	ErrCounterLow        = errors.New("u2f: counter not increasing")
	ErrRandomGen         = errors.New("u2f: unable to generate random bytes")
	ErrUntrustedFacet    = errors.New("u2f: untrusted facet id")
	ErrWrongKeyHandle    = errors.New("u2f: wrong key handle")
	ErrChallengeExpired  = errors.New("u2f: challenge has expired")
	ErrChallengeMismatch = errors.New("u2f: challenge does not match")
	ErrUserNotPresent    = errors.New("u2f: user was not present")

	// Parser errors
	ErrDataShort    = errors.New("u2f: data is too short")
	ErrTrailingData = errors.New("u2f: trailing data")

	ErrInvalidPresense     = errors.New("u2f: invalid user presence byte")
	ErrInvalidSig          = errors.New("u2f: invalid signature")
	ErrInvalidReservedByte = errors.New("u2f: invalid reserved byte")
	ErrInvalidPublicKey    = errors.New("u2f: invalid public key")
	ErrInvalidKeyHandle    = errors.New("u2f: invalid key handle")
)

Errors for external use

Functions

This section is empty.

Types

type Challenge

type Challenge struct {
	Challenge      []byte
	Timestamp      time.Time
	AppID          string
	TrustedFacets  []string
	RegisteredKeys []Registration
}

Challenge represents a single transaction between the server and authenticator. This data will typically be stored in a database.

func NewChallenge

func NewChallenge(appID string, trustedFacets []string, registeredKeys []Registration) (*Challenge, error)

NewChallenge generates a challenge for the given application, trusted facets, and registered keys This challenge can then be used to generate and validate registration or authorization requests

func (*Challenge) Authenticate

func (c *Challenge) Authenticate(resp SignResponse) (*Registration, error)

Authenticate validates a SignResponse authentication response against an particular Challenge. An error is returned if any part of the response fails to validate. The latest counter value is returned, which the caller should store.

func (*Challenge) Register

func (c *Challenge) Register(resp RegisterResponse, config *RegistrationConfig) (*Registration, error)

Register validates a RegisterResponse message to enrol a new token against the provided challenge An error is returned if any part of the response fails to validate. The returned Registration should be stored by the caller.

func (*Challenge) RegisterRequest

func (c *Challenge) RegisterRequest() *RegisterRequestMessage

RegisterRequest builds a registration request from a challenge This must be provided with already registered key handles

func (*Challenge) SignRequest

func (c *Challenge) SignRequest() *SignRequestMessage

SignRequest creates a request to initiate authentication.

type ClientData

type ClientData struct {
	Typ          string          `json:"typ"`
	Challenge    string          `json:"challenge"`
	Origin       string          `json:"origin"`
	CIDPublicKey json.RawMessage `json:"cid_pubkey"`
}

ClientData as defined by the FIDO U2F Raw Message Formats specification.

type JwkKey

type JwkKey struct {
	KTy string `json:"kty"`
	Crv string `json:"crv"`
	X   string `json:"x"`
	Y   string `json:"y"`
}

JwkKey represents a public key used by a browser for the Channel ID TLS extension.

type RegisterRequestMessage

type RegisterRequestMessage struct {
	AppID            string            `json:"appId"`
	RegisterRequests []registerRequest `json:"registerRequests"`
	RegisteredKeys   []registeredKey   `json:"registeredKeys"`
}

Represents U2F Registration Request This message is passed to the browser for registration

type RegisterResponse

type RegisterResponse struct {
	RegistrationData string `json:"registrationData"`
	ClientData       string `json:"clientData"`
}

RegisterResponse is the structure returned by the token/u2f implementation

type Registration

type Registration struct {
	// Raw KeyHandle
	KeyHandle string
	// Base64 encoded ASN1 public key
	PublicKey string
	// Usage counter
	Counter uint
	// Base64 encoded PEM certificate
	Certificate string
}

Registration represents a single enrolment or pairing between an application and a token. The keyHandle, publicKey and usage count must be stored

type RegistrationConfig

type RegistrationConfig struct {
	// SkipAttestationVerify controls whether the token attestation
	// certificate should be verified on registration. Ideally it should
	// always be verified. However, there is currently no public list of
	// trusted attestation root certificates so it may be necessary to skip.
	SkipAttestationVerify bool
}

Registration request configuration

type SignRequestMessage

type SignRequestMessage struct {
	AppID          string          `json:"appId"`
	Challenge      string          `json:"challenge"`
	RegisteredKeys []registeredKey `json:"registeredKeys"`
}

Represents a U2F Signature Request. This message is passed to the browser for authentication

type SignResponse

type SignResponse struct {
	KeyHandle     string `json:"keyHandle"`
	SignatureData string `json:"signatureData"`
	ClientData    string `json:"clientData"`
}

SignResponse as defined by the FIDO U2F Javascript API.

type TrustedFacets

type TrustedFacets struct {
	Version struct {
		Major int `json:"major"`
		Minor int `json:"minor"`
	} `json:"version"`
	Ids []string `json:"ids"`
}

TrustedFacets as defined by the FIDO AppID and Facet Specification.

type TrustedFacetsEndpoint

type TrustedFacetsEndpoint struct {
	TrustedFacets []TrustedFacets `json:"trustedFacets"`
}

TrustedFacetsEndpoint is a container of TrustedFacets. It is used as the response for an appId URL endpoint.

type VirtualKey

type VirtualKey struct {
	// contains filtered or unexported fields
}

Virtual U2F key

func NewVirtualKey

func NewVirtualKey() (*VirtualKey, error)

Create a virtual key

func (*VirtualKey) HandleAuthenticationRequest

func (vk *VirtualKey) HandleAuthenticationRequest(req SignRequestMessage) (*SignResponse, error)

Handle an authentication request

func (*VirtualKey) HandleRegisterRequest

func (vk *VirtualKey) HandleRegisterRequest(req RegisterRequestMessage) (*RegisterResponse, error)

Handle a registration request

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL