<commit_before>// Go FIDO U2F Library
// Copyright 2015 The Go FIDO U2F Library Authors. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package u2f

import (
	"crypto/ecdsa"
	"crypto/sha256"
	"encoding/asn1"
	"errors"
	"math/big"
	"time"
)

// SignRequest creates a request to initiate an authentication.
func (c *Challenge) SignRequest(regs ...Registration) *SignRequest {
	var encodedHandles = make([]string, len(regs), len(regs))
	for i, r := range regs {
		encodedHandles[i] = encodeBase64(r.KeyHandle)
	}

	var sr SignRequest
	sr.Version = u2fVersion
	sr.KeyHandles = encodedHandles
	sr.AppID = c.AppID
	sr.Challenge = encodeBase64(c.Challenge)
	return &sr
}

// Authenticate validates a SignResponse authentication response.
// 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 (reg *Registration) Authenticate(resp SignResponse, c Challenge, counter uint32) (newCounter uint32, err error) {
	if time.Now().Sub(c.Timestamp) > timeout {
		return 0, errors.New("u2f: challenge has expired")
	}
	if resp.KeyHandle != encodeBase64(reg.KeyHandle) {
		return 0, errors.New("u2f: wrong key handle")
	}

	sigData, err := decodeBase64(resp.SignatureData)
	if err != nil {
		return 0, err
	}

	clientData, err := decodeBase64(resp.ClientData)
	if err != nil {
		return 0, err
	}

	ar, err := parseSignResponse(sigData)
	if err != nil {
		return 0, err
	}

	if ar.Counter < counter {
		return 0, errors.New("u2f: counter not increasing")
	}<commit_msg>Expose ErrCounterTooLow so that applications can choose to disable the device. See issue #6.<commit_after>// Go FIDO U2F Library
// Copyright 2015 The Go FIDO U2F Library Authors. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package u2f

import (
	"crypto/ecdsa"
	"crypto/sha256"
	"encoding/asn1"
	"errors"
	"math/big"
	"time"
)

// SignRequest creates a request to initiate an authentication.
func (c *Challenge) SignRequest(regs ...Registration) *SignRequest {
	var encodedHandles = make([]string, len(regs), len(regs))
	for i, r := range regs {
		encodedHandles[i] = encodeBase64(r.KeyHandle)
	}

	var sr SignRequest
	sr.Version = u2fVersion
	sr.KeyHandles = encodedHandles
	sr.AppID = c.AppID
	sr.Challenge = encodeBase64(c.Challenge)
	return &sr
}

// ErrCounterTooLow is raised when the counter value received from the device is
// lower than last stored counter value. This may indicate that the device has
// been cloned (or is malfunctioning). The application may choose to disable
// the particular device as precaution.
var ErrCounterTooLow = errors.New("u2f: counter too low")

// Authenticate validates a SignResponse authentication response.
// 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 (reg *Registration) Authenticate(resp SignResponse, c Challenge, counter uint32) (newCounter uint32, err error) {
	if time.Now().Sub(c.Timestamp) > timeout {
		return 0, errors.New("u2f: challenge has expired")
	}
	if resp.KeyHandle != encodeBase64(reg.KeyHandle) {
		return 0, errors.New("u2f: wrong key handle")
	}

	sigData, err := decodeBase64(resp.SignatureData)
	if err != nil {
		return 0, err
	}

	clientData, err := decodeBase64(resp.ClientData)
	if err != nil {
		return 0, err
	}

	ar, err := parseSignResponse(sigData)
	if err != nil {
		return 0, err
	}

	if ar.Counter < counter {
		return 0, ErrCounterTooLow
	}
{'fraction_non_alphanumeric': 0.10237306843267108, 'fraction_numerical': 0.019591611479028697, 'mean_word_length': 4.027739251040222, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3148071', 'n_tokens_mistral': 1231, 'n_tokens_neox': 1151, 'n_words': 417}