ykoath

package module
v2.0.1 Latest Latest
Warning

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

Go to latest
Published: Nov 28, 2023 License: Apache-2.0 Imports: 18 Imported by: 1

README

go-ykoath

GitHub Workflow Status goreportcard Codecov branch License GitHub go.mod Go version Go Reference

The package ykoath implements the YubiKey YKOATH protocol for OATH-TOTP, OATH-HOTP and raw HMAC challenge-response.

Usage

c, err := ykoath.New()
if err != nil {
    log.Fatal(err)
}

defer c.Close()

if _, err = c.Select(); err != nil {
    log.Fatalf("Failed to select app: %v", err)
}

names, err := c.List()
if err != nil {
    log.Fatal("Failed to list slots: %v", err)
}

for _, name := range names {
    calc, err := c.Calculate(name.Name, func(name string) error {
        log.Printf("*** Please touch your YubiKey to unlock slot: %q ***", name)
        return nil
    })
    if err != nil {
        log.Fatal("Failed to calculate code for slot %q: %v", name.Name, err)
    }

    log.Printf("Got one-time-password %s for slot %q", calc, name)
}

if err := c.Put("test", ykoath.HmacSha1, ykoath.Totp, 6, []byte("open sesame"), true); err != nil {
    log.Fatal(err)
}

if err := c.Put("test2", ykoath.HmacSha1, ykoath.Totp, 6, []byte("open sesame"), true); err != nil {
    log.Fatal(err)
}

Authors

go-ykoath has been forked from yawn/ykoath at commit 201009e

License

go-ykoath is licensed under the Apache 2.0 license.

Documentation

Overview

Example
ctx, err := scard.EstablishContext()
if err != nil {
	log.Printf("Failed to establish context: %v", err)
	return
}

sc, err := pcsc.OpenFirstCard(ctx, yk.HasOATH, false)
if err != nil {
	log.Printf("Failed to connect to card: %v", err)
	return
}

c, err := ykoath.NewCard(sc)
if err != nil {
	log.Print(err)
	return
}

defer c.Close()

// Fix the clock
c.Clock = func() time.Time {
	return time.Unix(59, 0)
}

// Enable OATH for this session
if _, err = c.Select(); err != nil {
	log.Printf("Failed to select applet: %v", err)
	return
}

// Reset the applet
// if err := c.Reset(); err != nil {
// 	log.Printf("Failed to reset applet: %v", err)
// 	return
// }

// Add the testvector
if err = c.Put("testvector", ykoath.HmacSha1, ykoath.Totp, 8, []byte("12345678901234567890"), false, 0); err != nil {
	log.Printf("Failed to put: %v", err)
	return
}

names, err := c.List()
if err != nil {
	log.Printf("Failed to list: %v", err)
	return
}

for _, name := range names {
	fmt.Printf("Name: %s\n", name)
}

otp, _ := c.CalculateMatch("testvector", nil)
fmt.Printf("OTP: %s\n", otp)
Output:

Name: testvector (HMAC-SHA1 TOTP)
OTP: 94287082

Index

Examples

Constants

View Source
const (
	DefaultTimeStep    = 30 * time.Second
	HMACMinimumKeySize = 14
)

Variables

View Source
var (
	ErrNoValuesFound         = errors.New("no values found in response")
	ErrUnknownName           = errors.New("no such name configured")
	ErrMultipleMatches       = errors.New("multiple matches found")
	ErrTouchRequired         = errors.New("touch required")
	ErrTouchCallbackRequired = errors.New("touch callback required")
	ErrChallengeRequired     = errors.New("challenge required")
)
View Source
var (
	ErrAuthRequired         = Error{0x69, 0x82}
	ErrGeneric              = Error{0x65, 0x81}
	ErrNoSpace              = Error{0x6a, 0x84}
	ErrNoSuchObject         = Error{0x69, 0x84}
	ErrResponseDoesNotMatch = Error{0x69, 0x84}
	ErrWrongSyntax          = Error{0x6a, 0x80}
)
View Source
var ErrNameTooLong = errors.New("name too long)")

Functions

This section is empty.

Types

type Algorithm

type Algorithm byte

Algorithm denotes the HMAc algorithm used for deriving the one-time passwords

