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 ¶
const U2FTransportBLE string = "ble"
const U2FTransportBT string = "bt"
U2F message transport types
const U2FTransportNFC string = "nfc"
const U2FTransportUSB string = "usb"
Variables ¶
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 (*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