const (
	// HmacSha1 describes a HMAC with SHA-1
	HmacSha1 Algorithm = 0x01

	// HmacSha256 describes a HMAC with SHA-2 (256-bit)
	HmacSha256 Algorithm = 0x02

	// HmacSha512 describes a HMAC with SHA-2 (512-bit)
	HmacSha512 Algorithm = 0x03
)

func (Algorithm) Hash

func (a Algorithm) Hash() func() hash.Hash

Hash returns a constructor to create a new hash.Hash object for the given algorithm.

func (Algorithm) String

func (a Algorithm) String() string

String returns a string representation of the algorithm

type Card

type Card struct {
	*iso.Card

	Clock    func() time.Time
	Timestep time.Duration
	Rand     io.Reader
	// contains filtered or unexported fields
}

Card implements most parts of the TOTP portion of the YKOATH specification https://developers.yubico.com/Card/YKOATH_Protocol.html

func NewCard

func NewCard(pcscCard iso.PCSCCard) (*Card, error)

NewCard initializes a new OATH card.

func (*Card) Calculate

func (c *Card) Calculate(name string) (string, error)

func (*Card) CalculateChallengeResponse

func (c *Card) CalculateChallengeResponse(name string, challenge []byte) ([]byte, int, error)

func (*Card) CalculateMatch

func (c *Card) CalculateMatch(name string, touchRequiredCallback func(string) error) (string, error)

CalculateMatch is a high-level function that first identifies all TOTP credentials that are configured and returns the matching one (if no touch is required) or fires the callback and then fetches the name again while blocking during the device awaiting touch

func (*Card) Close

func (c *Card) Close() error

Close terminates an OATH session

func (*Card) Delete

func (c *Card) Delete(name string) error

Delete sends a "DELETE" instruction, removing one named OATH credential

func (*Card) List

func (c *Card) List() ([]*Name, error)

List sends a "LIST" instruction, return a list of OATH credentials

func (*Card) Put

func (c *Card) Put(name string, alg Algorithm, typ Type, digits int, key []byte, touch bool, counter uint32) error

Put sends a "PUT" instruction, storing a new / overwriting an existing OATH credentials with an algorithm and type, 6 or 8 digits one-time password, shared secrets and touch-required bit

func (*Card) RemoveCode

func (c *Card) RemoveCode() error

func (*Card) Reset

func (c *Card) Reset() error

Reset resets the application to just-installed state. This command requires no authentication. WARNING: This function wipes all secrets on the token. Use with care!

func (*Card) Select

func (c *Card) Select() (*Select, error)

Select sends a "SELECT" instruction, initializing the device for an OATH session

func (*Card) SetCode

func (c *Card) SetCode(code []byte, alg Algorithm) error

SetCode sets a new PIN. This command no authentication.

func (*Card) Validate

func (c *Card) Validate(code []byte) error

Reset resets the application to just-installed state. This command requires no authentication.

type Code

type Code struct {
	Hash          []byte
	Digits        int
	Type          Type
	TouchRequired bool
	Truncated     bool
}

func (Code) OTP

func (c Code) OTP() string

OTP converts a value into a (6 or 8 digits) one-time password See: RFC 4226 Section 5.3 - Generating an HOTP Value https://datatracker.ietf.org/doc/html/rfc4226#section-5.3

type Error

type Error iso.Code

func (Error) Error

func (e Error) Error() string

Error return the encapsulated error string

func (Error) HasMore

func (e Error) HasMore() bool

IsMore indicates more data that needs to be fetched

type Name

type Name struct {
	Algorithm Algorithm
	Type      Type
	Name      string
}

Name encapsulates the result of the "LIST" instruction

func (*Name) String

func (n *Name) String() string

String returns a string representation of the algorithm

type Select

type Select struct {
	Algorithm []byte
	Challenge []byte
	Name      []byte
	Version   []byte
}

Select encapsulates the results of the "SELECT" instruction

func (*Select) UnmarshalBinary

func (s *Select) UnmarshalBinary(b []byte) error

type Type

type Type byte

Type denotes the kind of derivation used for the one-time password

const (
	// Hotp describes HMAC based one-time passwords (https://tools.ietf.org/html/rfc4226)
	Hotp Type = 0x10

	// Totp describes time-based one-time passwords (https://tools.ietf.org/html/rfc6238)
	Totp Type = 0x20
)

func (Type) String

func (t Type) String() string

String returns a string representation of the type

Jump to

Keyboard shortcuts

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