Full Code of Yubico/java-u2flib-server for AI

master df59a357d079 cached
129 files
314.4 KB
86.9k tokens
456 symbols
1 requests
Download .txt
Showing preview only (355K chars total). Download the full file or copy to clipboard to get everything.
Repository: Yubico/java-u2flib-server
Branch: master
Commit: df59a357d079
Files: 129
Total size: 314.4 KB

Directory structure:
gitextract_r69ouwzl/

├── .gitattributes
├── .github/
│   └── workflows/
│       └── scan.yml
├── .gitignore
├── .travis.yml
├── COPYING
├── NEWS
├── README
├── buildSrc/
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── groovy/
│               └── com/
│                   └── yubico/
│                       └── gradle/
│                           └── pitest/
│                               └── tasks/
│                                   └── PitestMergeTask.groovy
├── dev-util/
│   ├── example-authentication.py
│   └── example-registration.py
├── lombok.config
├── pom.xml
├── u2flib-server-attestation/
│   ├── README.adoc
│   ├── build.gradle
│   ├── gradle/
│   │   └── wrapper/
│   │       ├── gradle-wrapper.jar
│   │       └── gradle-wrapper.properties
│   ├── gradlew
│   ├── gradlew.bat
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── yubico/
│       │   │           └── u2f/
│       │   │               └── attestation/
│       │   │                   ├── Attestation.java
│       │   │                   ├── DeviceMatcher.java
│       │   │                   ├── MetadataObject.java
│       │   │                   ├── MetadataResolver.java
│       │   │                   ├── MetadataService.java
│       │   │                   ├── Transport.java
│       │   │                   ├── matchers/
│       │   │                   │   ├── ExtensionMatcher.java
│       │   │                   │   └── FingerprintMatcher.java
│       │   │                   └── resolvers/
│       │   │                       └── SimpleResolver.java
│       │   └── resources/
│       │       └── metadata.json
│       └── test/
│           └── java/
│               └── com/
│                   └── yubico/
│                       └── u2f/
│                           └── attestation/
│                               ├── MetadataObjectTest.java
│                               ├── MetadataServiceTest.java
│                               ├── TransportTest.java
│                               ├── matchers/
│                               │   └── FingerprintMatcherTest.java
│                               └── resolvers/
│                                   └── SimpleResolverTest.java
├── u2flib-server-core/
│   ├── build.gradle
│   ├── gradle/
│   │   └── wrapper/
│   │       ├── gradle-wrapper.jar
│   │       └── gradle-wrapper.properties
│   ├── gradlew
│   ├── gradlew.bat
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── yubico/
│       │               └── u2f/
│       │                   ├── AppId.java
│       │                   ├── U2F.java
│       │                   ├── U2fPrimitives.java
│       │                   ├── crypto/
│       │                   │   ├── BouncyCastleCrypto.java
│       │                   │   ├── ChallengeGenerator.java
│       │                   │   ├── Crypto.java
│       │                   │   └── RandomChallengeGenerator.java
│       │                   ├── data/
│       │                   │   ├── DeviceRegistration.java
│       │                   │   └── messages/
│       │                   │       ├── ClientData.java
│       │                   │       ├── RegisterRequest.java
│       │                   │       ├── RegisterRequestData.java
│       │                   │       ├── RegisterResponse.java
│       │                   │       ├── RegisteredKey.java
│       │                   │       ├── SignRequest.java
│       │                   │       ├── SignRequestData.java
│       │                   │       ├── SignResponse.java
│       │                   │       ├── json/
│       │                   │       │   ├── JsonSerializable.java
│       │                   │       │   └── Persistable.java
│       │                   │       └── key/
│       │                   │           ├── RawRegisterResponse.java
│       │                   │           ├── RawSignResponse.java
│       │                   │           └── util/
│       │                   │               ├── ByteInputStream.java
│       │                   │               ├── CertificateParser.java
│       │                   │               └── U2fB64Encoding.java
│       │                   └── exceptions/
│       │                       ├── DeviceCompromisedException.java
│       │                       ├── InvalidDeviceCounterException.java
│       │                       ├── NoEligableDevicesException.java
│       │                       ├── NoEligibleDevicesException.java
│       │                       ├── U2fAuthenticationException.java
│       │                       ├── U2fBadConfigurationException.java
│       │                       ├── U2fBadInputException.java
│       │                       ├── U2fCeremonyException.java
│       │                       └── U2fRegistrationException.java
│       └── test/
│           ├── java/
│           │   └── com/
│           │       └── yubico/
│           │           └── u2f/
│           │               ├── AppIdTest.java
│           │               ├── SystemTest.java
│           │               ├── TestUtils.java
│           │               ├── U2FTest.java
│           │               ├── U2fPrimitivesTest.java
│           │               ├── codec/
│           │               │   ├── RawCodecTest.java
│           │               │   └── SerialCodecTest.java
│           │               ├── data/
│           │               │   ├── DeviceRegistrationTest.java
│           │               │   └── messages/
│           │               │       ├── ClientDataTest.java
│           │               │       ├── RegisterRequestDataTest.java
│           │               │       ├── RegisterRequestTest.java
│           │               │       ├── RegisterResponseTest.java
│           │               │       ├── SignRequestDataTest.java
│           │               │       ├── SignRequestTest.java
│           │               │       ├── SignResponseTest.java
│           │               │       ├── json/
│           │               │       │   └── JsonSerializableTest.java
│           │               │       └── key/
│           │               │           ├── Client.java
│           │               │           ├── CodecTestUtils.java
│           │               │           └── util/
│           │               │               ├── CertificateParserTest.java
│           │               │               └── U2fB64EncodingTest.java
│           │               ├── json/
│           │               │   └── SerializationTest.java
│           │               ├── softkey/
│           │               │   ├── SoftKey.java
│           │               │   ├── SoftKeyTest.java
│           │               │   └── messages/
│           │               │       ├── RegisterRequest.java
│           │               │       └── SignRequest.java
│           │               └── testdata/
│           │                   ├── AcmeKey.java
│           │                   ├── GnubbyKey.java
│           │                   └── TestVectors.java
│           └── resources/
│               └── com/
│                   └── yubico/
│                       └── u2f/
│                           └── testdata/
│                               ├── acme/
│                               │   └── attestation-certificate.der
│                               └── gnubby/
│                                   ├── attestation-certificate-private-key.hex
│                                   └── attestation-certificate.der
└── u2flib-server-demo/
    ├── README
    ├── build.gradle
    ├── config.yml
    ├── gradle/
    │   └── wrapper/
    │       ├── gradle-wrapper.jar
    │       └── gradle-wrapper.properties
    ├── gradlew
    ├── gradlew.bat
    ├── keystore.jks
    ├── pom.xml
    └── src/
        └── main/
            ├── java/
            │   └── demo/
            │       ├── App.java
            │       ├── Config.java
            │       ├── Resource.java
            │       ├── U2fDemoException.java
            │       └── view/
            │           ├── AuthenticationView.java
            │           ├── FinishAuthenticationView.java
            │           ├── FinishRegistrationView.java
            │           └── RegistrationView.java
            └── resources/
                ├── assets/
                │   ├── loginIndex.html
                │   ├── registerIndex.html
                │   └── u2f-api-1.1.js
                └── demo/
                    └── view/
                        ├── authenticate.ftl
                        ├── finishAuthentication.ftl
                        ├── finishRegistration.ftl
                        ├── navigation.ftl
                        └── register.ftl

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
# Auto-detect text files
* text=auto

# Always treat these as LF
gradlew text eol=lf
*.sh text eol=lf

# Always treat these as CRLF
*.bat text eol=crlf


================================================
FILE: .github/workflows/scan.yml
================================================
name: static code analysis
# Documentation: https://github.com/Yubico/yes-static-code-analysis

on:
  push:
  schedule:
    - cron: '0 0 * * 1'

env:
  SCAN_IMG:
    yubico-yes-docker-local.jfrog.io/static-code-analysis/java:v1
  SECRET: ${{ secrets.ARTIFACTORY_READER_TOKEN }}

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@master

    - name: Scan and fail on warnings
      run: |
        if [ "${SECRET}" != "" ]; then
          docker login yubico-yes-docker-local.jfrog.io/ \
            -u svc-static-code-analysis-reader -p ${SECRET}
          docker pull ${SCAN_IMG}
          docker run -v${PWD}:/k -e PROJECT_NAME=${GITHUB_REPOSITORY#Yubico/} \
            -t ${SCAN_IMG}
        else
          echo "No docker registry credentials, not scanning"
        fi

    - uses: actions/upload-artifact@master
      if: failure()
      with:
        name: suppression_files
        path: suppression_files


================================================
FILE: .gitignore
================================================
# Eclipse
.classpath
.project
.settings/

# Intellij
.idea/
out/
*.iml
*.iws

# Mac
.DS_Store

# Maven
log/
target/
*.versionsBackup

# Gradle
.gradle/
/build/
/*/build/


================================================
FILE: .travis.yml
================================================
language: java
jdk:
  - openjdk8
after_success:
  - ./gradlew coveralls

addons:
  hosts:
    - travis-issue-5227-workaround
  hostname: travis-issue-5227-workaround


================================================
FILE: COPYING
================================================
Copyright (c) 2014, Yubico AB
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-------------------------------

Copyright (c) 2014, Google Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

================================================
FILE: NEWS
================================================
== Version 0.19.12 ==

* Deprecated all classes with note that the library is obsolete. This is planned
  to be the final release of java-u2flib-server.


== Version 0.19.11 ==

* Bumped Guava dependency to version [24.1.1,30) in response to CVE-2018-10237


== Version 0.19.10 ==

* Bumped Jackson dependency to version 2.11.0 in response to CVEs:
 ** CVE-2020-9546
 ** CVE-2020-10672
 ** CVE-2020-10969
 ** CVE-2020-11620


== Version 0.19.9 ==

* Bumped Jackson dependency to version 2.9.10.3 in response to CVE-2019-20330 and CVE-2020-8840


== Version 0.19.8 ==

* Bumped Jackson dependency to version 2.9.10.1 which has patched CVE-2019-16942


== Version 0.19.7 ==

* Bumped Jackson dependency to version 2.9.10 which has patched CVE-2019-16335, CVE-2019-14540


== Version 0.19.6 ==

* Bumped Jackson dependency to version 2.9.9.3 which fixes a regression in 2.9.9.2


== Version 0.19.5 ==

* Bumped Jackson dependency to version 2.9.9.2 which has patched CVE-2019-12814, CVE-2019-14439, CVE-2019-14379


== Version 0.19.4 ==

* Bumped Jackson dependency to version 2.9.9 which has patched CVE-2019-12086


== Version 0.19.3 ==

Bug fixes:

* Use BouncyCastle security provider explicitly


== Version 0.19.2 ==

* Bumped Jackson dependency version to 2.9.8 which has patched CVE-2018-19360, CVE-2018-19362 and CVE-2018-19361


== Version 0.19.1 ==

* Bumped Jackson dependency version to 2.9.7 which has patched CVE-2018-7489 and CVE-2017-7525


== Version 0.19.0 ==

Breaking changes:

* Overhauled exception hierarchy
 ** New exception class: `U2fCeremonyException`
 ** New exception class: `U2fRegistrationException extends U2fCeremonyException`
 ** New exception class: `U2fAuthenticationException extends U2fCeremonyException`
 ** The following exception classes now extend `U2fAuthenticationException`:
  *** `DeviceCompromisedException`
  *** `InvalidDeviceCounterException`
  *** `NoEligableDevicesException`
  *** `NoEligibleDevicesException`
 ** `U2fBadConfigurationException` is now a checked exception
 ** `U2fBadInputException` is now a checked exception, and is no longer thrown directly by the methods of `U2F`.
  *** Methods of `U2F` now catch this exception and wrap it in a `U2fRegistrationException` or ``U2fAuthenticationException`.
* `DeviceRegistration.getAttestationCertificate()` now returns `null` instead of throwing `NoSuchFieldException`
* `static ClientData.getString(JsonNode, String)` now throws `U2fBadInputException` instead of `NullPointerException`, or if the returned field is not a `String` value
* Some `AssertionError`s and `IllegalArgumentException`s are now `U2fBadInputException`s instead


Improvements:

* `BouncyCastleCrypto` now throws more descriptive exceptions


Bug fixes:

* Improved error handling in client data input validation
 ** Thanks to Nicholas Wilson for the contribution, see https://github.com/Yubico/java-u2flib-server/pull/25


== Version 0.18.1 ==

* Lombok now longer leaks into runtime dependencies


== Version 0.18.0 ==

=== u2flib-server-core ===

Breaking changes:

* "Authenticate" renamed to "sign" everywhere in `u2flib-server-core`
** Classes `AuthenticateRequest` renamed to `SignRequest`
** Class `AuthenticateRequestData` renamed to `SignRequestData`
** Class `AuthenticateResponse` renamed to `SignResponse`
** Method `Client.authenticate` renamed to `sign`
** Class `RawAuthenticateResponse` renamed to `RawSignResponse`
** Method `SoftKey.authenticate` renamed to `sign`
** Method `U2F.finishAuthentication` renamed to `finishSignature`
** Method `U2F.startAuthentication` renamed to `startSignature`
** Method `U2fPrimitives.finishAuthentication` renamed to `finishSignature`
** Method `U2fPrimitives.startAuthenticateion` renamed to `startSignature`
* Constants `AUTHENTICATE_TYP` and `REGISTER_TYPE` in `U2fPrimitives` are
  now private

== Version 0.17.1 ==

* u2flib-server-attestation module now uses SLF4J logging instead of
  `Throwable.printStackTrace`


== Version 0.17.0 ==

=== u2flib-server-core ===

Breaking changes:

* Field `RegisterRequestData.authenticateRequests: List<AuthenticateRequest>`
 replaced by field `registeredKeys: List<RegisteredKey>`

Additions:

* Fields added to class `AuthenticateRequestData`:
  * `challenge: String`
  * `appId: String`
* New class `RegisteredKey`
* Field `appId: String` added to `RegisterRequestData`

=== u2flib-server-demo ===

* `u2f-api.js` upgraded from version 1.0 to 1.1
* JS calls in views updated to work with version 1.1 of the JS API
* All views except `loginIndex` and `registerIndex` are now rendered via
  templates
* Navigation links added to all views
* Error feedback improved


== Version 0.13.1 (unreleased) ==

* Changed demo server URL to `localhost:8080`.
* Added the method `ClientData.getString` to get arbitrary clientData fields.
* Added u2flib-server-attestation for device attestation and metadata.


== Version 0.13.0 ==

* Added built-in support for multiple devices per user.
* Fixed demo server bug when running from jar. Thanks to axianx.


================================================
FILE: README
================================================
== java-u2flib-server

NOTE: _OBSOLETE: This project is no longer maintained.
U2F has been superseded by https://www.w3.org/TR/webauthn/[Web Authentication],
and this project is superseded by https://github.com/Yubico/java-webauthn-server/[java-webauthn-server].
We recommend using WebAuthn instead._

image:https://travis-ci.org/Yubico/java-u2flib-server.svg?branch=master["Build Status", link="https://travis-ci.org/Yubico/java-u2flib-server"]
image:https://coveralls.io/repos/github/Yubico/java-u2flib-server/badge.svg["Coverage Status", link="https://coveralls.io/github/Yubico/java-u2flib-server"]

Server-side https://developers.yubico.com/U2F[U2F] library for Java. Provides functionality for registering
U2F devices and authenticating with said devices.

== Migrating to WebAuthn

See the https://github.com/Yubico/java-webauthn-server#migrating-from-u2f[Migrating from U2F] section
in the https://github.com/Yubico/java-webauthn-server/[java-webauthn-server] documentation.

=== Dependency

Maven:
[source, xml]
 <dependency>
   <groupId>com.yubico</groupId>
   <artifactId>u2flib-server-core</artifactId>
   <version>0.19.12</version>
 </dependency>

Gradle:
[source, groovy]
 repositories{ mavenCentral() }
 dependencies {
   compile 'com.yubico:u2flib-server-core:0.19.12'
 }

=== Example Usage
NOTE: Make sure that you have read https://developers.yubico.com/U2F/Libraries/Using_a_library.html[Using a U2F library] before continuing.

[source, java]
----

private abstract Iterable<DeviceRegistration> getRegistrations(String username);

@GET
public View startAuthentication(String username) throws NoEligibleDevicesException {

    // Generate a challenge for each U2F device that this user has registered
    SignRequestData requestData
        = u2f.startSignature(SERVER_ADDRESS, getRegistrations(username));

    // Store the challenges for future reference
    requestStorage.put(requestData.getRequestId(), requestData.toJson());

    // Return an HTML page containing the challenges
    return new AuthenticationView(requestData.toJson(), username);
}

@POST
public String finishAuthentication(SignResponse response, String username) throws
        DeviceCompromisedException {

    // Get the challenges that we stored when starting the authentication
    SignRequestData signRequest
        = requestStorage.remove(response.getRequestId());

    // Verify the that the given response is valid for one of the registered devices
    u2f.finishSignature(signRequest,
                             response,
                             getRegistrations(username));

    return "Successfully authenticated!";
}
----

In the above example `getRegistrations()` will return the U2F devices currently associated with a given user.
This is most likely stored in a database. 
See link:u2flib-server-demo[`u2flib-server-demo`] for a complete demo server (including registration and storage of U2F devices).

=== JavaDoc
JavaDoc can be found at https://developers.yubico.com/java-u2flib-server[developers.yubico.com/java-u2flib-server].


=== Attestation
The attestation module (`u2flib-server-attestation`) enables you to restrict registrations to certain U2F devices (e.g. devices made by a specific vendor). It can also provide metadata for devices.

=== Serialization
All relevant classes implement `Serializable`, so instead of using `toJson()`, you can use Java's built in serialization mechanism.
Internally the classes use Jackson to serialize to and from JSON, and the ObjectMapper from Jackson can be used.


================================================
FILE: buildSrc/build.gradle
================================================
apply plugin: 'groovy'

repositories {
  mavenCentral()
}

dependencies {
  compile(
    'commons-io:commons-io:2.5',
    'info.solidsoft.gradle.pitest:gradle-pitest-plugin:1.1.11',
  )
}


================================================
FILE: buildSrc/src/main/groovy/com/yubico/gradle/pitest/tasks/PitestMergeTask.groovy
================================================
package com.yubico.gradle.pitest.tasks

import groovy.xml.XmlUtil

import info.solidsoft.gradle.pitest.PitestTask
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction

/**
 * Merges PIT <code>mutations.xml</code> reports from all subprojects into one
 * report in the parent project.
 */
class PitestMergeTask extends DefaultTask {

  @OutputFile
  def File destinationFile = project.file("${project.buildDir}/reports/pitest/mutations.xml")

  PitestMergeTask() {
    project.subprojects.each { subproject ->
      subproject.tasks.withType(PitestTask).each { pitestTask ->
        inputs.files pitestTask.outputs.files
      }
    }
  }

  def Set<File> findMutationsXmlFiles(File f, Set<File> found) {
    if (f.isDirectory()) {
      Set<File> result = found
      for (File child : f.listFiles()) {
        result = findMutationsXmlFiles(child, result)
      }
      return result
    } else if (f.getName().endsWith(".xml")) {
      return found.plus(f)
    } else {
      return found
    }
  }

  def getMutations(File mutationsXmlFile) {
    return new XmlParser().parseText(mutationsXmlFile.text).children()
  }

  @TaskAction
  void merge() {
    Set<File> mutationsXmlFiles = new HashSet<File>()
    inputs.files.each { File f ->
      mutationsXmlFiles = findMutationsXmlFiles(f, mutationsXmlFiles)
    }

    def rootNode = new XmlParser().createNode(null, 'mutations', [:])

    mutationsXmlFiles.each {
      getMutations(it).each { mutation ->
        rootNode.append(mutation)
      }
    }

    if (!destinationFile.exists()) {
      destinationFile.createNewFile()
    }
    def os = destinationFile.newOutputStream()
    XmlUtil.serialize(rootNode, os)
    os.close()
  }

}


================================================
FILE: dev-util/example-authentication.py
================================================
#!/usr/bin/python3
#
# Scratchpad for working with raw U2F messages, useful for creating raw messages as test data.
# Example keys from secion 8.2 of
# https://fidoalliance.org/specs/fido-u2f-v1.0-nfc-bt-amendment-20150514/fido-u2f-raw-message-formats.html#authentication-response-message-success

from binascii import hexlify, unhexlify
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec

sig_alg = ec.ECDSA(hashes.SHA256())

private_key_hex = 'ffa1e110dde5a2f8d93c4df71e2d4337b7bf5ddb60c75dc2b6b81433b54dd3c0'
public_key_hex = '04d368f1b665bade3c33a20f1e429c7750d5033660c019119d29aa4ba7abc04aa7c80a46bbe11ca8cb5674d74f31f8a903f6bad105fb6ab74aefef4db8b0025e1d'

example_payload_hex = '4b0be934baebb5d12d26011b69227fa5e86df94e7d94aa2949a89f2d493992ca0100000001ccd6ee2e47baef244d49a222db496bad0ef5b6f93aa7cc4d30c4821b3b9dbc57'
example_signature_hex = '304402204b5f0cd17534cedd8c34ee09570ef542a353df4436030ce43d406de870b847780220267bb998fac9b7266eb60e7cb0b5eabdfd5ba9614f53c7b22272ec10047a923f'

s = int(private_key_hex, 16)
x = int(public_key_hex[2:66], 16)
y = int(public_key_hex[66:], 16)

keynums = ec.EllipticCurvePrivateNumbers(s, ec.EllipticCurvePublicNumbers(x, y, ec.SECP256R1()))
private_key = keynums.private_key(default_backend())
public_key = private_key.public_key()

# Just ensure that we can successfully verify the example signature against the example key
public_key.verify(unhexlify(example_signature_hex), unhexlify(example_payload_hex), sig_alg)


# Successful authentication message, but with invalid user presence byte
payload_hex = '4b0be934baebb5d12d26011b69227fa5e86df94e7d94aa2949a89f2d493992ca0000000001ccd6ee2e47baef244d49a222db496bad0ef5b6f93aa7cc4d30c4821b3b9dbc57'
payload_signature = private_key.sign(unhexlify(payload_hex), sig_alg)

print("Private key:", private_key_hex)
print("Public key:", public_key_hex)
print("Signing payload:", payload_hex)
print("Signature:", hexlify(payload_signature))


================================================
FILE: dev-util/example-registration.py
================================================
#!/usr/bin/python3
#
# Scratchpad for working with raw U2F messages, useful for creating raw messages as test data.
# Example keys from secion 8.1 of
# https://fidoalliance.org/specs/fido-u2f-v1.0-nfc-bt-amendment-20150514/fido-u2f-raw-message-formats.html#registration-example

from base64 import urlsafe_b64encode as b64encode
from binascii import hexlify, unhexlify
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec

def hextokeys(private_key_hex, public_key_hex):
  s = int(private_key_hex, 16)
  x = int(public_key_hex[2:66], 16)
  y = int(public_key_hex[66:], 16)

  keynums = ec.EllipticCurvePrivateNumbers(s, ec.EllipticCurvePublicNumbers(x, y, ec.SECP256R1()))
  private_key = keynums.private_key(default_backend())
  return (private_key, private_key.public_key())

def make_signature_base(application_parameter_hex, client_data_json, key_handle_hex, user_public_key_hex):
  challenge_parameter_hex = make_challenge_parameter_hex(client_data_json)
  return '00' + application_parameter_hex + challenge_parameter_hex + key_handle_hex + user_public_key_hex

def sign(private_key, message_hex):
  return private_key.sign(message_hex, sig_alg)

def make_challenge_parameter_hex(client_data_json):
  return sha256(bytes(client_data_json, 'UTF-8')).hex()

def make_registration_request_message(user_public_key_hex, key_handle_hex, attestation_certificate_hex, signature_hex):
  return '05' + user_public_key_hex + hex(len(key_handle_hex) // 2)[2:] + key_handle_hex + attestation_certificate_hex + signature_hex

def sha256(data):
  hasher = hashes.Hash(hashes.SHA256(), default_backend())
  hasher.update(data)
  return hasher.finalize()

def byteStringToDecimalBytes(data):
  return [int(b) for b in data]

def byteStringToDecimalSignedBytes(data):
  return [i if i < 128 else i - 256 for i in byteStringToDecimalBytes(data)]

sig_alg = ec.ECDSA(hashes.SHA256())

private_attestation_key_hex = 'f3fccc0d00d8031954f90864d43c247f4bf5f0665c6b50cc17749a27d1cf7664'
public_attestation_key_hex = '048d617e65c9508e64bcc5673ac82a6799da3c1446682c258c463fffdf58dfd2fa3e6c378b53d795c4a4dffb4199edd7862f23abaf0203b4b8911ba0569994e101'
attestation_certificate_hex = '3082013c3081e4a003020102020a47901280001155957352300a06082a8648ce3d0403023017311530130603550403130c476e756262792050696c6f74301e170d3132303831343138323933325a170d3133303831343138323933325a3031312f302d0603550403132650696c6f74476e756262792d302e342e312d34373930313238303030313135353935373335323059301306072a8648ce3d020106082a8648ce3d030107034200048d617e65c9508e64bcc5673ac82a6799da3c1446682c258c463fffdf58dfd2fa3e6c378b53d795c4a4dffb4199edd7862f23abaf0203b4b8911ba0569994e101300a06082a8648ce3d0403020347003044022060cdb6061e9c22262d1aac1d96d8c70829b2366531dda268832cb836bcd30dfa0220631b1459f09e6330055722c8d89b7f48883b9089b88d60d1d9795902b30410df'

private_user_key_hex = '9a9684b127c5e3a706d618c86401c7cf6fd827fd0bc18d24b0eb842e36d16df1'
public_user_key_hex = '04b174bc49c7ca254b70d2e5c207cee9cf174820ebd77ea3c65508c26da51b657c1cc6b952f8621697936482da0a6d3d3826a59095daf6cd7c03e2e60385d2f6d9'
key_handle_hex = '2a552dfdb7477ed65fd84133f86196010b2215b57da75d315b7b9e8fe2e3925a6019551bab61d16591659cbaf00b4950f7abfe6660e2e006f76868b772d70c25'

client_data = '{"typ":"navigator.id.finishEnrollment","challenge":"vqrS6WXDe1JUs5_c3i4-LkKIHRr-3XVb3azuA5TifHo","cid_pubkey":{"kty":"EC","crv":"P-256","x":"HzQwlfXX7Q4S5MtCCnZUNBw3RMzPO9tOyWjBqRl4tJ8","y":"XVguGFLIZx1fXg3wNqfdbn75hi4-_7-BxhMljw42Ht4"},"origin":"http://example.com"}'

application_parameter_hex = 'f0e6a6a97042a4f1f1c87f5f7d44315b2d852c2df5c7991cc66241bf7072d1c4'

# 1 byte RFU = 0x00
# 32 bytes application parameter
# 32 bytes challenge parameter
# L bytes key handle
# 65 bytes user public key
example_signature_base_hex = make_signature_base(application_parameter_hex, client_data, key_handle_hex, public_user_key_hex)
example_signature_hex = '304502201471899bcc3987e62e8202c9b39c33c19033f7340352dba80fcab017db9230e402210082677d673d891933ade6f617e5dbde2e247e70423fd5ad7804a6d3d3961ef871'

# 1 reserved byte = 0x05
# 65 bytes user public key
# 1 byte key handle length = L
# L bytes key handle
# X.509 attestation certificate
# X bytes = above signature
example_response_message_hex = '05' + public_user_key_hex + '40' + key_handle_hex + attestation_certificate_hex + example_signature_hex



(private_attestation_key, public_attestation_key) = hextokeys(private_attestation_key_hex, public_attestation_key_hex)

(private_user_key, public_user_key) = hextokeys(private_user_key_hex, public_user_key_hex)

# Just ensure that we can successfully verify the example signature against the example key
public_attestation_key.verify(unhexlify(example_signature_hex), unhexlify(example_signature_base_hex), sig_alg)


different_client_data = '{"typ":"navigator.id.launchNukes","challenge":"vqrS6WXDe1JUs5_c3i4-LkKIHRr-3XVb3azuA5TifHo","origin":"http://example.com"}'
different_challenge_parameter_hex = sha256(bytes(different_client_data, 'UTF-8')).hex()

public_attestation_key.verify(private_attestation_key.sign(b'Hello, World!', sig_alg), b'Hello, World!', sig_alg)

def print_results(private_user_key_hex, public_user_key_hex, private_attestation_key, application_parameter_hex, client_data_json, key_handle_hex, user_public_key_hex):
  signature_base_hex = make_signature_base(application_parameter_hex, client_data_json, key_handle_hex, user_public_key_hex)
  signature = sign(private_attestation_key, unhexlify(signature_base_hex))
  message = make_registration_request_message(public_user_key_hex, key_handle_hex, attestation_certificate_hex, signature.hex())

  public_attestation_key.verify(signature, unhexlify(signature_base_hex), sig_alg)

  print("Private key:\n ", private_user_key_hex)
  print("Public key:\n ", public_user_key_hex)
  print("App ID:\n ", application_parameter_hex)
  print("Client data:\n ", client_data_json)
  print("Data to sign:\n ", signature_base_hex)
  print("Signature:\n ", signature.hex())
  print("Registration request message:\n ", message)
  print("Registration request message Base64:\n ", b64encode(unhexlify(message)))

print_results(
  private_user_key_hex,
  public_user_key_hex,
  private_attestation_key,
  application_parameter_hex,
  different_client_data,
  key_handle_hex,
  public_user_key_hex
)


================================================
FILE: lombok.config
================================================
config.stopBubbling = true
lombok.addLombokGeneratedAnnotation = true


================================================
FILE: pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.yubico</groupId>
    <artifactId>u2flib-server-parent</artifactId>
    <packaging>pom</packaging>
    <version>0.19.12</version>
    <name>U2F parent</name>
    <description>Java server-side library for U2F</description>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <organization>
        <name>Yubico</name>
        <url>https://www.yubico.com/</url>
    </organization>
    <url>https://developers.yubico.com/</url>
    <developers>
        <developer>
            <id>dain</id>
            <name>Dain Nilsson</name>
            <email>dain@yubico.com</email>
        </developer>
        <developer>
            <id>emil</id>
            <name>Emil Lundberg</name>
            <email>emil@yubico.com</email>
        </developer>
    </developers>
    <licenses>
        <license>
            <name>BSD-license</name>
            <comments>Revised 2-clause BSD license</comments>
        </license>
    </licenses>
    <scm>
        <url>scm:git:git://github.com/Yubico/java-u2flib-server.git</url>
        <connection>scm:git:git://github.com/Yubico/java-u2flib-server.git</connection>
        <developerConnection>scm:git:ssh://git@github.com/Yubico/java-u2flib-server.git</developerConnection>
        <tag>HEAD</tag>
    </scm>

    <modules>
        <module>u2flib-server-core</module>
        <module>u2flib-server-demo</module>
        <module>u2flib-server-attestation</module>
    </modules>

    <distributionManagement>
        <repository>
            <id>sonatype-nexus-staging</id>
            <name>Nexus Staging Repo</name>
            <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
        </repository>
        <snapshotRepository>
            <id>sonatype-nexus-snapshots</id>
            <name>Nexus Snapshot Repo</name>
            <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
        </snapshotRepository>
    </distributionManagement>

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.25</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>2.8.47</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-release-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <localCheckout>true</localCheckout>
                    <pushChanges>false</pushChanges>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>2.1.2</version>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>jar-no-fork</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <version>2.8.1</version>
                <configuration>
                    <excludePackageNames>*.crypto;*.json;*.key</excludePackageNames>
                </configuration>
                <executions>
                    <execution>
                        <id>attach-javadoc</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.sonatype.plugins</groupId>
                <artifactId>nexus-staging-maven-plugin</artifactId>
                <version>1.6.3</version>
                <extensions>true</extensions>
                <configuration>
                    <serverId>ossrh</serverId>
                    <nexusUrl>https://oss.sonatype.org/</nexusUrl>
                    <autoReleaseAfterClose>true</autoReleaseAfterClose>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.pitest</groupId>
                <artifactId>pitest-maven</artifactId>
                <version>1.2.2</version>
                <configuration>
                    <timestampedReports>false</timestampedReports>
                </configuration>
            </plugin>

        </plugins>
    </build>
    <profiles>
        <profile>
            <id>release-sign-artifacts</id>
            <activation>
                <property>
                    <name>performRelease</name>
                    <value>true</value>
                </property>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-gpg-plugin</artifactId>
                        <version>1.6</version>
                        <executions>
                            <execution>
                                <id>sign-artifacts</id>
                                <phase>verify</phase>
                                <goals>
                                    <goal>sign</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <profile>
            <id>test-coveralls</id>
            <activation>
                <property>
                    <name>env.COVERALLS</name>
                    <value>true</value>
                </property>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.jacoco</groupId>
                        <artifactId>jacoco-maven-plugin</artifactId>
                        <version>0.7.5.201505241946</version>
                        <executions>
                            <execution>
                                <id>prepare-agent</id>
                                <goals>
                                    <goal>prepare-agent</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.eluder.coveralls</groupId>
                        <artifactId>coveralls-maven-plugin</artifactId>
                        <version>3.0.1</version>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

</project>


================================================
FILE: u2flib-server-attestation/README.adoc
================================================
== Device attestation  module
Module for verifying attestation certificates and providing additional device metadata.

This is useful if you want to:

 - Restrict which types of devices that can be registered with your server
 - Give users rich data about their registered devices, such as:
   * The vendor and model name
   * An image of the device model


=== Dependency

Maven:
[source, xml]
 <dependency>
   <groupId>com.yubico</groupId>
   <artifactId>u2flib-server-attestation</artifactId>
   <version>0.19.1</version>
 </dependency>

Gradle:
[source, groovy]
 repositories{ mavenCentral() }
 dependencies {
   compile 'com.yubico:u2flib-server-attestation:0.19.1'
 }


=== Usage
The Attestation class lets you know if the attestation certificate from the registration is trusted, and provides you with metadata about the vendor as well as the device itself.

[source,java]
----
DeviceRegistration registration = U2F.finishRegistration(request, response);
Attestation attestation = metadataService.getAttestation(
    registration.getAttestationCertificate()
);

// Check if the device is trusted
assert attestation.isTrusted();

// Check that the vendor is Yubico
assert attestation.getVendorProperties().get("name").equals("Yubico");

// Get device name and image
String deviceName = attestation.getDeviceProperties().get("displayName");
String imageUrl = attestation.getDeviceProperties().get("imageUrl");
----


================================================
FILE: u2flib-server-attestation/build.gradle
================================================
description = 'U2F attestation'

dependencies {

  compile(
    project(':u2flib-server-core'),
  )

}


================================================
FILE: u2flib-server-attestation/gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists


================================================
FILE: u2flib-server-attestation/gradlew
================================================
#!/usr/bin/env sh

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
    else
        PRG=`dirname "$PRG"`"/$link"
    fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn () {
    echo "$*"
}

die () {
    echo
    echo "$*"
    echo
    exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
  NONSTOP* )
    nonstop=true
    ;;
esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
    MAX_FD_LIMIT=`ulimit -H -n`
    if [ $? -eq 0 ] ; then
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
            MAX_FD="$MAX_FD_LIMIT"
        fi
        ulimit -n $MAX_FD
        if [ $? -ne 0 ] ; then
            warn "Could not set maximum file descriptor limit: $MAX_FD"
        fi
    else
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
    fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
    JAVACMD=`cygpath --unix "$JAVACMD"`

    # We build the pattern for arguments to be converted via cygpath
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
    SEP=""
    for dir in $ROOTDIRSRAW ; do
        ROOTDIRS="$ROOTDIRS$SEP$dir"
        SEP="|"
    done
    OURCYGPATTERN="(^($ROOTDIRS))"
    # Add a user-defined pattern to the cygpath arguments
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
    fi
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    i=0
    for arg in "$@" ; do
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option

        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=$((i+1))
    done
    case $i in
        (0) set -- ;;
        (1) set -- "$args0" ;;
        (2) set -- "$args0" "$args1" ;;
        (3) set -- "$args0" "$args1" "$args2" ;;
        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
    esac
fi

# Escape application args
save () {
    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
    echo " "
}
APP_ARGS=$(save "$@")

# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"

# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
  cd "$(dirname "$0")"
fi

exec "$JAVACMD" "$@"


================================================
FILE: u2flib-server-attestation/gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windows variants

if not "%OS%" == "Windows_NT" goto win9xME_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: u2flib-server-attestation/pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>u2flib-server-parent</artifactId>
        <groupId>com.yubico</groupId>
        <version>0.19.12</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>u2flib-server-attestation</artifactId>
    <name>U2F attestation</name>

    <dependencies>
        <dependency>
            <groupId>com.yubico</groupId>
            <artifactId>u2flib-server-core</artifactId>
            <version>0.19.12</version>
        </dependency>
    </dependencies>

</project>


================================================
FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/Attestation.java
================================================
/* Copyright 2015 Yubico */

package com.yubico.u2f.attestation;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;

import java.io.Serializable;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
import lombok.Getter;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
@Getter
public class Attestation implements Serializable {
    private final String metadataIdentifier;
    private final Map<String, String> vendorProperties;
    private final Map<String, String> deviceProperties;
    private final Set<Transport> transports;

    private Attestation() {
        metadataIdentifier = null;
        vendorProperties = null;
        deviceProperties = null;
        transports = Sets.immutableEnumSet(null);
    }

    public Attestation(String metadataIdentifier, Map<String, String> vendorProperties, Map<String, String> deviceProperties, Set<Transport> transports) {
        this.metadataIdentifier = metadataIdentifier;
        this.vendorProperties = vendorProperties == null ? ImmutableMap.<String, String>of() : ImmutableMap.copyOf(vendorProperties);
        this.deviceProperties = deviceProperties == null ? ImmutableMap.<String, String>of() : ImmutableMap.copyOf(deviceProperties);
        this.transports = Sets.immutableEnumSet(transports == null ? ImmutableSet.<Transport>of() : transports);
    }

    public boolean isTrusted() {
        return metadataIdentifier != null;
    }

}


================================================
FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/DeviceMatcher.java
================================================
/* Copyright 2015 Yubico */

package com.yubico.u2f.attestation;

import com.fasterxml.jackson.databind.JsonNode;

import java.security.cert.X509Certificate;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public interface DeviceMatcher {
    public boolean matches(X509Certificate attestationCertificate, JsonNode parameters);
}


================================================
FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/MetadataObject.java
================================================
/* Copyright 2015 Yubico */

package com.yubico.u2f.attestation;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.yubico.u2f.data.messages.json.JsonSerializable;
import com.yubico.u2f.exceptions.U2fBadInputException;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import lombok.EqualsAndHashCode;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
@JsonIgnoreProperties(ignoreUnknown = true)
@EqualsAndHashCode(of = { "data" })
public class MetadataObject extends JsonSerializable {
    private static final TypeReference<Map<String, String>> MAP_STRING_STRING_TYPE = new TypeReference<Map<String, String>>() {
    };
    private static final TypeReference<List<String>> LIST_STRING_TYPE = new TypeReference<List<String>>() {
    };
    private static final TypeReference<List<JsonNode>> LIST_JSONNODE_TYPE = new TypeReference<List<JsonNode>>() {
    };

    private final transient JsonNode data;

    private final String identifier;
    private final long version;
    private final Map<String, String> vendorInfo;
    private final List<String> trustedCertificates;
    private final List<JsonNode> devices;

    @JsonCreator
    public MetadataObject(JsonNode data) throws U2fBadInputException {
        this.data = data;
        try {
            vendorInfo = OBJECT_MAPPER.readValue(data.get("vendorInfo").traverse(), MAP_STRING_STRING_TYPE);
            trustedCertificates = OBJECT_MAPPER.readValue(data.get("trustedCertificates").traverse(), LIST_STRING_TYPE);
            devices = OBJECT_MAPPER.readValue(data.get("devices").traverse(), LIST_JSONNODE_TYPE);
        } catch (JsonMappingException e) {
            throw new U2fBadInputException("Invalid JSON data", e);
        } catch (JsonParseException e) {
            throw new U2fBadInputException("Invalid JSON data", e);
        } catch (IOException e) {
            throw new U2fBadInputException("Invalid JSON data", e);
        }

        identifier = data.get("identifier").asText();
        version = data.get("version").asLong();
    }

    @Override
    public String toJson() {
        return data.toString();
    }

    public String getIdentifier() {
        return identifier;
    }

    public long getVersion() {
        return version;
    }

    public Map<String, String> getVendorInfo() {
        return vendorInfo;
    }

    public List<String> getTrustedCertificates() {
        return trustedCertificates;
    }

    public List<JsonNode> getDevices() {
        return MoreObjects.firstNonNull(devices, ImmutableList.<JsonNode>of());
    }

    public static List<MetadataObject> parseFromJson(String jsonData) throws U2fBadInputException {
        JsonNode items;
        try {
            items = OBJECT_MAPPER.readValue(jsonData, JsonNode.class);
            if (!items.isArray()) {
                items = OBJECT_MAPPER.createArrayNode().add(items);
            }
        } catch (IOException e) {
            throw new U2fBadInputException("Malformed data", e);
        }

        ImmutableList.Builder<MetadataObject> objects = ImmutableList.builder();
        for (JsonNode item : items) {
            objects.add(MetadataObject.fromJson(item.toString()));
        }
        return objects.build();
    }

    public static MetadataObject fromJson(String json) throws U2fBadInputException {
        try {
            return new MetadataObject(OBJECT_MAPPER.readTree(json));
        } catch (IOException e) {
            throw new U2fBadInputException("Malformed data", e);
        }
    }
}


================================================
FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/MetadataResolver.java
================================================
/* Copyright 2015 Yubico */

package com.yubico.u2f.attestation;

import java.security.cert.X509Certificate;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public interface MetadataResolver {
    MetadataObject resolve(X509Certificate attestationCertificate);
}


================================================
FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/MetadataService.java
================================================
/* Copyright 2015 Yubico */

package com.yubico.u2f.attestation;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Charsets;
import com.google.common.base.Predicates;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.hash.Hashing;
import com.google.common.io.CharStreams;
import com.google.common.io.Closeables;
import com.yubico.u2f.attestation.matchers.ExtensionMatcher;
import com.yubico.u2f.attestation.matchers.FingerprintMatcher;
import com.yubico.u2f.attestation.resolvers.SimpleResolver;
import com.yubico.u2f.exceptions.U2fBadInputException;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class MetadataService {
    private static final Logger logger = LoggerFactory.getLogger(MetadataService.class);

    public static final String SELECTORS = "selectors";
    private static final String SELECTOR_TYPE = "type";
    private static final String SELECTOR_PARAMETERS = "parameters";

    private static final String TRANSPORTS = "transports";
    private static final String TRANSPORTS_EXT_OID = "1.3.6.1.4.1.45724.2.1.1";

    public static final Map<String, DeviceMatcher> DEFAULT_DEVICE_MATCHERS = ImmutableMap.of(
            ExtensionMatcher.SELECTOR_TYPE, new ExtensionMatcher(),
            FingerprintMatcher.SELECTOR_TYPE, new FingerprintMatcher()
    );

    private static MetadataResolver createDefaultMetadataResolver() {
        SimpleResolver resolver = new SimpleResolver();
        InputStream is = null;
        try {
            is = MetadataService.class.getResourceAsStream("/metadata.json");
            resolver.addMetadata(CharStreams.toString(new InputStreamReader(is, Charsets.UTF_8)));
        } catch (IOException e) {
            logger.error("createDefaultMetadataResolver failed", e);
        } catch (CertificateException e) {
            logger.error("createDefaultMetadataResolver failed", e);
        } catch (U2fBadInputException e) {
            logger.error("createDefaultMetadataResolver failed", e);
        } finally {
            Closeables.closeQuietly(is);
        }
        return resolver;
    }

    private final Attestation unknownAttestation = new Attestation(null, null, null, null);
    private final MetadataResolver resolver;
    private final Map<String, DeviceMatcher> matchers = new HashMap<String, DeviceMatcher>();
    private final Cache<String, Attestation> cache;

    public MetadataService(MetadataResolver resolver, Cache<String, Attestation> cache, Map<String, ? extends DeviceMatcher> matchers) {
        this.resolver = resolver != null ? resolver : createDefaultMetadataResolver();
        this.cache = cache != null ? cache : CacheBuilder.newBuilder().<String, Attestation>build();
        if (matchers == null) {
            matchers = DEFAULT_DEVICE_MATCHERS;
        }
        this.matchers.putAll(matchers);
    }

    public MetadataService() {
        this(null, null, null);
    }

    public MetadataService(MetadataResolver resolver) {
        this(resolver, null, null);
    }

    public MetadataService(MetadataResolver resolver, Map<String, ? extends DeviceMatcher> matchers) {
        this(resolver, null, matchers);
    }

    public MetadataService(MetadataResolver resolver, Cache<String, Attestation> cache) {
        this(resolver, cache, null);
    }

    public void registerDeviceMatcher(String matcherType, DeviceMatcher matcher) {
        matchers.put(matcherType, matcher);
    }

    private boolean deviceMatches(JsonNode selectors, X509Certificate attestationCertificate) {
        if (selectors != null && !selectors.isNull()) {
            for (JsonNode selector : selectors) {
                DeviceMatcher matcher = matchers.get(selector.get(SELECTOR_TYPE).asText());
                if (matcher != null && matcher.matches(attestationCertificate, selector.get(SELECTOR_PARAMETERS))) {
                    return true;
                }
            }
            return false;
        }
        return true; //Match if selectors is null or missing.
    }

    public Attestation getCachedAttestation(String attestationCertificateFingerprint) {
        return cache.getIfPresent(attestationCertificateFingerprint);
    }

    public Attestation getAttestation(final X509Certificate attestationCertificate) {
        if (attestationCertificate == null) {
            return unknownAttestation;
        }
        try {
            String fingerprint = Hashing.sha1().hashBytes(attestationCertificate.getEncoded()).toString();
            return cache.get(fingerprint, new Callable<Attestation>() {
                @Override
                public Attestation call() throws Exception {
                    return lookupAttestation(attestationCertificate);
                }
            });
        } catch (Exception e) {
            return unknownAttestation;
        }
    }

    private Attestation lookupAttestation(X509Certificate attestationCertificate) {
        MetadataObject metadata = resolver.resolve(attestationCertificate);
        Map<String, String> vendorProperties = null;
        Map<String, String> deviceProperties = null;
        String identifier = null;
        int transports = 0;
        if (metadata != null) {
            identifier = metadata.getIdentifier();
            vendorProperties = Maps.filterValues(metadata.getVendorInfo(), Predicates.notNull());
            for (JsonNode device : metadata.getDevices()) {
                if (deviceMatches(device.get(SELECTORS), attestationCertificate)) {
                    JsonNode transportNode = device.get(TRANSPORTS);
                    if(transportNode != null) {
                        transports = transportNode.asInt(0);
                    }
                    ImmutableMap.Builder<String, String> devicePropertiesBuilder = ImmutableMap.builder();
                    for (Map.Entry<String, JsonNode> deviceEntry : Lists.newArrayList(device.fields())) {
                        JsonNode value = deviceEntry.getValue();
                        if (value.isTextual()) {
                            devicePropertiesBuilder.put(deviceEntry.getKey(), value.asText());
                        }
                    }
                    deviceProperties = devicePropertiesBuilder.build();
                    break;
                }
            }
        }

        transports |= get_transports(attestationCertificate.getExtensionValue(TRANSPORTS_EXT_OID));

        return new Attestation(identifier, vendorProperties, deviceProperties, Transport.fromInt(transports));
    }

    private int get_transports(byte[] extensionValue) {
        if(extensionValue == null) {
            return 0;
        }

        // Mask out unused bits (shouldn't be needed as they should already be 0).
        int unusedBitMask = 0xff;
        for(int i=0; i < extensionValue[3]; i++) {
            unusedBitMask <<= 1;
        }
        extensionValue[extensionValue.length-1] &= unusedBitMask;

        int transports = 0;
        for(int i=extensionValue.length - 1; i >= 5; i--) {
            byte b = extensionValue[i];
            for(int bi=0; bi < 8; bi++) {
                transports = (transports << 1) | (b & 1);
                b >>= 1;
            }
        }

        return transports;
    }
}


================================================
FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/Transport.java
================================================
package com.yubico.u2f.attestation;

import java.util.Arrays;
import java.util.EnumSet;
import java.util.Set;

/**
 * Created by Dain on 2016-02-18.
 *
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public enum Transport {
    BT_CLASSIC(1),
    BLE(2),
    USB(4),
    NFC(8);

    private final int bitpos;

    Transport(int bitpos) {
        this.bitpos = bitpos;
    }

    public static Set<Transport> fromInt(int bits) {
        EnumSet<Transport> transports = EnumSet.noneOf(Transport.class);
        for(Transport transport : Transport.values()) {
            if((transport.bitpos & bits) != 0) {
                transports.add(transport);
            }
        }

        return transports;
    }

    public static int toInt(Iterable<Transport> transports) {
        int transportsInt = 0;
        for(Transport transport : transports) {
            transportsInt |= transport.bitpos;
        }
        return transportsInt;
    }

    public static int toInt(Transport...transports) {
        return toInt(Arrays.asList(transports));
    }
}


================================================
FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/matchers/ExtensionMatcher.java
================================================
/* Copyright 2015 Yubico */

package com.yubico.u2f.attestation.matchers;

import com.fasterxml.jackson.databind.JsonNode;
import com.yubico.u2f.attestation.DeviceMatcher;
import org.bouncycastle.util.Strings;

import java.security.cert.X509Certificate;
import java.util.Arrays;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class ExtensionMatcher implements DeviceMatcher {
    public static final String SELECTOR_TYPE = "x509Extension";

    private static final String EXTENSION_KEY = "key";
    private static final String EXTENSION_VALUE = "value";

    @Override
    public boolean matches(X509Certificate attestationCertificate, JsonNode parameters) {
        String matchKey = parameters.get(EXTENSION_KEY).asText();
        JsonNode matchValue = parameters.get(EXTENSION_VALUE);
        byte[] extensionValue = attestationCertificate.getExtensionValue(matchKey);
        if (extensionValue != null) {
            if (matchValue == null) {
                return true;
            } else {
                //TODO: Handle long lengths? Verify length?
                String readValue = Strings.fromByteArray(Arrays.copyOfRange(extensionValue, 2, extensionValue.length));
                if (matchValue.asText().equals(readValue)) {
                    return true;
                }
            }
        }
        return false;
    }
}


================================================
FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/matchers/FingerprintMatcher.java
================================================
package com.yubico.u2f.attestation.matchers;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.hash.Hashing;
import com.yubico.u2f.attestation.DeviceMatcher;

import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class FingerprintMatcher implements DeviceMatcher {
    public static final String SELECTOR_TYPE = "fingerprint";

    private static final String FINGERPRINTS_KEY = "fingerprints";

    @Override
    public boolean matches(X509Certificate attestationCertificate, JsonNode parameters) {
        JsonNode fingerprints = parameters.get(FINGERPRINTS_KEY);
        if(fingerprints.isArray()) {
            try {
                String fingerprint = Hashing.sha1().hashBytes(attestationCertificate.getEncoded()).toString().toLowerCase();
                for(JsonNode candidate : fingerprints) {
                    if(fingerprint.equals(candidate.asText().toLowerCase())) {
                        return true;
                    }
                }
            } catch (CertificateEncodingException e) {
                //Fall through to return false.
            }
        }
        return false;
    }
}


================================================
FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/resolvers/SimpleResolver.java
================================================
/* Copyright 2015 Yubico */

package com.yubico.u2f.attestation.resolvers;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.yubico.u2f.attestation.MetadataObject;
import com.yubico.u2f.attestation.MetadataResolver;
import com.yubico.u2f.data.messages.key.util.CertificateParser;
import com.yubico.u2f.exceptions.U2fBadInputException;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class SimpleResolver implements MetadataResolver {
    private static final Logger logger = LoggerFactory.getLogger(SimpleResolver.class);

    private final Multimap<String, X509Certificate> certs = ArrayListMultimap.create();
    private final Map<X509Certificate, MetadataObject> metadata = new HashMap<X509Certificate, MetadataObject>();

    public void addMetadata(String jsonData) throws CertificateException, U2fBadInputException {
        for (MetadataObject object : MetadataObject.parseFromJson(jsonData)) {
            addMetadata(object);
        }
    }

    public void addMetadata(MetadataObject object) throws CertificateException {
        for (String caPem : object.getTrustedCertificates()) {
            X509Certificate caCert = CertificateParser.parsePem(caPem);
            certs.put(caCert.getSubjectDN().getName(), caCert);
            metadata.put(caCert, object);
        }
    }

    @Override
    public MetadataObject resolve(X509Certificate attestationCertificate) {
        String issuer = attestationCertificate.getIssuerDN().getName();
        for (X509Certificate cert : certs.get(issuer)) {
            try {
                attestationCertificate.verify(cert.getPublicKey());
                return metadata.get(cert);
            } catch (CertificateException e) {
                logger.error("resolve failed", e);
            } catch (NoSuchAlgorithmException e) {
                logger.error("resolve failed", e);
            } catch (InvalidKeyException e) {
                logger.error("resolve failed", e);
            } catch (NoSuchProviderException e) {
                logger.error("resolve failed", e);
            } catch (SignatureException e) {
                logger.error("resolve failed", e);
            }
        }
        return null;
    }
}


================================================
FILE: u2flib-server-attestation/src/main/resources/metadata.json
================================================
{
  "identifier": "2fb54029-7613-4f1d-94f1-fb876c14a6fe",
  "version": 4,
  "vendorInfo": {
    "url": "https://yubico.com",
    "imageUrl": "https://developers.yubico.com/U2F/Images/yubico.png",
    "name": "Yubico"
  },
  "trustedCertificates": [
    "-----BEGIN CERTIFICATE-----\nMIIDHjCCAgagAwIBAgIEG1BT9zANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZ\ndWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAw\nMDBaGA8yMDUwMDkwNDAwMDAwMFowLjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290\nIENBIFNlcmlhbCA0NTcyMDA2MzEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\nAoIBAQC/jwYuhBVlqaiYWEMsrWFisgJ+PtM91eSrpI4TK7U53mwCIawSDHy8vUmk\n5N2KAj9abvT9NP5SMS1hQi3usxoYGonXQgfO6ZXyUA9a+KAkqdFnBnlyugSeCOep\n8EdZFfsaRFtMjkwz5Gcz2Py4vIYvCdMHPtwaz0bVuzneueIEz6TnQjE63Rdt2zbw\nnebwTG5ZybeWSwbzy+BJ34ZHcUhPAY89yJQXuE0IzMZFcEBbPNRbWECRKgjq//qT\n9nmDOFVlSRCt2wiqPSzluwn+v+suQEBsUjTGMEd25tKXXTkNW21wIWbxeSyUoTXw\nLvGS6xlwQSgNpk2qXYwf8iXg7VWZAgMBAAGjQjBAMB0GA1UdDgQWBBQgIvz0bNGJ\nhjgpToksyKpP9xv9oDAPBgNVHRMECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAN\nBgkqhkiG9w0BAQsFAAOCAQEAjvjuOMDSa+JXFCLyBKsycXtBVZsJ4Ue3LbaEsPY4\nMYN/hIQ5ZM5p7EjfcnMG4CtYkNsfNHc0AhBLdq45rnT87q/6O3vUEtNMafbhU6kt\nhX7Y+9XFN9NpmYxr+ekVY5xOxi8h9JDIgoMP4VB1uS0aunL1IGqrNooL9mmFnL2k\nLVVee6/VR6C5+KSTCMCWppMuJIZII2v9o4dkoZ8Y7QRjQlLfYzd3qGtKbw7xaF1U\nsG/5xUb/Btwb2X2g4InpiB/yt/3CpQXpiWX/K4mBvUKiGn05ZsqeY1gx4g0xLBqc\nU9psmyPzK+Vsgw2jeRQ5JlKDyqE0hebfC1tvFu0CCrJFcw==\n-----END CERTIFICATE-----"
  ],
  "devices": [
    {
      "deviceId": "1.3.6.1.4.1.41482.1.1",
      "displayName": "Security Key by Yubico",
      "transports": 4,
      "deviceUrl": "https://www.yubico.com/products/yubikey-hardware/fido-u2f-security-key/",
      "imageUrl": "https://developers.yubico.com/U2F/Images/SKY.png",
      "selectors": [
        {
          "type": "x509Extension",
          "parameters": {
            "key": "1.3.6.1.4.1.41482.1.1"
          }
        },
        {
          "type": "x509Extension",
          "parameters": {
            "value": "1.3.6.1.4.1.41482.1.1",
            "key": "1.3.6.1.4.1.41482.2"
          }
        }
      ]
    },
    {
      "deviceId": "1.3.6.1.4.1.41482.1.2",
      "displayName": "YubiKey NEO/NEO-n",
      "transports": 4,
      "deviceUrl": "https://www.yubico.com/products/yubikey-hardware/yubikey-neo/",
      "imageUrl": "https://developers.yubico.com/U2F/Images/NEO.png",
      "selectors": [
        {
          "type": "x509Extension",
          "parameters": {
            "key": "1.3.6.1.4.1.41482.1.2"
          }
        },
        {
          "type": "x509Extension",
          "parameters": {
            "value": "1.3.6.1.4.1.41482.1.2",
            "key": "1.3.6.1.4.1.41482.2"
          }
        }
      ]
    },
    {
      "deviceId": "1.3.6.1.4.1.41482.1.3",
      "displayName": "YubiKey Plus",
      "transports": 4,
      "deviceUrl": "https://www.yubico.com/products/yubikey-hardware/",
      "imageUrl": "https://developers.yubico.com/U2F/Images/PLS.png",
      "selectors": [
        {
          "type": "x509Extension",
          "parameters": {
            "key": "1.3.6.1.4.1.41482.1.3"
          }
        },
        {
          "type": "x509Extension",
          "parameters": {
            "value": "1.3.6.1.4.1.41482.1.3",
            "key": "1.3.6.1.4.1.41482.2"
          }
        }
      ]
    },
    {
      "deviceId": "1.3.6.1.4.1.41482.1.4",
      "displayName": "YubiKey Edge",
      "transports": 4,
      "deviceUrl": "https://www.yubico.com/products/yubikey-hardware/",
      "imageUrl": "https://developers.yubico.com/U2F/Images/YKE.png",
      "selectors": [
        {
          "type": "x509Extension",
          "parameters": {
            "value": "1.3.6.1.4.1.41482.1.4",
            "key": "1.3.6.1.4.1.41482.2"
          }
        }
      ]
    },
    {
      "deviceId": "1.3.6.1.4.1.41482.1.5",
      "displayName": "YubiKey 4/YubiKey 4 Nano",
      "transports": 4,
      "deviceUrl": "https://www.yubico.com/products/yubikey-hardware/yubikey4/",
      "imageUrl": "https://developers.yubico.com/U2F/Images/YK4.png",
      "selectors": [
        {
          "type": "x509Extension",
          "parameters": {
            "value": "1.3.6.1.4.1.41482.1.5",
            "key": "1.3.6.1.4.1.41482.2"
          }
        }
      ]
    }
  ]
}

================================================
FILE: u2flib-server-attestation/src/test/java/com/yubico/u2f/attestation/MetadataObjectTest.java
================================================
package com.yubico.u2f.attestation;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Iterables;
import com.yubico.u2f.exceptions.U2fBadInputException;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class MetadataObjectTest {
    public static final String JSON = "{\"identifier\":\"foobar\",\"version\":1,\"trustedCertificates\":[\"-----BEGIN CERTIFICATE-----\\nMIIDHjCCAgagAwIBAgIEG1BT9zANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZ\\ndWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAw\\nMDBaGA8yMDUwMDkwNDAwMDAwMFowLjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290\\nIENBIFNlcmlhbCA0NTcyMDA2MzEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\\nAoIBAQC/jwYuhBVlqaiYWEMsrWFisgJ+PtM91eSrpI4TK7U53mwCIawSDHy8vUmk\\n5N2KAj9abvT9NP5SMS1hQi3usxoYGonXQgfO6ZXyUA9a+KAkqdFnBnlyugSeCOep\\n8EdZFfsaRFtMjkwz5Gcz2Py4vIYvCdMHPtwaz0bVuzneueIEz6TnQjE63Rdt2zbw\\nnebwTG5ZybeWSwbzy+BJ34ZHcUhPAY89yJQXuE0IzMZFcEBbPNRbWECRKgjq//qT\\n9nmDOFVlSRCt2wiqPSzluwn+v+suQEBsUjTGMEd25tKXXTkNW21wIWbxeSyUoTXw\\nLvGS6xlwQSgNpk2qXYwf8iXg7VWZAgMBAAGjQjBAMB0GA1UdDgQWBBQgIvz0bNGJ\\nhjgpToksyKpP9xv9oDAPBgNVHRMECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAN\\nBgkqhkiG9w0BAQsFAAOCAQEAjvjuOMDSa+JXFCLyBKsycXtBVZsJ4Ue3LbaEsPY4\\nMYN/hIQ5ZM5p7EjfcnMG4CtYkNsfNHc0AhBLdq45rnT87q/6O3vUEtNMafbhU6kt\\nhX7Y+9XFN9NpmYxr+ekVY5xOxi8h9JDIgoMP4VB1uS0aunL1IGqrNooL9mmFnL2k\\nLVVee6/VR6C5+KSTCMCWppMuJIZII2v9o4dkoZ8Y7QRjQlLfYzd3qGtKbw7xaF1U\\nsG/5xUb/Btwb2X2g4InpiB/yt/3CpQXpiWX/K4mBvUKiGn05ZsqeY1gx4g0xLBqc\\nU9psmyPzK+Vsgw2jeRQ5JlKDyqE0hebfC1tvFu0CCrJFcw==\\n-----END CERTIFICATE-----\"],\"vendorInfo\":{\"name\":\"Yubico\",\"url\":\"https://yubico.com\",\"imageUrl\":\"https://developers.yubico.com/U2F/Images/yubico.png\"},\"devices\":[{\"displayName\":\"YubiKey NEO/NEO-n\",\"deviceId\":\"1.3.6.1.4.1.41482.1.2\",\"deviceUrl\":\"https://www.yubico.com/products/yubikey-hardware/yubikey-neo/\",\"imageUrl\":\"https://developers.yubico.com/U2F/Images/NEO.png\",\"selectors\":[{\"type\":\"x509Extension\",\"parameters\":{\"key\":\"1.3.6.1.4.1.41482.1.2\"}}]}]}";

    @Test
    public void testToAndFromJson() throws Exception {
        MetadataObject metadata = MetadataObject.fromJson(JSON);
        ObjectMapper objectMapper = new ObjectMapper();
        MetadataObject metadata2 = objectMapper.readValue(objectMapper.writeValueAsString(metadata), MetadataObject.class);

        assertEquals("foobar", metadata.getIdentifier());
        assertEquals(1, metadata.getVersion());
        assertEquals(1, metadata.getTrustedCertificates().size());

        assertEquals("Yubico", metadata.getVendorInfo().get("name"));
        assertEquals("1.3.6.1.4.1.41482.1.2", metadata.getDevices().get(0).get("deviceId").asText());

        assertEquals(metadata, metadata2);
        assertEquals(JSON, metadata.toJson());
    }

    @Test
    public void testParseFromJson() throws U2fBadInputException {
        MetadataObject parsed1 = Iterables.getOnlyElement(MetadataObject.parseFromJson(JSON));
        MetadataObject parsed2 = Iterables.getOnlyElement(MetadataObject.parseFromJson("[" + JSON + "]"));
        MetadataObject expected = MetadataObject.fromJson(JSON);

        assertEquals(expected.toJson(), parsed1.toJson());
        assertEquals(expected.toJson(), parsed2.toJson());
    }
}

================================================
FILE: u2flib-server-attestation/src/test/java/com/yubico/u2f/attestation/MetadataServiceTest.java
================================================
package com.yubico.u2f.attestation;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.ImmutableList;
import com.google.common.hash.Hashing;
import com.yubico.u2f.data.messages.key.util.CertificateParser;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.EnumSet;
import org.junit.Test;
import org.mockito.Matchers;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class MetadataServiceTest {
    private static final String ATTESTATION_CERT = "MIICGzCCAQWgAwIBAgIEdaP2dTALBgkqhkiG9w0BAQswLjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290IENBIFNlcmlhbCA0NTcyMDA2MzEwIBcNMTQwODAxMDAwMDAwWhgPMjA1MDA5MDQwMDAwMDBaMCoxKDAmBgNVBAMMH1l1YmljbyBVMkYgRUUgU2VyaWFsIDE5NzM2Nzk3MzMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQZo35Damtpl81YdmcbhEuXKAr7xDcQzAy5n3ftAAhtBbu8EeGU4ynfSgLonckqX6J2uXLBppTNE3v2bt+Yf8MLoxIwEDAOBgorBgEEAYLECgECBAAwCwYJKoZIhvcNAQELA4IBAQG9LbiNPgs0sQYOHAJcg+lMk+HCsiWRlYVnbT4I/5lnqU907vY17XYAORd432bU3Nnhsbkvjz76kQJGXeNAF4DPANGGlz8JU+LNEVE2PWPGgEM0GXgB7mZN5Sinfy1AoOdO+3c3bfdJQuXlUxHbo+nDpxxKpzq9gr++RbokF1+0JBkMbaA/qLYL4WdhY5NvaOyMvYpO3sBxlzn6FcP67hlotGH1wU7qhCeh+uur7zDeAWVh7c4QtJOXHkLJQfV3Z7ZMvhkIA6jZJAX99hisABU/SSa5DtgX7AfsHwa04h69AAAWDUzSk3HgOXbUd1FaSOPdlVFkG2N2JllFHykyO3zO";
    private static final String ATTESTATION_CERT2 = "MIICLzCCARmgAwIBAgIEQvUaTTALBgkqhkiG9w0BAQswLjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290IENBIFNlcmlhbCA0NTcyMDA2MzEwIBcNMTQwODAxMDAwMDAwWhgPMjA1MDA5MDQwMDAwMDBaMCoxKDAmBgNVBAMMH1l1YmljbyBVMkYgRUUgU2VyaWFsIDExMjMzNTkzMDkwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQphQ+PJYiZjZEVHtrx5QGE3/LE1+OytZPTwzrpWBKywji/3qmg22mwmVFl32PO269TxY+yVN4jbfVf5uX0EWJWoyYwJDAiBgkrBgEEAYLECgIEFTEuMy42LjEuNC4xLjQxNDgyLjEuNDALBgkqhkiG9w0BAQsDggEBALSc3YwTRbLwXhePj/imdBOhWiqh6ssS2ONgp5tphJCHR5Agjg2VstLBRsJzyJnLgy7bGZ0QbPOyh/J0hsvgBfvjByXOu1AwCW+tcoJ+pfxESojDLDn8hrFph6eWZoCtBsWMDh6vMqPENeP6grEAECWx4fTpBL9Bm7F+0Rp/d1/l66g4IhF/ZvuRFhY+BUK94BfivuBHpEkMwxKENTas7VkxvlVstUvPqhPHGYOq7RdF1D/THsbNY8+tgCTgvTziEG+bfDeY6zIz5h7bxb1rpajNVTpUDWtVYL7/w44e1KCoErqdS+kEbmmkmm7KvDE8kuyg42Fmb5DTMsbY2jxMlMU=";
    private static final String ATTESTATION_CERT_WITH_TRANSPORTS = "MIICIjCCAQygAwIBAgIEIHHwozALBgkqhkiG9w0BAQswDzENMAsGA1UEAxMEdGVzdDAeFw0xNTA4MTEwOTAwMzNaFw0xNjA4MTAwOTAwMzNaMCkxJzAlBgNVBAMTHll1YmljbyBVMkYgRUUgU2VyaWFsIDU0NDMzODA4MzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPdFG1pBjBBQVhLrD39Qg1vKjuR2kRdBZnwLI/zgzztQpf4ffpkrkB/3E0TXj5zg8gN9sgMkX48geBe+tBEpvMmjOzA5MCIGCSsGAQQBgsQKAgQVMS4zLjYuMS40LjEuNDE0ODIuMS4yMBMGCysGAQQBguUcAgEBBAQDAgQwMAsGCSqGSIb3DQEBCwOCAQEAb3YpnmHHduNuWEXlLqlnww9034ZeZaojhPAYSLR8d5NPk9gc0hkjQKmIaaBM7DsaHbcHMKpXoMGTQSC++NCZTcKvZ0Lt12mp5HRnM1NNBPol8Hte5fLmvW4tQ9EzLl4gkz7LSlORxTuwTbae1eQqNdxdeB+0ilMFCEUc+3NGCNM0RWd+sP5+gzMXBDQAI1Sc9XaPIg8t3du5JChAl1ifpu/uERZ2WQgtxeBDO6z1Xoa5qz4svf5oURjPZjxS0WUKht48Z2rIjk5lZzERSaY3RrX3UtrnZEIzCmInXOrcRPeAD4ZutpiwuHe62ABsjuMRnKbATbOUiLdknNyPYYQz2g==";

    @Test
    public void testGetAttestation_x509extension_key() throws Exception {
        MetadataService service = new MetadataService();

        X509Certificate attestationCert = CertificateParser.parsePem(ATTESTATION_CERT);
        Attestation attestation = service.getAttestation(attestationCert);

        assertTrue(attestation.isTrusted());
        assertEquals("Yubico", attestation.getVendorProperties().get("name"));
        assertEquals("1.3.6.1.4.1.41482.1.2", attestation.getDeviceProperties().get("deviceId"));
    }

    @Test
    public void testGetAttestation_x509extension_key_value() throws Exception {
        MetadataService service = new MetadataService();

        X509Certificate attestationCert = CertificateParser.parsePem(ATTESTATION_CERT2);
        Attestation attestation = service.getAttestation(attestationCert);

        assertTrue(attestation.isTrusted());
        assertEquals("Yubico", attestation.getVendorProperties().get("name"));
        assertEquals("1.3.6.1.4.1.41482.1.4", attestation.getDeviceProperties().get("deviceId"));
    }

    @Test
    public void testGetTransportsFromCertificate() throws CertificateException {
        MetadataService service = new MetadataService(mock(MetadataResolver.class));

        X509Certificate attestationCert = CertificateParser.parsePem(ATTESTATION_CERT_WITH_TRANSPORTS);
        Attestation attestation = service.getAttestation(attestationCert);

        assertEquals(EnumSet.of(Transport.USB, Transport.NFC), attestation.getTransports());
    }

    @Test
    public void testGetTransportsFromMetadata() throws CertificateException {
        MetadataService service = new MetadataService();

        X509Certificate attestationCert = CertificateParser.parsePem(ATTESTATION_CERT2);
        Attestation attestation = service.getAttestation(attestationCert);

        assertEquals(EnumSet.of(Transport.USB), attestation.getTransports());
    }

    @Test
    public void getCachedAttestationReturnsCertIfPresent() throws Exception {
        MetadataService service = new MetadataService();

        final X509Certificate attestationCert = CertificateParser.parsePem(ATTESTATION_CERT);
        final String certFingerprint = Hashing.sha1().hashBytes(attestationCert.getEncoded()).toString();

        assertNull(service.getCachedAttestation(certFingerprint));

        service.getAttestation(attestationCert);

        Attestation attestation = service.getCachedAttestation(certFingerprint);

        assertTrue(attestation.isTrusted());
        assertEquals("Yubico", attestation.getVendorProperties().get("name"));
        assertEquals("1.3.6.1.4.1.41482.1.2", attestation.getDeviceProperties().get("deviceId"));
    }

    @Test
    public void getAttestationReturnsUnknownIfFingerprintEncodingFails() throws Exception {
        MetadataService service = new MetadataService();

        final X509Certificate attestationCert = mock(X509Certificate.class);
        when(attestationCert.getEncoded()).thenThrow(new CertificateEncodingException("Forced failure"));

        Attestation attestation = service.getAttestation(attestationCert);

        assertFalse(attestation.isTrusted());
    }

    @Test
    public void deviceMatchesReturnsTrueIfNoSelectorsAreGiven() throws Exception {
        MetadataResolver resolver = mock(MetadataResolver.class);
        JsonNode device = mock(JsonNode.class);
        MetadataObject metadata = mock(MetadataObject.class);
        when(metadata.getDevices()).thenReturn(ImmutableList.of(device));
        when(resolver.resolve(Matchers.<X509Certificate>any())).thenReturn(metadata);

        MetadataService service = new MetadataService(resolver);

        final X509Certificate attestationCert = CertificateParser.parsePem(ATTESTATION_CERT);

        Attestation attestation = service.getAttestation(attestationCert);

        verify(device, times(1)).get("transports");
    }

}


================================================
FILE: u2flib-server-attestation/src/test/java/com/yubico/u2f/attestation/TransportTest.java
================================================
package com.yubico.u2f.attestation;

import org.junit.Test;

import java.util.EnumSet;

import static org.junit.Assert.assertEquals;

/**
 * Created by Dain on 2016-02-18.
 */
public class TransportTest {

    @Test
    public void testParsingSingleValuesFromInt() {
        assertEquals(EnumSet.of(Transport.BT_CLASSIC), Transport.fromInt(1));
        assertEquals(EnumSet.of(Transport.BLE), Transport.fromInt(2));
        assertEquals(EnumSet.of(Transport.USB), Transport.fromInt(4));
        assertEquals(EnumSet.of(Transport.NFC), Transport.fromInt(8));
    }

    @Test
    public void testParsingSetsFromInt() {
        assertEquals(EnumSet.noneOf(Transport.class), Transport.fromInt(0));
        assertEquals(EnumSet.of(Transport.BLE, Transport.NFC), Transport.fromInt(10));
        assertEquals(EnumSet.of(Transport.USB, Transport.BT_CLASSIC), Transport.fromInt(5));
        assertEquals(EnumSet.of(Transport.BT_CLASSIC, Transport.BLE, Transport.USB, Transport.NFC),
                Transport.fromInt(15));
    }

    @Test
    public void testEncodingSingleValuesToInt() {
        assertEquals(1, Transport.toInt(Transport.BT_CLASSIC));
        assertEquals(2, Transport.toInt(Transport.BLE));
        assertEquals(4, Transport.toInt(Transport.USB));
        assertEquals(8, Transport.toInt(Transport.NFC));
    }

    @Test
    public void testEncodingSetsToInt() {
        assertEquals(0, Transport.toInt());
        assertEquals(10, Transport.toInt(Transport.BLE, Transport.NFC));
        assertEquals(5, Transport.toInt(Transport.USB, Transport.BT_CLASSIC));
        assertEquals(15, Transport.toInt(Transport.BT_CLASSIC, Transport.BLE, Transport.USB, Transport.NFC));
    }

}


================================================
FILE: u2flib-server-attestation/src/test/java/com/yubico/u2f/attestation/matchers/FingerprintMatcherTest.java
================================================
package com.yubico.u2f.attestation.matchers;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.BooleanNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.TextNode;
import com.google.common.hash.Hashing;
import com.yubico.u2f.data.messages.key.util.CertificateParser;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import org.junit.Test;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class FingerprintMatcherTest {

    private static final String ATTESTATION_CERT = "MIICGzCCAQWgAwIBAgIEdaP2dTALBgkqhkiG9w0BAQswLjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290IENBIFNlcmlhbCA0NTcyMDA2MzEwIBcNMTQwODAxMDAwMDAwWhgPMjA1MDA5MDQwMDAwMDBaMCoxKDAmBgNVBAMMH1l1YmljbyBVMkYgRUUgU2VyaWFsIDE5NzM2Nzk3MzMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQZo35Damtpl81YdmcbhEuXKAr7xDcQzAy5n3ftAAhtBbu8EeGU4ynfSgLonckqX6J2uXLBppTNE3v2bt+Yf8MLoxIwEDAOBgorBgEEAYLECgECBAAwCwYJKoZIhvcNAQELA4IBAQG9LbiNPgs0sQYOHAJcg+lMk+HCsiWRlYVnbT4I/5lnqU907vY17XYAORd432bU3Nnhsbkvjz76kQJGXeNAF4DPANGGlz8JU+LNEVE2PWPGgEM0GXgB7mZN5Sinfy1AoOdO+3c3bfdJQuXlUxHbo+nDpxxKpzq9gr++RbokF1+0JBkMbaA/qLYL4WdhY5NvaOyMvYpO3sBxlzn6FcP67hlotGH1wU7qhCeh+uur7zDeAWVh7c4QtJOXHkLJQfV3Z7ZMvhkIA6jZJAX99hisABU/SSa5DtgX7AfsHwa04h69AAAWDUzSk3HgOXbUd1FaSOPdlVFkG2N2JllFHykyO3zO";

    @Test
    public void matchesIsFalseForNonArrayFingerprints() {
        JsonNode parameters = mock(JsonNode.class);
        when(parameters.get("fingerprints")).thenReturn(BooleanNode.TRUE);

        assertFalse(new FingerprintMatcher().matches(mock(X509Certificate.class), parameters));
    }

    @Test
    public void matchesIsFalseIfNoFingerprintMatches() throws CertificateException {
        final X509Certificate cert = CertificateParser.parsePem(ATTESTATION_CERT);
        final String fingerprint = Hashing.sha1().hashBytes(cert.getEncoded()).toString().toLowerCase();

        ArrayNode fingerprints = new ArrayNode(JsonNodeFactory.instance);
        fingerprints.add(new TextNode("foo"));
        fingerprints.add(new TextNode("bar"));

        JsonNode parameters = mock(JsonNode.class);
        when(parameters.get("fingerprints")).thenReturn(fingerprints);

        assertFalse(new FingerprintMatcher().matches(cert, parameters));
    }

    @Test
    public void matchesIsTrueIfSomeFingerprintMatches() throws CertificateException {
        final X509Certificate cert = CertificateParser.parsePem(ATTESTATION_CERT);
        final String fingerprint = Hashing.sha1().hashBytes(cert.getEncoded()).toString().toLowerCase();

        ArrayNode fingerprints = new ArrayNode(JsonNodeFactory.instance);
        fingerprints.add(new TextNode("foo"));
        fingerprints.add(new TextNode(fingerprint));

        JsonNode parameters = mock(JsonNode.class);
        when(parameters.get("fingerprints")).thenReturn(fingerprints);

        assertTrue(new FingerprintMatcher().matches(cert, parameters));
    }

}


================================================
FILE: u2flib-server-attestation/src/test/java/com/yubico/u2f/attestation/resolvers/SimpleResolverTest.java
================================================
package com.yubico.u2f.attestation.resolvers;

import com.yubico.u2f.attestation.MetadataObject;
import com.yubico.u2f.data.messages.key.util.CertificateParser;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Principal;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import org.junit.Test;
import org.mockito.Matchers;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class SimpleResolverTest {

    private static final String METADATA_JSON = "{\"identifier\":\"foobar\",\"version\":1,\"trustedCertificates\":[\"-----BEGIN CERTIFICATE-----\\nMIIDHjCCAgagAwIBAgIEG1BT9zANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZ\\ndWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAw\\nMDBaGA8yMDUwMDkwNDAwMDAwMFowLjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290\\nIENBIFNlcmlhbCA0NTcyMDA2MzEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\\nAoIBAQC/jwYuhBVlqaiYWEMsrWFisgJ+PtM91eSrpI4TK7U53mwCIawSDHy8vUmk\\n5N2KAj9abvT9NP5SMS1hQi3usxoYGonXQgfO6ZXyUA9a+KAkqdFnBnlyugSeCOep\\n8EdZFfsaRFtMjkwz5Gcz2Py4vIYvCdMHPtwaz0bVuzneueIEz6TnQjE63Rdt2zbw\\nnebwTG5ZybeWSwbzy+BJ34ZHcUhPAY89yJQXuE0IzMZFcEBbPNRbWECRKgjq//qT\\n9nmDOFVlSRCt2wiqPSzluwn+v+suQEBsUjTGMEd25tKXXTkNW21wIWbxeSyUoTXw\\nLvGS6xlwQSgNpk2qXYwf8iXg7VWZAgMBAAGjQjBAMB0GA1UdDgQWBBQgIvz0bNGJ\\nhjgpToksyKpP9xv9oDAPBgNVHRMECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAN\\nBgkqhkiG9w0BAQsFAAOCAQEAjvjuOMDSa+JXFCLyBKsycXtBVZsJ4Ue3LbaEsPY4\\nMYN/hIQ5ZM5p7EjfcnMG4CtYkNsfNHc0AhBLdq45rnT87q/6O3vUEtNMafbhU6kt\\nhX7Y+9XFN9NpmYxr+ekVY5xOxi8h9JDIgoMP4VB1uS0aunL1IGqrNooL9mmFnL2k\\nLVVee6/VR6C5+KSTCMCWppMuJIZII2v9o4dkoZ8Y7QRjQlLfYzd3qGtKbw7xaF1U\\nsG/5xUb/Btwb2X2g4InpiB/yt/3CpQXpiWX/K4mBvUKiGn05ZsqeY1gx4g0xLBqc\\nU9psmyPzK+Vsgw2jeRQ5JlKDyqE0hebfC1tvFu0CCrJFcw==\\n-----END CERTIFICATE-----\"],\"vendorInfo\":{\"name\":\"Yubico\",\"url\":\"https://yubico.com\",\"imageUrl\":\"https://developers.yubico.com/U2F/Images/yubico.png\"},\"devices\":[{\"displayName\":\"YubiKey NEO/NEO-n\",\"deviceId\":\"1.3.6.1.4.1.41482.1.2\",\"deviceUrl\":\"https://www.yubico.com/products/yubikey-hardware/yubikey-neo/\",\"imageUrl\":\"https://developers.yubico.com/U2F/Images/NEO.png\",\"selectors\":[{\"type\":\"x509Extension\",\"parameters\":{\"key\":\"1.3.6.1.4.1.41482.1.2\"}}]}]  }";
    private static final String ATTESTATION_CERT = "MIICGzCCAQWgAwIBAgIEdaP2dTALBgkqhkiG9w0BAQswLjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290IENBIFNlcmlhbCA0NTcyMDA2MzEwIBcNMTQwODAxMDAwMDAwWhgPMjA1MDA5MDQwMDAwMDBaMCoxKDAmBgNVBAMMH1l1YmljbyBVMkYgRUUgU2VyaWFsIDE5NzM2Nzk3MzMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQZo35Damtpl81YdmcbhEuXKAr7xDcQzAy5n3ftAAhtBbu8EeGU4ynfSgLonckqX6J2uXLBppTNE3v2bt+Yf8MLoxIwEDAOBgorBgEEAYLECgECBAAwCwYJKoZIhvcNAQELA4IBAQG9LbiNPgs0sQYOHAJcg+lMk+HCsiWRlYVnbT4I/5lnqU907vY17XYAORd432bU3Nnhsbkvjz76kQJGXeNAF4DPANGGlz8JU+LNEVE2PWPGgEM0GXgB7mZN5Sinfy1AoOdO+3c3bfdJQuXlUxHbo+nDpxxKpzq9gr++RbokF1+0JBkMbaA/qLYL4WdhY5NvaOyMvYpO3sBxlzn6FcP67hlotGH1wU7qhCeh+uur7zDeAWVh7c4QtJOXHkLJQfV3Z7ZMvhkIA6jZJAX99hisABU/SSa5DtgX7AfsHwa04h69AAAWDUzSk3HgOXbUd1FaSOPdlVFkG2N2JllFHykyO3zO";

    @Test
    public void testResolve() throws Exception {
        SimpleResolver resolver = new SimpleResolver();

        resolver.addMetadata(METADATA_JSON);
        X509Certificate certificate = CertificateParser.parseDer(ATTESTATION_CERT);

        MetadataObject metadata = resolver.resolve(certificate);

        assertNotNull(metadata);
        assertEquals("foobar", metadata.getIdentifier());
    }

    @Test
    public void resolveReturnsNullOnUntrustedSignature() throws Exception {
        SimpleResolver resolver = new SimpleResolver();
        resolver.addMetadata(METADATA_JSON);

        X509Certificate cert = mock(X509Certificate.class);
        doThrow(
            new CertificateException("Forced failure"),
            new NoSuchAlgorithmException("Forced failure"),
            new InvalidKeyException("Forced failure"),
            new NoSuchProviderException("Forced failure"),
            new SignatureException("Forced failure")
        ).when(cert).verify(Matchers.<PublicKey>any());
        Principal issuerDN = mock(Principal.class);
        when(issuerDN.getName()).thenReturn("CN=Yubico U2F Root CA Serial 457200631");
        when(cert.getIssuerDN()).thenReturn(issuerDN);

        assertNull(resolver.resolve(cert));
        assertNull(resolver.resolve(cert));
        assertNull(resolver.resolve(cert));
        assertNull(resolver.resolve(cert));
        assertNull(resolver.resolve(cert));
    }

}


================================================
FILE: u2flib-server-core/build.gradle
================================================
description = 'U2F core'

dependencies {

  compile(
    [group: 'org.bouncycastle', name: 'bcpkix-jdk15on', version:'1.54'],
    [group: 'com.google.guava', name: 'guava', version:'19.0'],
    [group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version:'2.11.0'],
  )

}


================================================
FILE: u2flib-server-core/gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists


================================================
FILE: u2flib-server-core/gradlew
================================================
#!/usr/bin/env sh

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
    else
        PRG=`dirname "$PRG"`"/$link"
    fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn () {
    echo "$*"
}

die () {
    echo
    echo "$*"
    echo
    exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
  NONSTOP* )
    nonstop=true
    ;;
esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
    MAX_FD_LIMIT=`ulimit -H -n`
    if [ $? -eq 0 ] ; then
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
            MAX_FD="$MAX_FD_LIMIT"
        fi
        ulimit -n $MAX_FD
        if [ $? -ne 0 ] ; then
            warn "Could not set maximum file descriptor limit: $MAX_FD"
        fi
    else
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
    fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
    JAVACMD=`cygpath --unix "$JAVACMD"`

    # We build the pattern for arguments to be converted via cygpath
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
    SEP=""
    for dir in $ROOTDIRSRAW ; do
        ROOTDIRS="$ROOTDIRS$SEP$dir"
        SEP="|"
    done
    OURCYGPATTERN="(^($ROOTDIRS))"
    # Add a user-defined pattern to the cygpath arguments
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
    fi
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    i=0
    for arg in "$@" ; do
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option

        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=$((i+1))
    done
    case $i in
        (0) set -- ;;
        (1) set -- "$args0" ;;
        (2) set -- "$args0" "$args1" ;;
        (3) set -- "$args0" "$args1" "$args2" ;;
        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
    esac
fi

# Escape application args
save () {
    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
    echo " "
}
APP_ARGS=$(save "$@")

# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"

# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
  cd "$(dirname "$0")"
fi

exec "$JAVACMD" "$@"


================================================
FILE: u2flib-server-core/gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windows variants

if not "%OS%" == "Windows_NT" goto win9xME_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: u2flib-server-core/pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>u2flib-server-parent</artifactId>
        <groupId>com.yubico</groupId>
        <version>0.19.12</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>u2flib-server-core</artifactId>
    <name>U2F core</name>

    <dependencies>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpkix-jdk15on</artifactId>
            <version>1.54</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>[24.1.1,30)</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.11.0</version>
        </dependency>
    </dependencies>
</project>


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/AppId.java
================================================
package com.yubico.u2f;

import com.google.common.net.InetAddresses;
import com.yubico.u2f.exceptions.U2fBadConfigurationException;

import com.yubico.u2f.exceptions.U2fBadInputException;
import java.net.URI;
import java.net.URISyntaxException;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class AppId {

    public static final String DISABLE_INSTRUCTIONS = "To disable this check, instantiate the U2F object using U2F.withoutAppIdValidation()";

    /**
     * Throws {@link U2fBadConfigurationException} if the given App ID is found to be incompatible with the U2F specification or any major
     * U2F Client implementation.
     *
     * @param appId the App ID to be validated
     */
    public static void checkIsValid(String appId) throws U2fBadConfigurationException {
        if(!appId.contains(":")) {
            throw new U2fBadConfigurationException("App ID does not look like a valid facet or URL. Web facets must start with 'https://'. " + DISABLE_INSTRUCTIONS);
        }
        if(appId.startsWith("http:")) {
            throw new U2fBadConfigurationException("HTTP is not supported for App IDs (by Chrome). Use HTTPS instead. " + DISABLE_INSTRUCTIONS);
        }
        if(appId.startsWith("https://")) {
            URI url = checkValidUrl(appId);
            checkPathIsNotSlash(url);
            checkNotIpAddress(url);
        }
    }

    private static void checkPathIsNotSlash(URI url) throws U2fBadConfigurationException {
        if("/".equals(url.getPath())) {
            throw new U2fBadConfigurationException("The path of the URL set as App ID is '/'. This is probably not what you want -- remove the trailing slash of the App ID URL. " + DISABLE_INSTRUCTIONS);
        }
    }

    private static URI checkValidUrl(String appId) throws U2fBadConfigurationException {
        URI url = null;
        try {
            url = new URI(appId);
        } catch (URISyntaxException e) {
            throw new U2fBadConfigurationException("App ID looks like a HTTPS URL, but has syntax errors.", e);
        }
        return url;
    }

    private static void checkNotIpAddress(URI url) throws U2fBadConfigurationException {
        if (InetAddresses.isInetAddress(url.getAuthority()) || (url.getHost() != null && InetAddresses.isInetAddress(url.getHost()))) {
            throw new U2fBadConfigurationException("App ID must not be an IP-address, since it is not supported (by Chrome). Use a host name instead. " + DISABLE_INSTRUCTIONS);
        }
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/U2F.java
================================================
/* Copyright 2014 Yubico */

package com.yubico.u2f;

import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.yubico.u2f.crypto.BouncyCastleCrypto;
import com.yubico.u2f.crypto.ChallengeGenerator;
import com.yubico.u2f.crypto.RandomChallengeGenerator;
import com.yubico.u2f.data.DeviceRegistration;
import com.yubico.u2f.data.messages.*;
import com.yubico.u2f.exceptions.DeviceCompromisedException;
import com.yubico.u2f.exceptions.InvalidDeviceCounterException;
import com.yubico.u2f.exceptions.NoEligibleDevicesException;
import com.yubico.u2f.exceptions.U2fAuthenticationException;
import com.yubico.u2f.exceptions.U2fBadConfigurationException;
import com.yubico.u2f.exceptions.U2fBadInputException;

import com.yubico.u2f.exceptions.U2fRegistrationException;
import java.util.Set;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class U2F {

    private final ChallengeGenerator challengeGenerator;
    private final U2fPrimitives primitives;
    private final boolean validateAppId;



    public U2F() {
        this(true);
    }

    public static U2F withoutAppIdValidation() {
        return new U2F(false);
    }

    private U2F(boolean validateAppId) {
        this.challengeGenerator = new RandomChallengeGenerator();
        primitives = new U2fPrimitives(new BouncyCastleCrypto(), challengeGenerator);
        this.validateAppId = validateAppId;
    }

    /**
     * Initiates a high-level registration of a device, given a set of already registered devices.
     *
     * @param appId   the U2F AppID. Set this to the Web Origin of the login page, unless you need to
     *                support logging in from multiple Web Origins.
     * @param devices the devices currently registered to the user.
     * @return a RegisterRequestData, which should be sent to the client and temporarily saved by the server.
     */
    public RegisterRequestData startRegistration(String appId, Iterable<? extends DeviceRegistration> devices) throws U2fBadConfigurationException {
        if(validateAppId) {
            AppId.checkIsValid(appId);
        }
        return new RegisterRequestData(appId, devices, primitives, challengeGenerator);
    }

    public SignRequestData startSignature(String appId, Iterable<? extends DeviceRegistration> devices) throws U2fBadConfigurationException, NoEligibleDevicesException {
        if(validateAppId) {
            AppId.checkIsValid(appId);
        }
        return new SignRequestData(appId, devices, primitives, challengeGenerator);
    }

    /***
     *
     */
    public DeviceRegistration finishRegistration(RegisterRequestData registerRequestData, RegisterResponse response) throws U2fRegistrationException {
        return finishRegistration(registerRequestData, response, null);
    }

    /**
     * Finishes a previously started high-level registration.
     *
     * @param registerRequestData the RegisterResponseData created by calling startRegistration
     * @param response            The response from the device/client.
     * @param facets              A list of valid facets to verify against.
     * @return a DeviceRegistration object, holding information about the registered device. Servers should
     * persist this.
     * @throws U2fRegistrationException if parsing or verification of the response fails
     */
    public DeviceRegistration finishRegistration(RegisterRequestData registerRequestData, RegisterResponse response, Set<String> facets) throws U2fRegistrationException {
        return primitives.finishRegistration(registerRequestData.getRegisterRequest(response), response, facets);
    }

    /**
     * @see U2F#finishSignature(SignRequestData, SignResponse, Iterable, java.util.Set)
     */
    public DeviceRegistration finishSignature(SignRequestData signRequestData, SignResponse response, Iterable<? extends DeviceRegistration> devices) throws U2fAuthenticationException {
        return finishSignature(signRequestData, response, devices, null);
    }

    /**
     * Finishes a previously started high-level signing action.
     *
     * @param signRequestData the SignRequestData created by calling startSignature
     * @param response                the response from the device/client.
     * @param devices                 the devices currently registered to the user.
     * @param facets                  A list of valid facets to verify against.
     * @return The (updated) DeviceRegistration that signed the challenge.
     *
     * @throws InvalidDeviceCounterException if the response is valid but the signature counter has not increased.
     * @throws DeviceCompromisedException if the device with the response's key handle is marked as compromised.
     * @throws U2fAuthenticationException if parsing or verification of the response fails.
     */
    public DeviceRegistration finishSignature(SignRequestData signRequestData, SignResponse response, Iterable<? extends DeviceRegistration> devices, Set<String> facets) throws U2fAuthenticationException {
        try {
            final SignRequest request = signRequestData.getSignRequest(response);
            DeviceRegistration device = Iterables.find(devices, new Predicate<DeviceRegistration>() {
                @Override
                public boolean apply(DeviceRegistration input) {
                    return Objects.equal(request.getKeyHandle(), input.getKeyHandle());
                }

                @Override
                public boolean test(DeviceRegistration input) {
                    return apply(input);
                }
            });

            if (device.isCompromised()) {
                throw new DeviceCompromisedException(device, "The device is marked as possibly compromised, and cannot make trusted signatures.");
            }

            primitives.finishSignature(request, response, device, facets);
            return device;
        } catch (U2fBadInputException e) {
            throw new U2fAuthenticationException("finishSignature failed", e);
        }
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/U2fPrimitives.java
================================================
/*
 * Copyright 2014 Yubico.
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

package com.yubico.u2f;

import com.google.common.base.Optional;
import com.yubico.u2f.crypto.BouncyCastleCrypto;
import com.yubico.u2f.crypto.ChallengeGenerator;
import com.yubico.u2f.crypto.Crypto;
import com.yubico.u2f.crypto.RandomChallengeGenerator;
import com.yubico.u2f.data.DeviceRegistration;
import com.yubico.u2f.data.messages.*;
import com.yubico.u2f.data.messages.key.RawSignResponse;
import com.yubico.u2f.data.messages.key.RawRegisterResponse;
import com.yubico.u2f.data.messages.key.util.U2fB64Encoding;
import com.yubico.u2f.exceptions.DeviceCompromisedException;
import com.yubico.u2f.exceptions.InvalidDeviceCounterException;
import com.yubico.u2f.exceptions.U2fBadInputException;

import com.yubico.u2f.exceptions.U2fAuthenticationException;
import com.yubico.u2f.exceptions.U2fRegistrationException;
import java.util.Set;

import static com.google.common.base.Preconditions.checkArgument;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class U2fPrimitives {

    private static final String SIGN_TYPE = "navigator.id.getAssertion";
    private static final String REGISTER_TYPE = "navigator.id.finishEnrollment";
    public static final String U2F_VERSION = "U2F_V2";

    private final Crypto crypto;
    private final ChallengeGenerator challengeGenerator;

    public U2fPrimitives(Crypto crypto, ChallengeGenerator challengeGenerator) {
        this.crypto = crypto;
        this.challengeGenerator = challengeGenerator;
    }

    public U2fPrimitives() {
        this(new BouncyCastleCrypto(), new RandomChallengeGenerator());
    }

    /**
     * @see U2fPrimitives#startRegistration(String, byte[])
     */
    public RegisterRequest startRegistration(String appId) {
        return startRegistration(appId, challengeGenerator.generateChallenge());
    }

    /**
     * Initiates the registration of a device.
     *
     * @param appId     the U2F AppID. Set this to the Web Origin of the login page, unless you need to
     *                  support logging in from multiple Web Origins.
     * @param challenge the challenge to use
     * @return a RegisterRequest, which should be sent to the client and temporary saved by the
     * server.
     */
    public RegisterRequest startRegistration(String appId, byte[] challenge) {
        return new RegisterRequest(U2fB64Encoding.encode(challenge), appId);
    }

    /**
     * @see U2fPrimitives#finishRegistration(com.yubico.u2f.data.messages.RegisterRequest, com.yubico.u2f.data.messages.RegisterResponse, java.util.Set)
     */
    public DeviceRegistration finishRegistration(RegisterRequest registerRequest, RegisterResponse response) throws U2fRegistrationException {
        return finishRegistration(registerRequest, response, null);
    }

    /**
     * Finishes a previously started registration.
     *
     * @param registerRequest
     * @param response        the response from the device/client.
     * @return a DeviceRegistration object, holding information about the registered device. Servers should
     * persist this.
     */
    public DeviceRegistration finishRegistration(RegisterRequest registerRequest,
                                                 RegisterResponse response,
                                                 Set<String> facets) throws U2fRegistrationException {
        try {
            ClientData clientData = response.getClientData();
            clientData.checkContent(REGISTER_TYPE, registerRequest.getChallenge(), Optional.fromNullable(facets));

            RawRegisterResponse rawRegisterResponse = RawRegisterResponse.fromBase64(response.getRegistrationData(), crypto);
            rawRegisterResponse.checkSignature(registerRequest.getAppId(), clientData.asJson());
            return rawRegisterResponse.createDevice();
        } catch (U2fBadInputException e) {
            throw new U2fRegistrationException("finishRegistration failed", e);
        }
    }

    /**
     * Initiates the signing process.
     *
     * @see U2fPrimitives#startSignature(String, com.yubico.u2f.data.DeviceRegistration, byte[])
     */
    public SignRequest startSignature(String appId, DeviceRegistration deviceRegistration) {
        return startSignature(appId, deviceRegistration, challengeGenerator.generateChallenge());
    }

    /**
     * Initiates the signing process.
     *
     * @param appId              the U2F AppID. Set this to the Web Origin of the login page, unless you need to
     *                           support logging in from multiple Web Origins.
     * @param deviceRegistration the DeviceRegistration for which to initiate signing.
     * @param challenge          the challenge to use
     * @return an SignRequest which should be sent to the client and temporary saved by
     * the server.
     */
    public SignRequest startSignature(String appId, DeviceRegistration deviceRegistration, byte[] challenge) {
        checkArgument(!deviceRegistration.isCompromised(), "Device has been marked as compromised, cannot sign.");

        return SignRequest.builder()
            .appId(appId)
            .challenge(U2fB64Encoding.encode(challenge))
            .keyHandle(deviceRegistration.getKeyHandle())
            .build();
    }

    /**
     * @see U2fPrimitives#finishSignature(SignRequest, SignResponse, com.yubico.u2f.data.DeviceRegistration, java.util.Set)
     */
    public void finishSignature(SignRequest signRequest,
                                SignResponse response,
                                DeviceRegistration deviceRegistration) throws U2fAuthenticationException {
        finishSignature(signRequest, response, deviceRegistration, null);
    }

    /**
     * Finishes a previously started signature.
     *
     * @param signRequest
     * @param response            the response from the device/client.
     */
    public void finishSignature(SignRequest signRequest,
                                SignResponse response,
                                DeviceRegistration deviceRegistration,
                                Set<String> facets) throws U2fAuthenticationException {
        checkArgument(!deviceRegistration.isCompromised(), "Device has been marked as compromised, cannot sign.");
        checkArgument(signRequest.getKeyHandle().equals(deviceRegistration.getKeyHandle()), "Wrong DeviceRegistration for the given SignRequest");
        if (!deviceRegistration.getKeyHandle().equals(response.getKeyHandle())) {
            throw new U2fAuthenticationException("KeyHandle of SignResponse does not match");
        }

        try {
            ClientData clientData = response.getClientData();
            clientData.checkContent(SIGN_TYPE, signRequest.getChallenge(), Optional.fromNullable(facets));

            RawSignResponse rawSignResponse = RawSignResponse.fromBase64(
                response.getSignatureData(), crypto
            );
            rawSignResponse.checkSignature(
                signRequest.getAppId(),
                clientData.asJson(),
                U2fB64Encoding.decode(deviceRegistration.getPublicKey())
            );
            rawSignResponse.checkUserPresence();
            deviceRegistration.checkAndUpdateCounter(rawSignResponse.getCounter());
        } catch (U2fBadInputException e) {
            throw new U2fAuthenticationException("finishSignature failed", e);
        }
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/crypto/BouncyCastleCrypto.java
================================================
/*
 * Copyright 2014 Yubico.
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

package com.yubico.u2f.crypto;

import com.yubico.u2f.data.messages.key.util.U2fB64Encoding;
import com.yubico.u2f.exceptions.U2fBadInputException;
import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;

import java.security.*;
import java.security.cert.X509Certificate;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class BouncyCastleCrypto implements Crypto {

    private static final Provider provider = new BouncyCastleProvider();

    public Provider getProvider() {
        return provider;
    }

    @Override
    public void checkSignature(X509Certificate attestationCertificate, byte[] signedBytes, byte[] signature)
            throws U2fBadInputException {
        checkSignature(attestationCertificate.getPublicKey(), signedBytes, signature);
    }

    @Override
    public void checkSignature(PublicKey publicKey, byte[] signedBytes, byte[] signature)
            throws U2fBadInputException {
        try {
            Signature ecdsaSignature = Signature.getInstance("SHA256withECDSA", provider);
            ecdsaSignature.initVerify(publicKey);
            ecdsaSignature.update(signedBytes);
            if (!ecdsaSignature.verify(signature)) {
                throw new U2fBadInputException(String.format(
                    "Signature is invalid. Public key: %s, signed data: %s , signature: %s",
                    publicKey,
                    U2fB64Encoding.encode(signedBytes),
                    U2fB64Encoding.encode(signature)
                ));
            }
        } catch (GeneralSecurityException e) {
            throw new RuntimeException(
                String.format(
                    "Failed to verify signature. This could be a problem with your JVM environment, or a bug in u2flib-server-core. Public key: %s, signed data: %s , signature: %s",
                    publicKey,
                    U2fB64Encoding.encode(signedBytes),
                    U2fB64Encoding.encode(signature)
                ),
                e
            );
        }
    }

    @Override
    public PublicKey decodePublicKey(byte[] encodedPublicKey) throws U2fBadInputException {
        try {
            X9ECParameters curve = SECNamedCurves.getByName("secp256r1");
            ECPoint point;
            try {
                point = curve.getCurve().decodePoint(encodedPublicKey);
            } catch (RuntimeException e) {
                throw new U2fBadInputException("Could not parse user public key", e);
            }

            return KeyFactory.getInstance("ECDSA", provider).generatePublic(
                    new ECPublicKeySpec(point,
                            new ECParameterSpec(
                                    curve.getCurve(),
                                    curve.getG(),
                                    curve.getN(),
                                    curve.getH()
                            )
                    )
            );
        } catch (GeneralSecurityException e) { //This should not happen
            throw new RuntimeException(
                "Failed to decode public key: " + U2fB64Encoding.encode(encodedPublicKey),
                e
            );
        }
    }

    @Override
    public byte[] hash(byte[] bytes) {
        try {
            return MessageDigest.getInstance("SHA-256", provider).digest(bytes);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public byte[] hash(String str) {
        return hash(str.getBytes());
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/crypto/ChallengeGenerator.java
================================================
/*
 * Copyright 2014 Yubico.
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

package com.yubico.u2f.crypto;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public interface ChallengeGenerator {

    byte[] generateChallenge();
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/crypto/Crypto.java
================================================
/*
 * Copyright 2014 Yubico.
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

package com.yubico.u2f.crypto;

import com.yubico.u2f.exceptions.U2fBadInputException;

import java.security.PublicKey;
import java.security.cert.X509Certificate;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public interface Crypto {
    void checkSignature(X509Certificate attestationCertificate, byte[] signedBytes,
                        byte[] signature) throws U2fBadInputException;

    void checkSignature(PublicKey publicKey, byte[] signedBytes,
                        byte[] signature) throws U2fBadInputException;

    PublicKey decodePublicKey(byte[] encodedPublicKey) throws U2fBadInputException;

    byte[] hash(byte[] bytes);

    byte[] hash(String str);
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/crypto/RandomChallengeGenerator.java
================================================
/*
 * Copyright 2014 Yubico.
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

package com.yubico.u2f.crypto;

import java.security.SecureRandom;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class RandomChallengeGenerator implements ChallengeGenerator {

    private final SecureRandom random = new SecureRandom();

    @Override
    public byte[] generateChallenge() {
        byte[] randomBytes = new byte[32];
        random.nextBytes(randomBytes);
        return randomBytes;
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/DeviceRegistration.java
================================================
/*
 * Copyright 2014 Yubico.
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

package com.yubico.u2f.data;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.base.MoreObjects;
import com.yubico.u2f.data.messages.json.JsonSerializable;
import com.yubico.u2f.data.messages.key.util.CertificateParser;
import com.yubico.u2f.data.messages.key.util.U2fB64Encoding;
import com.yubico.u2f.exceptions.InvalidDeviceCounterException;
import com.yubico.u2f.exceptions.U2fBadInputException;
import java.io.Serializable;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import lombok.EqualsAndHashCode;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
@EqualsAndHashCode(of = { "keyHandle", "publicKey", "attestationCert" })
public class DeviceRegistration extends JsonSerializable implements Serializable {
    private static final long serialVersionUID = -142942195464329902L;
    public static final long INITIAL_COUNTER_VALUE = -1;

    @JsonProperty
    private final String keyHandle;
    @JsonProperty
    private final String publicKey;
    @JsonProperty
    private final String attestationCert;
    @JsonProperty
    private long counter;
    @JsonProperty
    private boolean compromised;

    @JsonCreator
    public DeviceRegistration(@JsonProperty("keyHandle") String keyHandle, @JsonProperty("publicKey") String publicKey, @JsonProperty("attestationCert") String attestationCert, @JsonProperty("counter") long counter, @JsonProperty("compromised") boolean compromised) {
        this.keyHandle = keyHandle;
        this.publicKey = publicKey;
        this.attestationCert = attestationCert;
        this.counter = counter;
        this.compromised = compromised;
    }

    public DeviceRegistration(String keyHandle, String publicKey, X509Certificate attestationCert, long counter)
            throws U2fBadInputException {
        this.keyHandle = keyHandle;
        this.publicKey = publicKey;
        try {
            this.attestationCert = U2fB64Encoding.encode(attestationCert.getEncoded());
        } catch (CertificateEncodingException e) {
            throw new U2fBadInputException("Malformed attestation certificate", e);
        }
        this.counter = counter;
    }

    public String getKeyHandle() {
        return keyHandle;
    }

    public String getPublicKey() {
        return publicKey;
    }

    @JsonIgnore
    public X509Certificate getAttestationCertificate() throws U2fBadInputException, CertificateException {
        if (attestationCert == null) {
            return null;
        } else {
            return CertificateParser.parseDer(U2fB64Encoding.decode(attestationCert));
        }
    }

    public long getCounter() {
        return counter;
    }

    public boolean isCompromised() {
        return compromised;
    }

    public void markCompromised() {
        compromised = true;
    }

    @Override
    public String toString() {
        X509Certificate certificate = null;
        try {
            certificate = getAttestationCertificate();
        } catch (CertificateException e) {
            // do nothing
        } catch (U2fBadInputException e) {
            // do nothing
        }
        return MoreObjects.toStringHelper(this)
                .omitNullValues()
                .add("Key handle", keyHandle)
                .add("Public key", publicKey)
                .add("Counter", counter)
                .add("Attestation certificate", certificate)
                .toString();
    }

    public static DeviceRegistration fromJson(String json) throws U2fBadInputException {
        return fromJson(json, DeviceRegistration.class);
    }

    @Override
    public String toJson() {
        try {
            return OBJECT_MAPPER.writeValueAsString(new DeviceWithoutCertificate(keyHandle, publicKey, counter, compromised));
        } catch (JsonProcessingException e) {
            throw new IllegalStateException(e);
        }
    }

    public String toJsonWithAttestationCert() {
        return super.toJson();
    }

    public void checkAndUpdateCounter(long clientCounter) throws InvalidDeviceCounterException {
        if (clientCounter <= getCounter()) {
            markCompromised();
            throw new InvalidDeviceCounterException(this);
        }
        counter = clientCounter;
    }

    private static class DeviceWithoutCertificate {
        @JsonProperty
        private final String keyHandle;
        @JsonProperty
        private final String publicKey;
        @JsonProperty
        private final long counter;
        @JsonProperty
        private final boolean compromised;

        private DeviceWithoutCertificate(String keyHandle, String publicKey, long counter, boolean compromised) {
            this.keyHandle = keyHandle;
            this.publicKey = publicKey;
            this.counter = counter;
            this.compromised = compromised;
        }
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/ClientData.java
================================================
package com.yubico.u2f.data.messages;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import com.yubico.u2f.data.messages.key.util.U2fB64Encoding;
import com.yubico.u2f.exceptions.U2fBadInputException;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Set;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class ClientData {

    private static final String TYPE_PARAM = "typ";
    private static final String CHALLENGE_PARAM = "challenge";
    private static final String ORIGIN_PARAM = "origin";

    private final String type;
    private final String challenge;
    private final String origin;
    private final String rawClientData;

    public String asJson() {
        return rawClientData;
    }

    public ClientData(String clientData) throws U2fBadInputException {
        rawClientData = new String(U2fB64Encoding.decode(clientData));
        try {
            JsonNode data = new ObjectMapper().readTree(rawClientData);
            type = getString(data, TYPE_PARAM);
            challenge = getString(data, CHALLENGE_PARAM);
            origin = getString(data, ORIGIN_PARAM);
        } catch (IOException e) {
            throw new U2fBadInputException("Malformed ClientData", e);
        }
    }

    @Override
    public String toString() {
        return rawClientData;
    }

    public String getChallenge() {
        return challenge;
    }

    private static String getString(JsonNode data, String key) throws U2fBadInputException {
        JsonNode node = data.get(key);
        if (node == null) {
            throw new U2fBadInputException("Bad clientData: missing field " + key);
        }
        if (!node.isTextual()) {
            throw new U2fBadInputException("Bad clientData: field " + key + " not a string");
        }
        return node.asText();
    }

    public void checkContent(String type, String challenge, Optional<Set<String>> facets) throws U2fBadInputException {
        if (!type.equals(this.type)) {
            throw new U2fBadInputException("Bad clientData: wrong type " + this.type);
        }
        if (!challenge.equals(this.challenge)) {
            throw new U2fBadInputException("Bad clientData: wrong challenge");
        }
        if (facets.isPresent()) {
            Set<String> allowedFacets = canonicalizeOrigins(facets.get());
            String canonicalOrigin;
            try {
                canonicalOrigin = canonicalizeOrigin(origin);
            } catch (RuntimeException e) {
                throw new U2fBadInputException("Bad clientData: Malformed origin", e);
            }
            verifyOrigin(canonicalOrigin, allowedFacets);
        }
    }

    private static void verifyOrigin(String origin, Set<String> allowedOrigins) throws U2fBadInputException {
        if (!allowedOrigins.contains(origin)) {
            throw new U2fBadInputException(origin +
                    " is not a recognized facet for this application");
        }
    }

    public static Set<String> canonicalizeOrigins(Set<String> origins) {
        ImmutableSet.Builder<String> result = ImmutableSet.builder();
        for (String origin : origins) {
            result.add(canonicalizeOrigin(origin));
        }
        return result.build();
    }

    public static String canonicalizeOrigin(String url) {
        try {
            URI uri = new URI(url);
            if (uri.getAuthority() == null) {
                return url;
            }
            return uri.getScheme() + "://" + uri.getAuthority();
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException("specified bad origin", e);
        }
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/RegisterRequest.java
================================================
/*
 * Copyright 2014 Yubico.
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

package com.yubico.u2f.data.messages;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.yubico.u2f.U2fPrimitives;
import com.yubico.u2f.data.messages.json.JsonSerializable;
import com.yubico.u2f.data.messages.json.Persistable;
import com.yubico.u2f.exceptions.U2fBadInputException;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
@Value
@Builder
@AllArgsConstructor
@JsonDeserialize(builder = RegisterRequest.RegisterRequestBuilder.class)
public class RegisterRequest extends JsonSerializable implements Persistable {

    private static final long serialVersionUID = 24349091760814188L;

    /**
     * Version of the protocol that the to-be-registered U2F token must speak. For
     * the version of the protocol described herein, must be "U2F_V2"
     */
    @NonNull String version;

    /**
     * The websafe-base64-encoded challenge.
     */
    @NonNull String challenge;

    /**
     * The application id that the RP would like to assert. The U2F token will
     * enforce that the key handle provided above is associated with this
     * application id. The browser enforces that the calling origin belongs to the
     * application identified by the application id.
     */
    @NonNull String appId;

    public RegisterRequest(String challenge, String appId) {
        this(U2fPrimitives.U2F_VERSION, challenge, appId);
    }

    @Override
    public String getRequestId() {
        return getChallenge();
    }

    public static RegisterRequest fromJson(String json) throws U2fBadInputException {
        return fromJson(json, RegisterRequest.class);
    }

    @JsonPOJOBuilder(withPrefix = "")
    static class RegisterRequestBuilder {}
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/RegisterRequestData.java
================================================
package com.yubico.u2f.data.messages;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.yubico.u2f.U2fPrimitives;
import com.yubico.u2f.crypto.ChallengeGenerator;
import com.yubico.u2f.data.DeviceRegistration;
import com.yubico.u2f.data.messages.json.JsonSerializable;
import com.yubico.u2f.data.messages.json.Persistable;
import com.yubico.u2f.exceptions.U2fBadInputException;
import java.util.List;
import lombok.EqualsAndHashCode;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
@EqualsAndHashCode
public class RegisterRequestData extends JsonSerializable implements Persistable {

    private static final long serialVersionUID = 60855174227617680L;

    @JsonProperty
    private final String appId;
    @JsonProperty
    private final List<RegisteredKey> registeredKeys;
    @JsonProperty
    private final List<RegisterRequest> registerRequests;

    public RegisterRequestData(@JsonProperty("appId") String appId, @JsonProperty("registeredKeys") List<RegisteredKey> registeredKeys, @JsonProperty("registerRequests") List<RegisterRequest> registerRequests) {
        this.appId = appId;
        this.registeredKeys = registeredKeys;
        this.registerRequests = registerRequests;
    }

    public RegisterRequestData(String appId, Iterable<? extends DeviceRegistration> devices, U2fPrimitives u2f, ChallengeGenerator challengeGenerator) {
        this.appId = appId;

        ImmutableList.Builder<RegisteredKey> registeredKeys = ImmutableList.builder();
        for (DeviceRegistration device : devices) {
            if(!device.isCompromised()) {
                registeredKeys.add(new RegisteredKey(device.getKeyHandle()));
            }
        }

        this.registeredKeys = registeredKeys.build();
        this.registerRequests = ImmutableList.of(u2f.startRegistration(appId, challengeGenerator.generateChallenge()));
    }

    public List<RegisteredKey> getRegisteredKeys() {
        return ImmutableList.copyOf(registeredKeys);
    }

    public List<RegisterRequest> getRegisterRequests() {
        return ImmutableList.copyOf(registerRequests);
    }

    public RegisterRequest getRegisterRequest(RegisterResponse response) {
        return Iterables.getOnlyElement(registerRequests);
    }

    public String getRequestId() {
        return Iterables.getOnlyElement(registerRequests).getChallenge();
    }

    public static RegisterRequestData fromJson(String json) throws U2fBadInputException {
        return fromJson(json, RegisterRequestData.class);
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/RegisterResponse.java
================================================
/*
 * Copyright 2014 Yubico.
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

package com.yubico.u2f.data.messages;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.yubico.u2f.data.messages.json.JsonSerializable;
import com.yubico.u2f.data.messages.json.Persistable;
import com.yubico.u2f.exceptions.U2fBadInputException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import lombok.EqualsAndHashCode;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
@EqualsAndHashCode
@JsonIgnoreProperties(ignoreUnknown = true)
public class RegisterResponse extends JsonSerializable implements Persistable {
    private static final int MAX_SIZE = 20000;

    /**
     * base64(raw registration response message)
     */
    @JsonProperty
    private final String registrationData;

    /**
     * base64(UTF8(client data))
     */
    @JsonProperty("clientData")
    private final String clientDataRaw;

    private transient ClientData clientDataRef;

    @JsonCreator
    public RegisterResponse(@JsonProperty("registrationData") String registrationData, @JsonProperty("clientData") String clientData) throws U2fBadInputException {
        this.registrationData = checkNotNull(registrationData);
        this.clientDataRaw = checkNotNull(clientData);
        this.clientDataRef = new ClientData(clientData);
    }

    public String getRegistrationData() {
        return registrationData;
    }

    @JsonIgnore
    public ClientData getClientData() {
        return clientDataRef;
    }

    public String getRequestId() {
        return getClientData().getChallenge();
    }

    public static RegisterResponse fromJson(String json) throws U2fBadInputException {
        checkArgument(json.length() < MAX_SIZE, "Client response bigger than allowed");
        return JsonSerializable.fromJson(json, RegisterResponse.class);
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        try {
            clientDataRef = new ClientData(clientDataRaw);
        } catch (U2fBadInputException e) {
            throw new IOException(e);
        }
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/RegisteredKey.java
================================================
package com.yubico.u2f.data.messages;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.yubico.u2f.U2fPrimitives;
import com.yubico.u2f.data.messages.json.JsonSerializable;
import java.io.Serializable;
import java.util.Set;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;


/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
@Value
@Builder
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonDeserialize(builder = RegisteredKey.RegisteredKeyBuilder.class)
public class RegisteredKey extends JsonSerializable implements Serializable {

    private static final long serialVersionUID = -5509788965855488374L;

    /**
     * Version of the protocol that the to-be-registered U2F token must speak. For
     * the version of the protocol described herein, must be "U2F_V2"
     */
    @NonNull
    String version;

    /**
     * websafe-base64 encoding of the key handle obtained from the U2F token
     * during registration.
     */
    @NonNull String keyHandle;

    String appId;
    Set<String> transports;

    public RegisteredKey(String keyHandle) {
        this(U2fPrimitives.U2F_VERSION, keyHandle, null, null);
    }

    @JsonPOJOBuilder(withPrefix = "")
    public static class RegisteredKeyBuilder {}
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/SignRequest.java
================================================
/*
 * Copyright 2014 Yubico.
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

package com.yubico.u2f.data.messages;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.yubico.u2f.U2fPrimitives;
import com.yubico.u2f.data.messages.json.JsonSerializable;
import com.yubico.u2f.data.messages.json.Persistable;
import com.yubico.u2f.exceptions.U2fBadInputException;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
@Value
@Builder
@JsonDeserialize(builder = SignRequest.SignRequestBuilder.class)
public class SignRequest extends JsonSerializable implements Persistable {

    private static final long serialVersionUID = -27808961388655010L;

    /**
     * Version of the protocol that the to-be-registered U2F token must speak. For
     * the version of the protocol described herein, must be "U2F_V2"
     */
    @JsonProperty
    @NonNull @Builder.Default String version = U2fPrimitives.U2F_VERSION;

    /**
     * The websafe-base64-encoded challenge.
     */
    @JsonProperty
    @NonNull String challenge;

    /**
     * The application id that the RP would like to assert. The U2F token will
     * enforce that the key handle provided above is associated with this
     * application id. The browser enforces that the calling origin belongs to the
     * application identified by the application id.
     */
    @JsonProperty
    @NonNull String appId;

    /**
     * websafe-base64 encoding of the key handle obtained from the U2F token
     * during registration.
     */
    @JsonProperty
    @NonNull String keyHandle;

    public String getRequestId() {
        return challenge;
    }

    public static SignRequest fromJson(String json) throws U2fBadInputException {
        return fromJson(json, SignRequest.class);
    }

    @JsonPOJOBuilder(withPrefix = "")
    public static class SignRequestBuilder {}
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/SignRequestData.java
================================================
package com.yubico.u2f.data.messages;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.yubico.u2f.U2fPrimitives;
import com.yubico.u2f.crypto.ChallengeGenerator;
import com.yubico.u2f.data.DeviceRegistration;
import com.yubico.u2f.data.messages.json.JsonSerializable;
import com.yubico.u2f.data.messages.json.Persistable;
import com.yubico.u2f.data.messages.key.util.U2fB64Encoding;
import com.yubico.u2f.exceptions.NoEligibleDevicesException;
import com.yubico.u2f.exceptions.U2fBadInputException;
import java.util.List;
import lombok.EqualsAndHashCode;

import static com.google.common.base.Preconditions.checkArgument;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
@EqualsAndHashCode
public class SignRequestData extends JsonSerializable implements Persistable {

    private static final long serialVersionUID = 35378338769078256L;

    @JsonProperty
    private final String appId;

    /**
     * The websafe-base64-encoded challenge.
     */
    @JsonProperty
    private final String challenge;

    @JsonProperty
    private final List<SignRequest> signRequests;

    @JsonCreator
    public SignRequestData(@JsonProperty("appId") String appId, @JsonProperty("challenge") String challenge, @JsonProperty("signRequests") List<SignRequest> signRequests) {
        this.appId = appId;
        this.challenge = challenge;
        this.signRequests = signRequests;
    }

    public SignRequestData(String appId, Iterable<? extends DeviceRegistration> devices, U2fPrimitives u2f, ChallengeGenerator challengeGenerator) throws NoEligibleDevicesException {
        this.appId = appId;

        byte[] challenge = challengeGenerator.generateChallenge();
        this.challenge = U2fB64Encoding.encode(challenge);

        ImmutableList.Builder<SignRequest> requestBuilder = ImmutableList.builder();
        for (DeviceRegistration device : devices) {
            if(!device.isCompromised()) {
                requestBuilder.add(u2f.startSignature(appId, device, challenge));
            }
        }
        signRequests = requestBuilder.build();

        if (signRequests.isEmpty()) {
            if(Iterables.isEmpty(devices)) {
                throw new NoEligibleDevicesException(ImmutableList.<DeviceRegistration>of(), "No devices registrered");
            } else {
                throw new NoEligibleDevicesException(devices, "All devices compromised");
            }
        }
    }

    public List<SignRequest> getSignRequests() {
        return ImmutableList.copyOf(signRequests);
    }

    public SignRequest getSignRequest(SignResponse response) throws U2fBadInputException {
        checkArgument(Objects.equal(getRequestId(), response.getRequestId()), "Wrong request for response data");

        for (SignRequest request : signRequests) {
            if (Objects.equal(request.getKeyHandle(), response.getKeyHandle())) {
                return request;
            }
        }
        throw new U2fBadInputException("Responses keyHandle does not match any contained request");
    }

    public String getRequestId() {
        return signRequests.get(0).getChallenge();
    }

    public static SignRequestData fromJson(String json) throws U2fBadInputException {
        return fromJson(json, SignRequestData.class);
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/SignResponse.java
================================================
/*
 * Copyright 2014 Yubico.
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

package com.yubico.u2f.data.messages;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.yubico.u2f.data.messages.json.JsonSerializable;
import com.yubico.u2f.data.messages.json.Persistable;
import com.yubico.u2f.exceptions.U2fBadInputException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import lombok.EqualsAndHashCode;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
@JsonIgnoreProperties(ignoreUnknown = true)
@EqualsAndHashCode
public class SignResponse extends JsonSerializable implements Persistable {
    private static final int MAX_SIZE = 20000;

    /* base64(client data) */
    @JsonProperty("clientData")
    private final String clientDataRaw;

    @JsonIgnore
    private transient ClientData clientDataRef;

    /* base64(raw response from U2F device) */
    @JsonProperty
    private final String signatureData;

    /* keyHandle originally passed */
    @JsonProperty
    private final String keyHandle;

    @JsonCreator
    public SignResponse(@JsonProperty("clientData") String clientData, @JsonProperty("signatureData") String signatureData, @JsonProperty("keyHandle") String keyHandle) throws U2fBadInputException {
        this.clientDataRaw = checkNotNull(clientData);
        this.signatureData = checkNotNull(signatureData);
        this.keyHandle = checkNotNull(keyHandle);
        clientDataRef = new ClientData(clientData);
    }

    @JsonIgnore
    public ClientData getClientData() {
        return clientDataRef;
    }

    public String getSignatureData() {
        return signatureData;
    }

    public String getKeyHandle() {
        return keyHandle;
    }

    public String getRequestId() {
        return getClientData().getChallenge();
    }

    public static SignResponse fromJson(String json) throws U2fBadInputException {
        checkArgument(json.length() < MAX_SIZE, "Client response bigger than allowed");
        return fromJson(json, SignResponse.class);
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        try {
            clientDataRef = new ClientData(clientDataRaw);
        } catch (U2fBadInputException e) {
            throw new IOException(e);
        }
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/json/JsonSerializable.java
================================================
package com.yubico.u2f.data.messages.json;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yubico.u2f.exceptions.U2fBadInputException;

import java.io.IOException;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public abstract class JsonSerializable {
    protected static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    @JsonIgnore
    public String toJson() {
        try {
            return OBJECT_MAPPER.writeValueAsString(this);
        } catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
    }

    @Override
    public String toString() {
        return toJson();
    }

    public static <T extends JsonSerializable> T fromJson(String json, Class<T> cls) throws U2fBadInputException {
        try {
            return OBJECT_MAPPER.readValue(json, cls);
        } catch (JsonMappingException e) {
            throw new U2fBadInputException("Invalid JSON data", e);
        } catch (JsonParseException e) {
            throw new U2fBadInputException("Invalid JSON data", e);
        } catch (IOException e) {
            throw new U2fBadInputException("Invalid JSON data", e);
        }
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/json/Persistable.java
================================================
package com.yubico.u2f.data.messages.json;

import com.fasterxml.jackson.annotation.JsonIgnore;

import java.io.Serializable;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public interface Persistable extends Serializable {
    @JsonIgnore
    public String getRequestId();

    public String toJson();
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/key/RawRegisterResponse.java
================================================
/*
 * Copyright 2014 Yubico.
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

package com.yubico.u2f.data.messages.key;

import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import com.yubico.u2f.crypto.BouncyCastleCrypto;
import com.yubico.u2f.crypto.Crypto;
import com.yubico.u2f.data.DeviceRegistration;
import com.yubico.u2f.data.messages.key.util.ByteInputStream;
import com.yubico.u2f.data.messages.key.util.CertificateParser;
import com.yubico.u2f.data.messages.key.util.U2fB64Encoding;
import com.yubico.u2f.exceptions.U2fBadInputException;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import lombok.EqualsAndHashCode;

/**
 * The register response produced by the token/key, which is transformed by the client into an RegisterResponse
 * and sent to the server.
 *
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
@EqualsAndHashCode
public class RawRegisterResponse {
    public static final byte REGISTRATION_RESERVED_BYTE_VALUE = (byte) 0x05;
    public static final byte REGISTRATION_SIGNED_RESERVED_BYTE_VALUE = (byte) 0x00;

    private transient final Crypto crypto;

    /**
     * The (uncompressed) x,y-representation of a curve point on the P-256
     * NIST elliptic curve.
     */
    final byte[] userPublicKey;

    /**
     * A handle that allows the U2F token to identify the generated key pair.
     */
    final byte[] keyHandle;
    final X509Certificate attestationCertificate;

    /**
     * A ECDSA signature (on P-256)
     */
    final byte[] signature;

    public RawRegisterResponse(byte[] userPublicKey,
                               byte[] keyHandle,
                               X509Certificate attestationCertificate,
                               byte[] signature) {
        this(userPublicKey, keyHandle, attestationCertificate, signature, new BouncyCastleCrypto());
    }

    public RawRegisterResponse(byte[] userPublicKey,
                               byte[] keyHandle,
                               X509Certificate attestationCertificate,
                               byte[] signature,
                               Crypto crypto) {
        this.userPublicKey = userPublicKey;
        this.keyHandle = keyHandle;
        this.attestationCertificate = attestationCertificate;
        this.signature = signature;
        this.crypto = crypto;
    }

    public static RawRegisterResponse fromBase64(String rawDataBase64, Crypto crypto) throws U2fBadInputException {
        ByteInputStream bytes = new ByteInputStream(U2fB64Encoding.decode(rawDataBase64));
        try {
            byte reservedByte = bytes.readSigned();
            if (reservedByte != REGISTRATION_RESERVED_BYTE_VALUE) {
                throw new U2fBadInputException(
                        "Incorrect value of reserved byte. Expected: " + REGISTRATION_RESERVED_BYTE_VALUE +
                                ". Was: " + reservedByte
                );
            }

            return new RawRegisterResponse(
                    bytes.read(65),
                    bytes.read(bytes.readUnsigned()),
                    CertificateParser.parseDer(bytes),
                    bytes.readAll(),
                    crypto
            );
        } catch (CertificateException e) {
            throw new U2fBadInputException("Malformed attestation certificate", e);
        } catch (IOException e) {
            throw new U2fBadInputException("Truncated registration data", e);
        }
    }

    public void checkSignature(String appId, String clientData) throws U2fBadInputException {
        byte[] signedBytes = packBytesToSign(crypto.hash(appId), crypto.hash(clientData), keyHandle, userPublicKey);
        crypto.checkSignature(attestationCertificate, signedBytes, signature);
    }

    public static byte[] packBytesToSign(byte[] appIdHash, byte[] clientDataHash, byte[] keyHandle, byte[] userPublicKey) {
        ByteArrayDataOutput encoded = ByteStreams.newDataOutput();
        encoded.write(REGISTRATION_SIGNED_RESERVED_BYTE_VALUE);
        encoded.write(appIdHash);
        encoded.write(clientDataHash);
        encoded.write(keyHandle);
        encoded.write(userPublicKey);
        return encoded.toByteArray();
    }

    public DeviceRegistration createDevice() throws U2fBadInputException {
        return new DeviceRegistration(
                U2fB64Encoding.encode(keyHandle),
                U2fB64Encoding.encode(userPublicKey),
                attestationCertificate,
                DeviceRegistration.INITIAL_COUNTER_VALUE
        );
    }

}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/key/RawSignResponse.java
================================================
/*
 * Copyright 2014 Yubico.
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

package com.yubico.u2f.data.messages.key;

import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import com.yubico.u2f.crypto.BouncyCastleCrypto;
import com.yubico.u2f.crypto.Crypto;
import com.yubico.u2f.data.messages.SignResponse;
import com.yubico.u2f.data.messages.key.util.ByteInputStream;
import com.yubico.u2f.data.messages.key.util.U2fB64Encoding;
import com.yubico.u2f.exceptions.U2fBadInputException;
import java.io.IOException;
import lombok.EqualsAndHashCode;

/**
 * The sign response produced by the token/key, which is transformed by the client into an
 * {@link SignResponse} and sent to the server.
 *
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
@EqualsAndHashCode(of = { "userPresence", "counter", "signature" })
public class RawSignResponse {
    public static final byte USER_PRESENT_FLAG = 0x01;

    private final byte userPresence;
    private final long counter;
    private final byte[] signature;
    private final Crypto crypto;

    public RawSignResponse(byte userPresence, long counter, byte[] signature) {
        this(userPresence, counter, signature, new BouncyCastleCrypto());
    }

    public RawSignResponse(byte userPresence, long counter, byte[] signature, Crypto crypto) {
        this.userPresence = userPresence;
        this.counter = counter;
        this.signature = signature;
        this.crypto = crypto;
    }

    public static RawSignResponse fromBase64(String rawDataBase64, Crypto crypto) throws U2fBadInputException {
        ByteInputStream bytes = new ByteInputStream(U2fB64Encoding.decode(rawDataBase64));
        try {
            return new RawSignResponse(
                    bytes.readSigned(),
                    bytes.readInteger(),
                    bytes.readAll(),
                    crypto
            );
        } catch (IOException e) {
            throw new U2fBadInputException("Truncated authentication data", e);
        }
    }

    public void checkSignature(String appId, String clientData, byte[] publicKey) throws U2fBadInputException {
        byte[] signedBytes = packBytesToSign(
                crypto.hash(appId),
                userPresence,
                counter,
                crypto.hash(clientData)
        );
        crypto.checkSignature(
                crypto.decodePublicKey(publicKey),
                signedBytes,
                signature
        );
    }

    public static byte[] packBytesToSign(byte[] appIdHash, byte userPresence, long counter, byte[] challengeHash) {
        ByteArrayDataOutput encoded = ByteStreams.newDataOutput();
        encoded.write(appIdHash);
        encoded.write(userPresence);
        encoded.writeInt((int) counter);
        encoded.write(challengeHash);
        return encoded.toByteArray();
    }

    /**
     * Bit 0 is set to 1, which means that user presence was verified. (This version of the protocol doesn't specify a
     * way to request sign responses without requiring user presence.) A different value of bit 0, as well as bits 1
     * through 7, are reserved for future use. The values of bit 1 through 7 SHOULD be 0
     */
    public byte getUserPresence() {
        return userPresence;
    }

    /**
     * This is the big-endian representation of a counter value that the U2F device
     * increments every time it performs a sign operation.
     */
    public long getCounter() {
        return counter;
    }

    /**
     * This is a ECDSA signature (on P-256)
     */
    public byte[] getSignature() {
        return signature;
    }

    public void checkUserPresence() throws U2fBadInputException {
        if (userPresence != USER_PRESENT_FLAG) {
            throw new U2fBadInputException("User presence invalid during signing");
        }
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/key/util/ByteInputStream.java
================================================
/*
 * Copyright 2014 Yubico.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */

package com.yubico.u2f.data.messages.key.util;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;

/**
 * Provides an easy way to read a byte array in chunks.
 *
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class ByteInputStream extends DataInputStream {

    public ByteInputStream(byte[] data) {
        super(new ByteArrayInputStream(data));
    }

    public byte[] read(int numberOfBytes) throws IOException {
        byte[] readBytes = new byte[numberOfBytes];
        readFully(readBytes);
        return readBytes;
    }

    public byte[] readAll() throws IOException {
        byte[] readBytes = new byte[available()];
        readFully(readBytes);
        return readBytes;
    }

    public int readInteger() throws IOException {
        return readInt();
    }

    public byte readSigned() throws IOException {
        return readByte();
    }

    public int readUnsigned() throws IOException {
        return readUnsignedByte();
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/key/util/CertificateParser.java
================================================
package com.yubico.u2f.data.messages.key.util;

import com.google.common.io.BaseEncoding;
import com.yubico.u2f.crypto.BouncyCastleCrypto;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringReader;
import java.security.Provider;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.List;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class CertificateParser {
    private static final Provider BC_PROVIDER = new BouncyCastleCrypto().getProvider();

    private final static List<String> FIXSIG = Arrays.asList(
            "CN=Yubico U2F EE Serial 776137165",
            "CN=Yubico U2F EE Serial 1086591525",
            "CN=Yubico U2F EE Serial 1973679733",
            "CN=Yubico U2F EE Serial 13503277888",
            "CN=Yubico U2F EE Serial 13831167861",
            "CN=Yubico U2F EE Serial 14803321578"
    );


    public static X509Certificate parsePem(String pemEncodedCert) throws CertificateException {
        return parseDer(pemEncodedCert.replaceAll("-----BEGIN CERTIFICATE-----", "").replaceAll("-----END CERTIFICATE-----", "").replaceAll("\n", ""));
    }

    public static X509Certificate parseDer(String base64DerEncodedCert) throws CertificateException {
        return parseDer(BaseEncoding.base64().decodingStream(new StringReader(base64DerEncodedCert)));
    }

    public static X509Certificate parseDer(byte[] derEncodedCert) throws CertificateException {
        return parseDer(new ByteArrayInputStream(derEncodedCert));
    }

    public static X509Certificate parseDer(InputStream is) throws CertificateException {
        X509Certificate cert = (X509Certificate) CertificateFactory.getInstance("X.509", BC_PROVIDER).generateCertificate(is);
        //Some known certs have an incorrect "unused bits" value, which causes problems on newer versions of BouncyCastle.
        if(FIXSIG.contains(cert.getSubjectDN().getName())) {
            byte[] encoded = cert.getEncoded();
            encoded[encoded.length-257] = 0;  // Fix the "unused bits" field (should always be 0).
            cert = (X509Certificate) CertificateFactory.getInstance("X.509", BC_PROVIDER).generateCertificate(new ByteArrayInputStream(encoded));
        }
        return cert;
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/key/util/U2fB64Encoding.java
================================================
package com.yubico.u2f.data.messages.key.util;

import com.google.common.io.BaseEncoding;
import com.yubico.u2f.exceptions.U2fBadInputException;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class U2fB64Encoding {
    private final static BaseEncoding BASE64_ENCODER = BaseEncoding.base64Url().omitPadding();
    private final static BaseEncoding BASE64_DECODER = BaseEncoding.base64Url();

    public static String encode(byte[] decoded) {
        return BASE64_ENCODER.encode(decoded);
    }

    public static byte[] decode(String encoded) throws U2fBadInputException {
        try {
            return BASE64_DECODER.decode(encoded);
        } catch (IllegalArgumentException e) {
            throw new U2fBadInputException("Bad base64 encoding", e);
        }
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/DeviceCompromisedException.java
================================================
package com.yubico.u2f.exceptions;

import com.yubico.u2f.data.DeviceRegistration;
import lombok.Getter;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
@Getter
public class DeviceCompromisedException extends U2fAuthenticationException {
    private final DeviceRegistration deviceRegistration;

    public DeviceCompromisedException(DeviceRegistration deviceRegistration, String message, Throwable cause) {
        super(message, cause);
        this.deviceRegistration = deviceRegistration;
    }

    public DeviceCompromisedException(DeviceRegistration deviceRegistration, String message) {
        super(message);
        this.deviceRegistration = deviceRegistration;
    }

}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/InvalidDeviceCounterException.java
================================================
package com.yubico.u2f.exceptions;

import com.yubico.u2f.data.DeviceRegistration;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class InvalidDeviceCounterException extends DeviceCompromisedException {
    public InvalidDeviceCounterException(DeviceRegistration registration) {
        super(registration, "The device's internal counter was was smaller than expected." +
                "It's possible that the device has been cloned!");
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/NoEligableDevicesException.java
================================================
package com.yubico.u2f.exceptions;

import com.google.common.collect.ImmutableList;
import com.yubico.u2f.data.DeviceRegistration;

import java.util.List;
import lombok.Getter;

/**
 * @deprecated use {@link NoEligibleDevicesException}
 */
@Deprecated
@Getter
public class NoEligableDevicesException extends U2fAuthenticationException {
    private final List<DeviceRegistration> devices;

    public NoEligableDevicesException(Iterable<? extends DeviceRegistration> devices, String message, Throwable cause) {
        super(message, cause);
        this.devices = ImmutableList.copyOf(devices);
    }

    public NoEligableDevicesException(Iterable<? extends DeviceRegistration> devices, String message) {
        super(message);
        this.devices = ImmutableList.copyOf(devices);
    }

    public boolean hasDevices() {
        return !devices.isEmpty();
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/NoEligibleDevicesException.java
================================================
package com.yubico.u2f.exceptions;

import com.yubico.u2f.data.DeviceRegistration;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
@SuppressWarnings("deprecation")
public class NoEligibleDevicesException extends NoEligableDevicesException {

    public NoEligibleDevicesException(Iterable<? extends DeviceRegistration> devices, String message, Throwable cause) {
        super(devices, message, cause);
    }

    public NoEligibleDevicesException(Iterable<? extends DeviceRegistration> devices, String message) {
        super(devices, message);
    }

}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/U2fAuthenticationException.java
================================================
package com.yubico.u2f.exceptions;

/**
 * Base class for exceptions thrown when a U2F authentication ceremony fails.
 *
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class U2fAuthenticationException extends U2fCeremonyException {
    public U2fAuthenticationException(String message, Throwable cause) {
        super(message, cause);
    }

    public U2fAuthenticationException(String message) {
        super(message);
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/U2fBadConfigurationException.java
================================================
package com.yubico.u2f.exceptions;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class U2fBadConfigurationException extends Exception {
    public U2fBadConfigurationException(String message) {
        super(message);
    }

    public U2fBadConfigurationException(String message, Throwable cause) {
        super(message, cause);
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/U2fBadInputException.java
================================================
/*
 * Copyright 2014 Yubico.
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

package com.yubico.u2f.exceptions;

/**
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
@SuppressWarnings("serial")
public class U2fBadInputException extends Exception {

    public U2fBadInputException(String message) {
        super(message);
    }

    public U2fBadInputException(String message, Throwable cause) {
        super(message, cause);
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/U2fCeremonyException.java
================================================
package com.yubico.u2f.exceptions;

/**
 * Base class for exceptions thrown when a U2F registration or authentication ceremony fails.
 *
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class U2fCeremonyException extends Exception {
    public U2fCeremonyException(String message, Throwable cause) {
        super(message, cause);
    }

    public U2fCeremonyException(String message) {
        super(message);
    }
}


================================================
FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/U2fRegistrationException.java
================================================
package com.yubico.u2f.exceptions;

/**
 * Base class for exceptions thrown when a U2F registration ceremony fails.
 *
 * @deprecated The java-u2flib-server library is obsolete. Use <a
 * href="https://developers.yubico.com/java-webauthn-server/">java-webauthn-server</a> instead.
 */
@Deprecated
public class U2fRegistrationException extends U2fCeremonyException {
    public U2fRegistrationException(String message, Throwable cause) {
        super(message, cause);
    }

    public U2fRegistrationException(String message) {
        super(message);
    }
}


================================================
FILE: u2flib-server-core/src/test/java/com/yubico/u2f/AppIdTest.java
================================================
package com.yubico.u2f;

import com.yubico.u2f.exceptions.U2fBadConfigurationException;
import org.junit.Test;

import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertTrue;

public class AppIdTest {

    @Test
    public void validUrls() {
        assertTrue(isValid("https://www.example.com"));
        assertTrue(isValid("https://internal-server"));
        assertTrue(isValid("https://åäö.se:8443"));
        assertTrue(isValid("https://localhost:8443/myAppId.json"));
    }

    @Test
    public void validUris() {
        assertTrue(isValid("android:apk-key-hash:585215fd5153209a7e246f53286035838a0be227"));
        assertTrue(isValid("ios:bundle-id:com.example.Example"));
    }

    @Test
    public void disallowHttp() {
        assertFalse(isValid("http://www.example.com"));
    }

    @Test
    public void disallowSlashAsPath() {
        assertFalse(isValid("https://www.example.com/"));
    }

    @Test
    public void disallowIP() {
        assertFalse(isValid("https://127.0.0.1:8443"));
        assertFalse(isValid("https://127.0.0.1"));
        assertFalse(isValid("https://127.0.0.1/foo"));
        assertFalse(isValid("https://2001:0db8:0000:0000:0000:ff00:0042:8329"));
        assertFalse(isValid("https://2001:0db8:0000:0000:0000:ff00:0042:8329/åäö"));
    }

    @Test
    public void badSyntax() {
        assertFalse(isValid("https://bad[syntax]"));
    }

    private static boolean isValid(String appId) {
        try {
            AppId.checkIsValid(appId);
            return true;
        } catch (U2fBadConfigurationException e) {
            return false;
        }

    }
}


================================================
FILE: u2flib-server-core/src/test/java/com/yubico/u2f/SystemTest.java
================================================
package com.yubico.u2f;

import com.google.common.collect.ImmutableSet;
import com.yubico.u2f.data.DeviceRegistration;
import com.yubico.u2f.data.messages.SignRequest;
import com.yubico.u2f.data.messages.SignResponse;
import com.yubico.u2f.data.messages.RegisterRequest;
import com.yubico.u2f.data.messages.RegisterResponse;
import org.junit.Ignore;

import java.util.Scanner;

@Ignore("Includes manual steps")
public class SystemTest {

    public static final ImmutableSet<String> TRUSTED_DOMAINS = ImmutableSet.of("http://example.com");
    public static final String APP_ID = "my-app";
    private static Scanner scan = new Scanner(System.in);
    private static final U2fPrimitives u2f = new U2fPrimitives();

    /*
      For manual testing with physical keys. Can e.g. be combined with these libu2f-host commands:

        u2f-host -aregister -o http://example.com
        u2f-host -aauthenticate -o http://example.com
     */
    public static void main(String... args) throws Exception {
        String startedRegistration = u2f.startRegistration(APP_ID).toJson();
        System.out.println("Registration data:");
        System.out.println(startedRegistration);

        System.out.println();
        System.out.println("Enter token response:");

        String json = scan.nextLine();
        RegisterResponse registerResponse = RegisterResponse.fromJson(json);
        registerResponse.getClientData().getChallenge();
        DeviceRegistration deviceRegistration = u2f.finishRegistration(
                RegisterRequest.fromJson(startedRegistration),
                registerResponse,
                TRUSTED_DOMAINS
        );

        System.out.println(deviceRegistration);

        String startedSignature = u2f.startSignature(APP_ID, deviceRegistration).toJson();
        System.out.println("Signature data:");
        System.out.println(startedSignature);

        System.out.println();
        System.out.println("Enter token response:");

        u2f.finishSignature(
                SignRequest.fromJson(startedSignature),
                SignResponse.fromJson(scan.nextLine()),
                deviceRegistration,
                TRUSTED_DOMAINS
        );
        System.out.println("Device counter: " + deviceRegistration.getCounter());
    }
}


================================================
FILE: u2flib-server-core/src/test/java/com/yubico/u2f/TestUtils.java
================================================
/*
 * Copyright 2014 Yubico.
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

package com.yubico.u2f;

import com.google.common.io.BaseEncoding;
import com.google.common.io.ByteArrayDataOutput;
import com.yubico.u2f.data.messages.key.util.CertificateParser;
import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;

import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.util.Scanner;

public class TestUtils {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public static final BaseEncoding HEX = BaseEncoding.base16().lowerCase();
    public static final BaseEncoding BASE64 = BaseEncoding.base64();

    public static X509Certificate fetchCertificate(InputStream resourceAsStream) {
        Scanner in = new Scanner(resourceAsStream);
        String base64String = in.nextLine();
        return parseCertificate(BASE64.decode(base64String));
    }

    public static X509Certificate parseCertificate(byte[] encodedDerCertificate) {
        try {
            return CertificateParser.parseDer(encodedDerCertificate);
        } catch (CertificateException e) {
            throw new RuntimeException(e);
        }
    }

    public static PrivateKey parsePrivateKey(InputStream is) {
        String keyBytesHex = new Scanner(is).nextLine();
        return parsePrivateKey(keyBytesHex);
    }

    public static PrivateKey parsePrivateKey(String keyBytesHex) {
        try {
            KeyFactory fac = KeyFactory.getInstance("ECDSA");
            X9ECParameters curve = SECNamedCurves.getByName("secp256r1");
            ECParameterSpec curveSpec = new ECParameterSpec(
                    curve.getCurve(), curve.getG(), curve.getN(), curve.getH());
            ECPrivateKeySpec keySpec = new ECPrivateKeySpec(
                    new BigInteger(keyBytesHex, 16),
                    curveSpec);
            return fac.generatePrivate(keySpec);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException(e);
        }
    }

    public static PublicKey parsePublicKey(byte[] keyBytes) {
        try {
            X9ECParameters curve = SECNamedCurves.getByName("secp256r1");
            ECParameterSpec curveSpec = new ECParameterSpec(curve.getCurve(), curve.getG(), curve.getN(),
                    curve.getH());
            ECPoint point = curve.getCurve().decodePoint(keyBytes);
            return KeyFactory.getInstance("ECDSA").generatePublic(
                    new ECPublicKeySpec(point, curveSpec));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException(e);
        }
    }

    public static byte[] serialize(Object o) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ObjectOutputStream objectOut = new ObjectOutputStream(out);
        objectOut.writeObject(o);
        objectOut.close();
        return out.toByteArray();
    }

    public static <T> T deserialize(byte[] serialized) throws IOException, ClassNotFoundException {
        ByteArrayInputStream is = new ByteArrayInputStream(serialized);
        ObjectInputStream objectIn = new ObjectInputStream(is);
        T object = (T) objectIn.readObject();
        objectIn.close();
        return  object;
    }

    public static <T> T clone(T input) throws IOException, ClassNotFoundException {
        return deserialize(serialize(input));
    }
}


================================================
FILE: u2flib-server-core/src/test/java/com/yubico/u2f/U2FTest.java
================================================
package com.yubico.u2f;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.yubico.u2f.data.DeviceRegistration;
import com.yubico.u2f.data.messages.SignRequest;
import com.yubico.u2f.data.messages.SignRequestData;
import com.yubico.u2f.data.messages.SignResponse;
import com.yubico.u2f.data.messages.RegisterRequest;
import com.yubico.u2f.data.messages.RegisterRequestData;
import com.yubico.u2f.data.messages.RegisterResponse;
import com.yubico.u2f.data.messages.RegisteredKey;
import com.yubico.u2f.exceptions.DeviceCompromisedException;
import com.yubico.u2f.exceptions.NoEligibleDevicesException;
import com.yubico.u2f.exceptions.U2fBadConfigurationException;
import com.yubico.u2f.exceptions.U2fBadInputException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static com.yubico.u2f.testdata.GnubbyKey.ATTESTATION_CERTIFICATE;
import static com.yubico.u2f.testdata.TestVectors.*;
import static org.hamcrest.core.Is.isA;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class U2FTest {
    U2F u2f = U2F.withoutAppIdValidation();

    @Rule
    public ExpectedException expectedException = ExpectedException.none();

    @Test
    public void startRegistration_compromisedDevice() throws Exception {
        DeviceRegistration deviceRegistration = new DeviceRegistration(KEY_HANDLE_BASE64, USER_PUBLIC_KEY_SIGN_HEX, ATTESTATION_CERTIFICATE, 0);
        deviceRegistration.markCompromised();
        u2f.startRegistration(APP_ID_ENROLL, ImmutableList.of(deviceRegistration));
    }

    @Test(expected = NoEligibleDevicesException.class)
    public void startSignature_compromisedDevices() throws Exception {
        DeviceRegistration deviceRegistration = new DeviceRegistration(KEY_HANDLE_BASE64, USER_PUBLIC_KEY_SIGN_HEX, ATTESTATION_CERTIFICATE, 0);
        deviceRegistration.markCompromised();
        u2f.startSignature(APP_ID_ENROLL, ImmutableList.of(deviceRegistration));
    }

    @Test(expected = U2fBadConfigurationException.class)
    public void defaultConstructedU2FstartRegistrationShouldRefuseInvalidAppId() throws U2fBadInputException, U2fBadConfigurationException {
        DeviceRegistration deviceRegistration = new DeviceRegistration(KEY_HANDLE_BASE64, USER_PUBLIC_KEY_SIGN_HEX, ATTESTATION_CERTIFICATE, 0);
        deviceRegistration.markCompromised();
        new U2F().startRegistration("example.com", ImmutableList.of(deviceRegistration));

        fail("startRegistration did not refuse an invalid app ID.");
    }

    @Test
    public void startRegistrationShouldReturnARandomChallenge() throws U2fBadInputException, U2fBadConfigurationException {
        DeviceRegistration deviceRegistration = new DeviceRegistration(KEY_HANDLE_BASE64, USER_PUBLIC_KEY_SIGN_HEX, ATTESTATION_CERTIFICATE, 0);
        RegisterRequestData data = u2f.startRegistration("example.com", ImmutableList.of(deviceRegistration));
        RegisterRequestData data2 = u2f.startRegistration("example.com", ImmutableList.of(deviceRegistration));

        assertEquals(1, data.getRegisterRequests().size());
        assertEquals(1, data2.getRegisterRequests().size());
        assertNotEquals(
            "startRegistration must not return the same challenge twice in a row.",
            data.getRegisterRequests().get(0).getChallenge(),
            data2.getRegisterRequests().get(0).getChallenge()
        );
    }

    @Test(expected = U2fBadConfigurationException.class)
    public void defaultConstructedU2FstartSignatureShouldRefuseInvalidAppId() throws Exception {
        DeviceRegistration deviceRegistration = new DeviceRegistration(KEY_HANDLE_BASE64, USER_PUBLIC_KEY_SIGN_HEX, ATTESTATION_CERTIFICATE, 0);
        deviceRegistration.markCompromised();
        new U2F().startSignature("example.com", ImmutableList.of(deviceRegistration));

        fail("startRegistration did not refuse an invalid app ID.");
    }

    @Test
    public void startSignatureShouldReturnARandomChallenge() throws Exception {
        DeviceRegistration deviceRegistration = new DeviceRegistration(KEY_HANDLE_BASE64, USER_PUBLIC_KEY_SIGN_HEX, ATTESTATION_CERTIFICATE, 0);
        SignRequestData data = u2f.startSignature("example.com", ImmutableList.of(deviceRegistration));
        SignRequestData data2 = u2f.startSignature("example.com", ImmutableList.of(deviceRegistration));

        assertEquals(1, data.getSignRequests().size());
        assertNotNull(data.getSignRequests().get(0).getChallenge());
        assertNotEquals(
            "startSignature must not return the same challenge twice in a row.",
            data.getSignRequests().get(0).getChallenge(),
            data2.getSignRequests().get(0).getChallenge()
        );
    }

    @Test(expected = DeviceCompromisedException.class)
    public void finishSignature_compromisedDevice() throws Exception {
        DeviceRegistration deviceRegistration = new DeviceRegistration(KEY_HANDLE_BASE64, USER_PUBLIC_KEY_SIGN_HEX, ATTESTATION_CERTIFICATE, 0);

        SignRequest request = SignRequest.builder()
            .challenge(SERVER_CHALLENGE_SIGN_BASE64)
            .appId(APP_ID_SIGN)
            .keyHandle(KEY_HANDLE_BASE64)
            .build();

        SignResponse tokenResponse = new SignResponse(CLIENT_DATA_SIGN_BASE64,
                SIGN_RESPONSE_DATA_BASE64, KEY_HANDLE_BASE64);

        SignRequestData requestData = mock(SignRequestData.class);
        when(requestData.getSignRequest(tokenResponse)).thenReturn(request);

        deviceRegistration.markCompromised();
        u2f.finishSignature(requestData, tokenResponse, ImmutableList.of(deviceRegistration));
    }

    @Test
    public void finishSignature_invalidFacet() throws Exception {
        expectedException.expectCause(isA(U2fBadInputException.class));

        DeviceRegistration deviceRegistration = new DeviceRegistration(KEY_HANDLE_BASE64, USER_PUBLIC_KEY_SIGN_HEX, ATTESTATION_CERTIFICATE, 0);

        SignRequest request = SignRequest.builder()
            .challenge(SERVER_CHALLENGE_SIGN_BASE64)
            .appId(APP_ID_SIGN)
            .keyHandle(KEY_HANDLE_BASE64)
            .build();

        SignResponse tokenResponse = new SignResponse(CLIENT_DATA_SIGN_BASE64,
                SIGN_RESPONSE_DATA_BASE64, KEY_HANDLE_BASE64);

        SignRequestData requestData = mock(SignRequestData.class);
        when(requestData.getSignRequest(tokenResponse)).thenReturn(request);

        u2f.finishSignature(requestData, tokenResponse, ImmutableList.of(deviceRegistration), ImmutableSet.of("https://wrongfacet.com"));
    }


    @Test
    public void finishRegistrationShouldReturnAMatchedDevice() throws Exception {
        DeviceRegistration deviceRegistration = new DeviceRegistration(KEY_HANDLE_BASE64, USER_PUBLIC_KEY_SIGN_HEX, ATTESTATION_CERTIFICATE, 0);
        DeviceRegistration deviceRegistration2 = new DeviceRegistration(KEY_HANDLE_BASE64, USER_PUBLIC_KEY_SIGN_HEX, ATTESTATION_CERTIFICATE, 0);

        RegisterRequest request = new RegisterRequest(SERVER_CHALLENGE_REGISTER_BASE64, APP_ID_ENROLL);

        RegisterResponse tokenResponse = new RegisterResponse(
            REGISTRATION_DATA_BASE64,
            CLIENT_DATA_REGISTRATION_BASE64
        );

        RegisterRequestData registerRequest = new RegisterRequestData(
            APP_ID_ENROLL,
            ImmutableList.<RegisteredKey>of(),
            ImmutableList.of(request)
        );

        DeviceRegistration device = u2f.finishRegistration(registerRequest, tokenResponse, ImmutableSet.of(APP_ID_ENROLL));
        DeviceRegistration overloadDevice = u2f.finishRegistration(registerRequest, tokenResponse);

        assertEquals(KEY_HANDLE_BASE64, device.getKeyHandle());
        assertEquals(device, overloadDevice);
    }

    @Test
    public void finishSignatureShouldReturnAMatchedDevice() throws Exception {
        DeviceRegistration deviceRegistration = new DeviceRegistration(KEY_HANDLE_BASE64, USER_PUBLIC_KEY_SIGN_HEX, ATTESTATION_CERTIFICATE, 0);
        DeviceRegistration deviceRegistration2 = new DeviceRegistration(KEY_HANDLE_BASE64, USER_PUBLIC_KEY_SIGN_HEX, ATTESTATION_CERTIFICATE, 0);

        SignRequest request = SignRequest.builder()
            .challenge(SERVER_CHALLENGE_SIGN_BASE64)
            .appId(APP_ID_SIGN)
            .keyHandle(KEY_HANDLE_BASE64)
            .build();

        SignResponse tokenResponse = new SignResponse(CLIENT_DATA_SIGN_BASE64,
            SIGN_RESPONSE_DATA_BASE64, KEY_HANDLE_BASE64);

        SignRequestData requestData = new SignRequestData(
            APP_ID_SIGN,
            SERVER_CHALLENGE_SIGN_BASE64,
            ImmutableList.of(request)
        );

        DeviceRegistration device = u2f.finishSignature(requestData, tokenResponse, ImmutableList.of(deviceRegistration), ImmutableSet.of(APP_ID_ENROLL));
        DeviceRegistration overloadDevice = u2f.finishSignature(requestData, tokenResponse, ImmutableList.of(deviceRegistration2));

        assertEquals(KEY_HANDLE_BASE64, device.getKeyHandle());
        assertEquals(device, overloadDevice);
    }

}


================================================
FILE: u2flib-server-core/src/test/java/com/yubico/u2f/U2fPrimitivesTest.java
================================================
/*
 * Copyright 2014 Yubico.
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file or at
 * https://developers.google.com/open-source/licenses/bsd
 */

package com.yubico.u2f;

import com.google.common.collect.ImmutableSet;
import com.yubico.u2f.data.DeviceRegistration;
import com.yubico.u2f.data.messages.SignRequest;
import com.yubico.u2f.data.messages.SignResponse;
import com.yubico.u2f.data.messages.RegisterRequest;
import com.yubico.u2f.data.messages.RegisterRespons
Download .txt
gitextract_r69ouwzl/

├── .gitattributes
├── .github/
│   └── workflows/
│       └── scan.yml
├── .gitignore
├── .travis.yml
├── COPYING
├── NEWS
├── README
├── buildSrc/
│   ├── build.gradle
│   └── src/
│       └── main/
│           └── groovy/
│               └── com/
│                   └── yubico/
│                       └── gradle/
│                           └── pitest/
│                               └── tasks/
│                                   └── PitestMergeTask.groovy
├── dev-util/
│   ├── example-authentication.py
│   └── example-registration.py
├── lombok.config
├── pom.xml
├── u2flib-server-attestation/
│   ├── README.adoc
│   ├── build.gradle
│   ├── gradle/
│   │   └── wrapper/
│   │       ├── gradle-wrapper.jar
│   │       └── gradle-wrapper.properties
│   ├── gradlew
│   ├── gradlew.bat
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── yubico/
│       │   │           └── u2f/
│       │   │               └── attestation/
│       │   │                   ├── Attestation.java
│       │   │                   ├── DeviceMatcher.java
│       │   │                   ├── MetadataObject.java
│       │   │                   ├── MetadataResolver.java
│       │   │                   ├── MetadataService.java
│       │   │                   ├── Transport.java
│       │   │                   ├── matchers/
│       │   │                   │   ├── ExtensionMatcher.java
│       │   │                   │   └── FingerprintMatcher.java
│       │   │                   └── resolvers/
│       │   │                       └── SimpleResolver.java
│       │   └── resources/
│       │       └── metadata.json
│       └── test/
│           └── java/
│               └── com/
│                   └── yubico/
│                       └── u2f/
│                           └── attestation/
│                               ├── MetadataObjectTest.java
│                               ├── MetadataServiceTest.java
│                               ├── TransportTest.java
│                               ├── matchers/
│                               │   └── FingerprintMatcherTest.java
│                               └── resolvers/
│                                   └── SimpleResolverTest.java
├── u2flib-server-core/
│   ├── build.gradle
│   ├── gradle/
│   │   └── wrapper/
│   │       ├── gradle-wrapper.jar
│   │       └── gradle-wrapper.properties
│   ├── gradlew
│   ├── gradlew.bat
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── com/
│       │           └── yubico/
│       │               └── u2f/
│       │                   ├── AppId.java
│       │                   ├── U2F.java
│       │                   ├── U2fPrimitives.java
│       │                   ├── crypto/
│       │                   │   ├── BouncyCastleCrypto.java
│       │                   │   ├── ChallengeGenerator.java
│       │                   │   ├── Crypto.java
│       │                   │   └── RandomChallengeGenerator.java
│       │                   ├── data/
│       │                   │   ├── DeviceRegistration.java
│       │                   │   └── messages/
│       │                   │       ├── ClientData.java
│       │                   │       ├── RegisterRequest.java
│       │                   │       ├── RegisterRequestData.java
│       │                   │       ├── RegisterResponse.java
│       │                   │       ├── RegisteredKey.java
│       │                   │       ├── SignRequest.java
│       │                   │       ├── SignRequestData.java
│       │                   │       ├── SignResponse.java
│       │                   │       ├── json/
│       │                   │       │   ├── JsonSerializable.java
│       │                   │       │   └── Persistable.java
│       │                   │       └── key/
│       │                   │           ├── RawRegisterResponse.java
│       │                   │           ├── RawSignResponse.java
│       │                   │           └── util/
│       │                   │               ├── ByteInputStream.java
│       │                   │               ├── CertificateParser.java
│       │                   │               └── U2fB64Encoding.java
│       │                   └── exceptions/
│       │                       ├── DeviceCompromisedException.java
│       │                       ├── InvalidDeviceCounterException.java
│       │                       ├── NoEligableDevicesException.java
│       │                       ├── NoEligibleDevicesException.java
│       │                       ├── U2fAuthenticationException.java
│       │                       ├── U2fBadConfigurationException.java
│       │                       ├── U2fBadInputException.java
│       │                       ├── U2fCeremonyException.java
│       │                       └── U2fRegistrationException.java
│       └── test/
│           ├── java/
│           │   └── com/
│           │       └── yubico/
│           │           └── u2f/
│           │               ├── AppIdTest.java
│           │               ├── SystemTest.java
│           │               ├── TestUtils.java
│           │               ├── U2FTest.java
│           │               ├── U2fPrimitivesTest.java
│           │               ├── codec/
│           │               │   ├── RawCodecTest.java
│           │               │   └── SerialCodecTest.java
│           │               ├── data/
│           │               │   ├── DeviceRegistrationTest.java
│           │               │   └── messages/
│           │               │       ├── ClientDataTest.java
│           │               │       ├── RegisterRequestDataTest.java
│           │               │       ├── RegisterRequestTest.java
│           │               │       ├── RegisterResponseTest.java
│           │               │       ├── SignRequestDataTest.java
│           │               │       ├── SignRequestTest.java
│           │               │       ├── SignResponseTest.java
│           │               │       ├── json/
│           │               │       │   └── JsonSerializableTest.java
│           │               │       └── key/
│           │               │           ├── Client.java
│           │               │           ├── CodecTestUtils.java
│           │               │           └── util/
│           │               │               ├── CertificateParserTest.java
│           │               │               └── U2fB64EncodingTest.java
│           │               ├── json/
│           │               │   └── SerializationTest.java
│           │               ├── softkey/
│           │               │   ├── SoftKey.java
│           │               │   ├── SoftKeyTest.java
│           │               │   └── messages/
│           │               │       ├── RegisterRequest.java
│           │               │       └── SignRequest.java
│           │               └── testdata/
│           │                   ├── AcmeKey.java
│           │                   ├── GnubbyKey.java
│           │                   └── TestVectors.java
│           └── resources/
│               └── com/
│                   └── yubico/
│                       └── u2f/
│                           └── testdata/
│                               ├── acme/
│                               │   └── attestation-certificate.der
│                               └── gnubby/
│                                   ├── attestation-certificate-private-key.hex
│                                   └── attestation-certificate.der
└── u2flib-server-demo/
    ├── README
    ├── build.gradle
    ├── config.yml
    ├── gradle/
    │   └── wrapper/
    │       ├── gradle-wrapper.jar
    │       └── gradle-wrapper.properties
    ├── gradlew
    ├── gradlew.bat
    ├── keystore.jks
    ├── pom.xml
    └── src/
        └── main/
            ├── java/
            │   └── demo/
            │       ├── App.java
            │       ├── Config.java
            │       ├── Resource.java
            │       ├── U2fDemoException.java
            │       └── view/
            │           ├── AuthenticationView.java
            │           ├── FinishAuthenticationView.java
            │           ├── FinishRegistrationView.java
            │           └── RegistrationView.java
            └── resources/
                ├── assets/
                │   ├── loginIndex.html
                │   ├── registerIndex.html
                │   └── u2f-api-1.1.js
                └── demo/
                    └── view/
                        ├── authenticate.ftl
                        ├── finishAuthentication.ftl
                        ├── finishRegistration.ftl
                        ├── navigation.ftl
                        └── register.ftl
Download .txt
SYMBOL INDEX (456 symbols across 83 files)

FILE: dev-util/example-registration.py
  function hextokeys (line 13) | def hextokeys(private_key_hex, public_key_hex):
  function make_signature_base (line 22) | def make_signature_base(application_parameter_hex, client_data_json, key...
  function sign (line 26) | def sign(private_key, message_hex):
  function make_challenge_parameter_hex (line 29) | def make_challenge_parameter_hex(client_data_json):
  function make_registration_request_message (line 32) | def make_registration_request_message(user_public_key_hex, key_handle_he...
  function sha256 (line 35) | def sha256(data):
  function byteStringToDecimalBytes (line 40) | def byteStringToDecimalBytes(data):
  function byteStringToDecimalSignedBytes (line 43) | def byteStringToDecimalSignedBytes(data):
  function print_results (line 91) | def print_results(private_user_key_hex, public_user_key_hex, private_att...

FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/Attestation.java
  class Attestation (line 19) | @Deprecated
    method Attestation (line 27) | private Attestation() {
    method Attestation (line 34) | public Attestation(String metadataIdentifier, Map<String, String> vend...
    method isTrusted (line 41) | public boolean isTrusted() {

FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/DeviceMatcher.java
  type DeviceMatcher (line 13) | @Deprecated
    method matches (line 15) | public boolean matches(X509Certificate attestationCertificate, JsonNod...

FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/MetadataObject.java
  class MetadataObject (line 25) | @Deprecated
    method MetadataObject (line 44) | @JsonCreator
    method toJson (line 63) | @Override
    method getIdentifier (line 68) | public String getIdentifier() {
    method getVersion (line 72) | public long getVersion() {
    method getVendorInfo (line 76) | public Map<String, String> getVendorInfo() {
    method getTrustedCertificates (line 80) | public List<String> getTrustedCertificates() {
    method getDevices (line 84) | public List<JsonNode> getDevices() {
    method parseFromJson (line 88) | public static List<MetadataObject> parseFromJson(String jsonData) thro...
    method fromJson (line 106) | public static MetadataObject fromJson(String json) throws U2fBadInputE...

FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/MetadataResolver.java
  type MetadataResolver (line 11) | @Deprecated
    method resolve (line 13) | MetadataObject resolve(X509Certificate attestationCertificate);

FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/MetadataService.java
  class MetadataService (line 36) | @Deprecated
    method createDefaultMetadataResolver (line 52) | private static MetadataResolver createDefaultMetadataResolver() {
    method MetadataService (line 75) | public MetadataService(MetadataResolver resolver, Cache<String, Attest...
    method MetadataService (line 84) | public MetadataService() {
    method MetadataService (line 88) | public MetadataService(MetadataResolver resolver) {
    method MetadataService (line 92) | public MetadataService(MetadataResolver resolver, Map<String, ? extend...
    method MetadataService (line 96) | public MetadataService(MetadataResolver resolver, Cache<String, Attest...
    method registerDeviceMatcher (line 100) | public void registerDeviceMatcher(String matcherType, DeviceMatcher ma...
    method deviceMatches (line 104) | private boolean deviceMatches(JsonNode selectors, X509Certificate atte...
    method getCachedAttestation (line 117) | public Attestation getCachedAttestation(String attestationCertificateF...
    method getAttestation (line 121) | public Attestation getAttestation(final X509Certificate attestationCer...
    method lookupAttestation (line 138) | private Attestation lookupAttestation(X509Certificate attestationCerti...
    method get_transports (line 171) | private int get_transports(byte[] extensionValue) {

FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/Transport.java
  type Transport (line 13) | @Deprecated
    method Transport (line 22) | Transport(int bitpos) {
    method fromInt (line 26) | public static Set<Transport> fromInt(int bits) {
    method toInt (line 37) | public static int toInt(Iterable<Transport> transports) {
    method toInt (line 45) | public static int toInt(Transport...transports) {

FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/matchers/ExtensionMatcher.java
  class ExtensionMatcher (line 16) | @Deprecated
    method matches (line 23) | @Override

FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/matchers/FingerprintMatcher.java
  class FingerprintMatcher (line 14) | @Deprecated
    method matches (line 20) | @Override

FILE: u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/resolvers/SimpleResolver.java
  class SimpleResolver (line 27) | @Deprecated
    method addMetadata (line 34) | public void addMetadata(String jsonData) throws CertificateException, ...
    method addMetadata (line 40) | public void addMetadata(MetadataObject object) throws CertificateExcep...
    method resolve (line 48) | @Override

FILE: u2flib-server-attestation/src/test/java/com/yubico/u2f/attestation/MetadataObjectTest.java
  class MetadataObjectTest (line 10) | public class MetadataObjectTest {
    method testToAndFromJson (line 13) | @Test
    method testParseFromJson (line 30) | @Test

FILE: u2flib-server-attestation/src/test/java/com/yubico/u2f/attestation/MetadataServiceTest.java
  class MetadataServiceTest (line 23) | public class MetadataServiceTest {
    method testGetAttestation_x509extension_key (line 28) | @Test
    method testGetAttestation_x509extension_key_value (line 40) | @Test
    method testGetTransportsFromCertificate (line 52) | @Test
    method testGetTransportsFromMetadata (line 62) | @Test
    method getCachedAttestationReturnsCertIfPresent (line 72) | @Test
    method getAttestationReturnsUnknownIfFingerprintEncodingFails (line 90) | @Test
    method deviceMatchesReturnsTrueIfNoSelectorsAreGiven (line 102) | @Test

FILE: u2flib-server-attestation/src/test/java/com/yubico/u2f/attestation/TransportTest.java
  class TransportTest (line 12) | public class TransportTest {
    method testParsingSingleValuesFromInt (line 14) | @Test
    method testParsingSetsFromInt (line 22) | @Test
    method testEncodingSingleValuesToInt (line 31) | @Test
    method testEncodingSetsToInt (line 39) | @Test

FILE: u2flib-server-attestation/src/test/java/com/yubico/u2f/attestation/matchers/FingerprintMatcherTest.java
  class FingerprintMatcherTest (line 19) | public class FingerprintMatcherTest {
    method matchesIsFalseForNonArrayFingerprints (line 23) | @Test
    method matchesIsFalseIfNoFingerprintMatches (line 31) | @Test
    method matchesIsTrueIfSomeFingerprintMatches (line 46) | @Test

FILE: u2flib-server-attestation/src/test/java/com/yubico/u2f/attestation/resolvers/SimpleResolverTest.java
  class SimpleResolverTest (line 23) | public class SimpleResolverTest {
    method testResolve (line 28) | @Test
    method resolveReturnsNullOnUntrustedSignature (line 41) | @Test

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/AppId.java
  class AppId (line 14) | @Deprecated
    method checkIsValid (line 25) | public static void checkIsValid(String appId) throws U2fBadConfigurati...
    method checkPathIsNotSlash (line 39) | private static void checkPathIsNotSlash(URI url) throws U2fBadConfigur...
    method checkValidUrl (line 45) | private static URI checkValidUrl(String appId) throws U2fBadConfigurat...
    method checkNotIpAddress (line 55) | private static void checkNotIpAddress(URI url) throws U2fBadConfigurat...

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/U2F.java
  class U2F (line 27) | @Deprecated
    method U2F (line 36) | public U2F() {
    method withoutAppIdValidation (line 40) | public static U2F withoutAppIdValidation() {
    method U2F (line 44) | private U2F(boolean validateAppId) {
    method startRegistration (line 58) | public RegisterRequestData startRegistration(String appId, Iterable<? ...
    method startSignature (line 65) | public SignRequestData startSignature(String appId, Iterable<? extends...
    method finishRegistration (line 75) | public DeviceRegistration finishRegistration(RegisterRequestData regis...
    method finishRegistration (line 89) | public DeviceRegistration finishRegistration(RegisterRequestData regis...
    method finishSignature (line 96) | public DeviceRegistration finishSignature(SignRequestData signRequestD...
    method finishSignature (line 113) | public DeviceRegistration finishSignature(SignRequestData signRequestD...

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/U2fPrimitives.java
  class U2fPrimitives (line 36) | @Deprecated
    method U2fPrimitives (line 46) | public U2fPrimitives(Crypto crypto, ChallengeGenerator challengeGenera...
    method U2fPrimitives (line 51) | public U2fPrimitives() {
    method startRegistration (line 58) | public RegisterRequest startRegistration(String appId) {
    method startRegistration (line 71) | public RegisterRequest startRegistration(String appId, byte[] challeng...
    method finishRegistration (line 78) | public DeviceRegistration finishRegistration(RegisterRequest registerR...
    method finishRegistration (line 90) | public DeviceRegistration finishRegistration(RegisterRequest registerR...
    method startSignature (line 110) | public SignRequest startSignature(String appId, DeviceRegistration dev...
    method startSignature (line 124) | public SignRequest startSignature(String appId, DeviceRegistration dev...
    method finishSignature (line 137) | public void finishSignature(SignRequest signRequest,
    method finishSignature (line 149) | public void finishSignature(SignRequest signRequest,

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/crypto/BouncyCastleCrypto.java
  class BouncyCastleCrypto (line 28) | @Deprecated
    method getProvider (line 33) | public Provider getProvider() {
    method checkSignature (line 37) | @Override
    method checkSignature (line 43) | @Override
    method decodePublicKey (line 71) | @Override
    method hash (line 100) | @Override
    method hash (line 109) | @Override

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/crypto/ChallengeGenerator.java
  type ChallengeGenerator (line 16) | @Deprecated
    method generateChallenge (line 19) | byte[] generateChallenge();

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/crypto/Crypto.java
  type Crypto (line 21) | @Deprecated
    method checkSignature (line 23) | void checkSignature(X509Certificate attestationCertificate, byte[] sig...
    method checkSignature (line 26) | void checkSignature(PublicKey publicKey, byte[] signedBytes,
    method decodePublicKey (line 29) | PublicKey decodePublicKey(byte[] encodedPublicKey) throws U2fBadInputE...
    method hash (line 31) | byte[] hash(byte[] bytes);
    method hash (line 33) | byte[] hash(String str);

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/crypto/RandomChallengeGenerator.java
  class RandomChallengeGenerator (line 18) | @Deprecated
    method generateChallenge (line 23) | @Override

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/DeviceRegistration.java
  class DeviceRegistration (line 32) | @Deprecated
    method DeviceRegistration (line 49) | @JsonCreator
    method DeviceRegistration (line 58) | public DeviceRegistration(String keyHandle, String publicKey, X509Cert...
    method getKeyHandle (line 70) | public String getKeyHandle() {
    method getPublicKey (line 74) | public String getPublicKey() {
    method getAttestationCertificate (line 78) | @JsonIgnore
    method getCounter (line 87) | public long getCounter() {
    method isCompromised (line 91) | public boolean isCompromised() {
    method markCompromised (line 95) | public void markCompromised() {
    method toString (line 99) | @Override
    method fromJson (line 118) | public static DeviceRegistration fromJson(String json) throws U2fBadIn...
    method toJson (line 122) | @Override
    method toJsonWithAttestationCert (line 131) | public String toJsonWithAttestationCert() {
    method checkAndUpdateCounter (line 135) | public void checkAndUpdateCounter(long clientCounter) throws InvalidDe...
    class DeviceWithoutCertificate (line 143) | private static class DeviceWithoutCertificate {
      method DeviceWithoutCertificate (line 153) | private DeviceWithoutCertificate(String keyHandle, String publicKey,...

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/ClientData.java
  class ClientData (line 19) | @Deprecated
    method asJson (line 31) | public String asJson() {
    method ClientData (line 35) | public ClientData(String clientData) throws U2fBadInputException {
    method toString (line 47) | @Override
    method getChallenge (line 52) | public String getChallenge() {
    method getString (line 56) | private static String getString(JsonNode data, String key) throws U2fB...
    method checkContent (line 67) | public void checkContent(String type, String challenge, Optional<Set<S...
    method verifyOrigin (line 86) | private static void verifyOrigin(String origin, Set<String> allowedOri...
    method canonicalizeOrigins (line 93) | public static Set<String> canonicalizeOrigins(Set<String> origins) {
    method canonicalizeOrigin (line 101) | public static String canonicalizeOrigin(String url) {

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/RegisterRequest.java
  class RegisterRequest (line 27) | @Deprecated
    method RegisterRequest (line 55) | public RegisterRequest(String challenge, String appId) {
    method getRequestId (line 59) | @Override
    method fromJson (line 64) | public static RegisterRequest fromJson(String json) throws U2fBadInput...
    class RegisterRequestBuilder (line 68) | @JsonPOJOBuilder(withPrefix = "")

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/RegisterRequestData.java
  class RegisterRequestData (line 19) | @Deprecated
    method RegisterRequestData (line 32) | public RegisterRequestData(@JsonProperty("appId") String appId, @JsonP...
    method RegisterRequestData (line 38) | public RegisterRequestData(String appId, Iterable<? extends DeviceRegi...
    method getRegisteredKeys (line 52) | public List<RegisteredKey> getRegisteredKeys() {
    method getRegisterRequests (line 56) | public List<RegisterRequest> getRegisterRequests() {
    method getRegisterRequest (line 60) | public RegisterRequest getRegisterRequest(RegisterResponse response) {
    method getRequestId (line 64) | public String getRequestId() {
    method fromJson (line 68) | public static RegisterRequestData fromJson(String json) throws U2fBadI...

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/RegisterResponse.java
  class RegisterResponse (line 31) | @Deprecated
    method RegisterResponse (line 51) | @JsonCreator
    method getRegistrationData (line 58) | public String getRegistrationData() {
    method getClientData (line 62) | @JsonIgnore
    method getRequestId (line 67) | public String getRequestId() {
    method fromJson (line 71) | public static RegisterResponse fromJson(String json) throws U2fBadInpu...
    method writeObject (line 76) | private void writeObject(ObjectOutputStream out) throws IOException {
    method readObject (line 80) | private void readObject(ObjectInputStream in) throws IOException, Clas...

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/RegisteredKey.java
  class RegisteredKey (line 20) | @Deprecated
    method RegisteredKey (line 46) | public RegisteredKey(String keyHandle) {
    class RegisteredKeyBuilder (line 50) | @JsonPOJOBuilder(withPrefix = "")

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/SignRequest.java
  class SignRequest (line 27) | @Deprecated
    method getRequestId (line 64) | public String getRequestId() {
    method fromJson (line 68) | public static SignRequest fromJson(String json) throws U2fBadInputExce...
    class SignRequestBuilder (line 72) | @JsonPOJOBuilder(withPrefix = "")

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/SignRequestData.java
  class SignRequestData (line 25) | @Deprecated
    method SignRequestData (line 43) | @JsonCreator
    method SignRequestData (line 50) | public SignRequestData(String appId, Iterable<? extends DeviceRegistra...
    method getSignRequests (line 73) | public List<SignRequest> getSignRequests() {
    method getSignRequest (line 77) | public SignRequest getSignRequest(SignResponse response) throws U2fBad...
    method getRequestId (line 88) | public String getRequestId() {
    method fromJson (line 92) | public static SignRequestData fromJson(String json) throws U2fBadInput...

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/SignResponse.java
  class SignResponse (line 31) | @Deprecated
    method SignResponse (line 52) | @JsonCreator
    method getClientData (line 60) | @JsonIgnore
    method getSignatureData (line 65) | public String getSignatureData() {
    method getKeyHandle (line 69) | public String getKeyHandle() {
    method getRequestId (line 73) | public String getRequestId() {
    method fromJson (line 77) | public static SignResponse fromJson(String json) throws U2fBadInputExc...
    method writeObject (line 82) | private void writeObject(ObjectOutputStream out) throws IOException {
    method readObject (line 86) | private void readObject(ObjectInputStream in) throws IOException, Clas...

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/json/JsonSerializable.java
  class JsonSerializable (line 15) | @Deprecated
    method toJson (line 19) | @JsonIgnore
    method toString (line 28) | @Override
    method fromJson (line 33) | public static <T extends JsonSerializable> T fromJson(String json, Cla...

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/json/Persistable.java
  type Persistable (line 11) | @Deprecated
    method getRequestId (line 13) | @JsonIgnore
    method toJson (line 16) | public String toJson();

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/key/RawRegisterResponse.java
  class RawRegisterResponse (line 33) | @Deprecated
    method RawRegisterResponse (line 58) | public RawRegisterResponse(byte[] userPublicKey,
    method RawRegisterResponse (line 65) | public RawRegisterResponse(byte[] userPublicKey,
    method fromBase64 (line 77) | public static RawRegisterResponse fromBase64(String rawDataBase64, Cry...
    method checkSignature (line 102) | public void checkSignature(String appId, String clientData) throws U2f...
    method packBytesToSign (line 107) | public static byte[] packBytesToSign(byte[] appIdHash, byte[] clientDa...
    method createDevice (line 117) | public DeviceRegistration createDevice() throws U2fBadInputException {

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/key/RawSignResponse.java
  class RawSignResponse (line 30) | @Deprecated
    method RawSignResponse (line 40) | public RawSignResponse(byte userPresence, long counter, byte[] signatu...
    method RawSignResponse (line 44) | public RawSignResponse(byte userPresence, long counter, byte[] signatu...
    method fromBase64 (line 51) | public static RawSignResponse fromBase64(String rawDataBase64, Crypto ...
    method checkSignature (line 65) | public void checkSignature(String appId, String clientData, byte[] pub...
    method packBytesToSign (line 79) | public static byte[] packBytesToSign(byte[] appIdHash, byte userPresen...
    method getUserPresence (line 93) | public byte getUserPresence() {
    method getCounter (line 101) | public long getCounter() {
    method getSignature (line 108) | public byte[] getSignature() {
    method checkUserPresence (line 112) | public void checkUserPresence() throws U2fBadInputException {

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/key/util/ByteInputStream.java
  class ByteInputStream (line 20) | @Deprecated
    method ByteInputStream (line 23) | public ByteInputStream(byte[] data) {
    method read (line 27) | public byte[] read(int numberOfBytes) throws IOException {
    method readAll (line 33) | public byte[] readAll() throws IOException {
    method readInteger (line 39) | public int readInteger() throws IOException {
    method readSigned (line 43) | public byte readSigned() throws IOException {
    method readUnsigned (line 47) | public int readUnsigned() throws IOException {

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/key/util/CertificateParser.java
  class CertificateParser (line 21) | @Deprecated
    method parsePem (line 35) | public static X509Certificate parsePem(String pemEncodedCert) throws C...
    method parseDer (line 39) | public static X509Certificate parseDer(String base64DerEncodedCert) th...
    method parseDer (line 43) | public static X509Certificate parseDer(byte[] derEncodedCert) throws C...
    method parseDer (line 47) | public static X509Certificate parseDer(InputStream is) throws Certific...

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/key/util/U2fB64Encoding.java
  class U2fB64Encoding (line 10) | @Deprecated
    method encode (line 15) | public static String encode(byte[] decoded) {
    method decode (line 19) | public static byte[] decode(String encoded) throws U2fBadInputException {

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/DeviceCompromisedException.java
  class DeviceCompromisedException (line 10) | @Deprecated
    method DeviceCompromisedException (line 15) | public DeviceCompromisedException(DeviceRegistration deviceRegistratio...
    method DeviceCompromisedException (line 20) | public DeviceCompromisedException(DeviceRegistration deviceRegistratio...

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/InvalidDeviceCounterException.java
  class InvalidDeviceCounterException (line 9) | @Deprecated
    method InvalidDeviceCounterException (line 11) | public InvalidDeviceCounterException(DeviceRegistration registration) {

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/NoEligableDevicesException.java
  class NoEligableDevicesException (line 12) | @Deprecated
    method NoEligableDevicesException (line 17) | public NoEligableDevicesException(Iterable<? extends DeviceRegistratio...
    method NoEligableDevicesException (line 22) | public NoEligableDevicesException(Iterable<? extends DeviceRegistratio...
    method hasDevices (line 27) | public boolean hasDevices() {

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/NoEligibleDevicesException.java
  class NoEligibleDevicesException (line 9) | @Deprecated
    method NoEligibleDevicesException (line 13) | public NoEligibleDevicesException(Iterable<? extends DeviceRegistratio...
    method NoEligibleDevicesException (line 17) | public NoEligibleDevicesException(Iterable<? extends DeviceRegistratio...

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/U2fAuthenticationException.java
  class U2fAuthenticationException (line 9) | @Deprecated
    method U2fAuthenticationException (line 11) | public U2fAuthenticationException(String message, Throwable cause) {
    method U2fAuthenticationException (line 15) | public U2fAuthenticationException(String message) {

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/U2fBadConfigurationException.java
  class U2fBadConfigurationException (line 7) | @Deprecated
    method U2fBadConfigurationException (line 9) | public U2fBadConfigurationException(String message) {
    method U2fBadConfigurationException (line 13) | public U2fBadConfigurationException(String message, Throwable cause) {

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/U2fBadInputException.java
  class U2fBadInputException (line 16) | @Deprecated
    method U2fBadInputException (line 20) | public U2fBadInputException(String message) {
    method U2fBadInputException (line 24) | public U2fBadInputException(String message, Throwable cause) {

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/U2fCeremonyException.java
  class U2fCeremonyException (line 9) | @Deprecated
    method U2fCeremonyException (line 11) | public U2fCeremonyException(String message, Throwable cause) {
    method U2fCeremonyException (line 15) | public U2fCeremonyException(String message) {

FILE: u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/U2fRegistrationException.java
  class U2fRegistrationException (line 9) | @Deprecated
    method U2fRegistrationException (line 11) | public U2fRegistrationException(String message, Throwable cause) {
    method U2fRegistrationException (line 15) | public U2fRegistrationException(String message) {

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/AppIdTest.java
  class AppIdTest (line 9) | public class AppIdTest {
    method validUrls (line 11) | @Test
    method validUris (line 19) | @Test
    method disallowHttp (line 25) | @Test
    method disallowSlashAsPath (line 30) | @Test
    method disallowIP (line 35) | @Test
    method badSyntax (line 44) | @Test
    method isValid (line 49) | private static boolean isValid(String appId) {

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/SystemTest.java
  class SystemTest (line 13) | @Ignore("Includes manual steps")
    method main (line 27) | public static void main(String... args) throws Exception {

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/TestUtils.java
  class TestUtils (line 31) | public class TestUtils {
    method fetchCertificate (line 40) | public static X509Certificate fetchCertificate(InputStream resourceAsS...
    method parseCertificate (line 46) | public static X509Certificate parseCertificate(byte[] encodedDerCertif...
    method parsePrivateKey (line 54) | public static PrivateKey parsePrivateKey(InputStream is) {
    method parsePrivateKey (line 59) | public static PrivateKey parsePrivateKey(String keyBytesHex) {
    method parsePublicKey (line 76) | public static PublicKey parsePublicKey(byte[] keyBytes) {
    method serialize (line 91) | public static byte[] serialize(Object o) throws IOException {
    method deserialize (line 99) | public static <T> T deserialize(byte[] serialized) throws IOException,...
    method clone (line 107) | public static <T> T clone(T input) throws IOException, ClassNotFoundEx...

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/U2FTest.java
  class U2FTest (line 31) | public class U2FTest {
    method startRegistration_compromisedDevice (line 37) | @Test
    method startSignature_compromisedDevices (line 44) | @Test(expected = NoEligibleDevicesException.class)
    method defaultConstructedU2FstartRegistrationShouldRefuseInvalidAppId (line 51) | @Test(expected = U2fBadConfigurationException.class)
    method startRegistrationShouldReturnARandomChallenge (line 60) | @Test
    method defaultConstructedU2FstartSignatureShouldRefuseInvalidAppId (line 75) | @Test(expected = U2fBadConfigurationException.class)
    method startSignatureShouldReturnARandomChallenge (line 84) | @Test
    method finishSignature_compromisedDevice (line 99) | @Test(expected = DeviceCompromisedException.class)
    method finishSignature_invalidFacet (line 119) | @Test
    method finishRegistrationShouldReturnAMatchedDevice (line 141) | @Test
    method finishSignatureShouldReturnAMatchedDevice (line 166) | @Test

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/U2fPrimitivesTest.java
  class U2fPrimitivesTest (line 37) | public class U2fPrimitivesTest {
    method setup (line 44) | @Before
    method finishRegistration (line 49) | @Test
    method finishRegistration2 (line 57) | @Test
    method finishRegistrationWithoutAllowedAppIds (line 67) | @Test
    method finishRegistrationShouldDetectIncorrectAppId (line 82) | @Test
    method finishRegistrationShouldDetectIncorrectChallenge (line 99) | @Test
    method finishRegistrationShouldDetectIncorrectClientDataType (line 118) | @Test
    method finishRegistrationShouldDetectIncorrectClientDataOrigin (line 137) | @Test
    method finishSignature (line 156) | @Test
    method finishSignature_badOrigin (line 171) | @Test(expected = U2fAuthenticationException.class)
    method finishAuthentication_badBase64 (line 186) | @Test(expected = U2fBadInputException.class)
    method finishAuthentication_clientDataMissingField (line 199) | @Test(expected = U2fBadInputException.class)
    method finishAuthentication_truncatedData (line 212) | @Test
    method startSignature_compromisedDevice (line 227) | @Test(expected = IllegalArgumentException.class)
    method finishSignature_compromisedDevice (line 236) | @Test(expected = IllegalArgumentException.class)
    method finishSignatureShouldDetectInvalidUserPresence (line 253) | @Test
    method finishSignatureShouldDetectIncorrectDeviceRegistration (line 284) | @Test(expected = IllegalArgumentException.class)

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/codec/RawCodecTest.java
  class RawCodecTest (line 26) | public class RawCodecTest {
    method testEncodeRegisterResponse (line 30) | @Test
    method testEncodeRegisterSignedBytes (line 38) | @Test
    method testDecodeRegisterResponse (line 45) | @Test
    method testEncodeSignResponse (line 54) | @Test
    method testDecodeSignResponse (line 64) | @Test
    method testEncodeSignedBytes (line 73) | @Test

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/codec/SerialCodecTest.java
  class SerialCodecTest (line 25) | public class SerialCodecTest {
    method testEncodeRegisterResponse (line 29) | @Test
    method testEncodeRegisterSignedBytes (line 39) | @Test
    method testDecodeRegisterResponse (line 47) | @Test
    method testEncodeSignResponse (line 56) | @Test
    method testDecodeSignResponse (line 66) | @Test
    method testEncodeSignedBytes (line 75) | @Test

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/data/DeviceRegistrationTest.java
  class DeviceRegistrationTest (line 19) | public class DeviceRegistrationTest {
    method shouldSerialize (line 21) | @Test
    method shouldSerializeWithAttestationCertificate (line 34) | @Test
    method serializationRoundTripWithJackson (line 44) | @Test
    method shouldAcceptValidCounters (line 57) | @Test
    method shouldDetectInvalidCounters (line 68) | @Test
    method equalsAndHashCodeIgnoreCounter (line 82) | @Test
    method equalsAndHashCodeIgnoreCompromisedFlag (line 91) | @Test
    method equalsAndHashCodeDoNotIgnoreKeyHandle (line 100) | @Test
    method equalsAndHashCodeDoNotIgnorePublicKey (line 109) | @Test
    method equalsAndHashCodeDoNotIgnoreAttestationCert (line 118) | @Test
    method toStringDoesNotReturnNull (line 127) | @Test
    method getDeviceRegistration (line 132) | private DeviceRegistration getDeviceRegistration() throws Exception {

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/ClientDataTest.java
  class ClientDataTest (line 14) | public class ClientDataTest {
    method shouldCanonicalizeOrigin (line 16) | @Test
    method shouldCheckContent (line 29) | @Test

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/RegisterRequestDataTest.java
  class RegisterRequestDataTest (line 21) | public class RegisterRequestDataTest {
    method testGetters (line 25) | @Test
    method testToAndFromJson (line 47) | @Test
    method testJavaSerializer (line 59) | @Test
    method mockDevice (line 68) | private DeviceRegistration mockDevice(final String keyHandle, boolean ...
    method testConstructorAddsOneRegisteredKeyForEachGivenNonCompromisedDeviceRegistration (line 75) | @Test

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/RegisterRequestTest.java
  class RegisterRequestTest (line 12) | public class RegisterRequestTest {
    method testGetters (line 16) | @Test
    method testToAndFromJson (line 24) | @Test
    method testJavaSerializer (line 36) | @Test

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/RegisterResponseTest.java
  class RegisterResponseTest (line 13) | public class RegisterResponseTest {
    method testGetters (line 16) | @Test
    method testToAndFromJson (line 25) | @Test
    method testJavaSerializer (line 36) | @Test
    method fromJsonDetectsTooLongJsonContent (line 46) | @Test(expected = IllegalArgumentException.class)
    method fromJsonAllowsShortJsonContent (line 52) | @Test
    method makeLongJson (line 57) | private String makeLongJson(int totalLength) {

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/SignRequestDataTest.java
  class SignRequestDataTest (line 23) | public class SignRequestDataTest {
    method testGetters (line 26) | @Test
    method testToAndFromJson (line 44) | @Test
    method testJavaSerializer (line 55) | @Test
    method getSignRequestChecksResponseId (line 64) | @Test(expected = IllegalArgumentException.class)
    method testFailureModesAreIdentifiable (line 75) | @Test

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/SignRequestTest.java
  class SignRequestTest (line 10) | public class SignRequestTest {
    method testGetters (line 14) | @Test
    method testToAndFromJson (line 23) | @Test
    method testJavaSerializer (line 34) | @Test

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/SignResponseTest.java
  class SignResponseTest (line 13) | public class SignResponseTest {
    method testGetters (line 16) | @Test
    method testToAndFromJson (line 24) | @Test
    method testJavaSerializer (line 35) | @Test
    method fromJsonDetectsTooLongJsonContent (line 44) | @Test(expected = IllegalArgumentException.class)
    method fromJsonAllowsShortJsonContent (line 50) | @Test
    method makeLongJson (line 55) | private String makeLongJson(int totalLength) {

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/json/JsonSerializableTest.java
  class JsonSerializableTest (line 8) | public class JsonSerializableTest {
    class Thing (line 10) | private static class Thing extends JsonSerializable {
      method Thing (line 12) | private Thing(@JsonProperty("foo") String foo) {
    method toStringReturnsJson (line 17) | @Test

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/key/Client.java
  class Client (line 24) | public class Client {
    method Client (line 34) | public Client(SoftKey key) {
    method encodeRegisterResponse (line 38) | public static byte[] encodeRegisterResponse(RawRegisterResponse rawReg...
    method encodeTokenRegistrationResponse (line 68) | public static RegisterResponse encodeTokenRegistrationResponse(String ...
    method register (line 75) | public DeviceRegistration register() throws Exception {
    method sign (line 95) | public SignResponse sign(DeviceRegistration registeredDevice, SignRequ...

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/key/CodecTestUtils.java
  class CodecTestUtils (line 18) | public class CodecTestUtils {
    method encodeSignResponse (line 19) | public static byte[] encodeSignResponse(RawSignResponse rawSignRespons...
    method encodeRegisterResponse (line 27) | public static byte[] encodeRegisterResponse(RawRegisterResponse rawReg...

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/key/util/CertificateParserTest.java
  class CertificateParserTest (line 8) | public class CertificateParserTest {
    method parsePemDoesNotReturnNull (line 13) | @Test

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/key/util/U2fB64EncodingTest.java
  class U2fB64EncodingTest (line 9) | public class U2fB64EncodingTest {
    method encodeTest (line 10) | @Test
    method decodeTest (line 19) | @Test
    method decodeBadAlphabetTest (line 35) | @Test(expected = U2fBadInputException.class)
    method decodeBadPaddingTest (line 40) | @Test(expected = U2fBadInputException.class)

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/json/SerializationTest.java
  class SerializationTest (line 9) | public class SerializationTest {
    method tokenSignResponse (line 11) | @Test

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/softkey/SoftKey.java
  class SoftKey (line 26) | public final class SoftKey implements Cloneable {
    method SoftKey (line 33) | public SoftKey() {
    method SoftKey (line 42) | public SoftKey(
    method clone (line 54) | @Override
    method register (line 64) | public RawRegisterResponse register(RegisterRequest registerRequest) t...
    method stripMetaData (line 90) | private byte[] stripMetaData(byte[] a) {
    method sign (line 103) | public RawSignResponse sign(SignRequest signRequest) throws Exception {
    method sign (line 119) | private byte[] sign(byte[] signedData, PrivateKey privateKey) throws E...

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/softkey/SoftKeyTest.java
  class SoftKeyTest (line 25) | public class SoftKeyTest {
    method setup (line 34) | @Before
    method shouldRegister (line 39) | @Test
    method shouldSign (line 45) | @Test
    method shouldProvideAttestationCert (line 53) | @Test
    method shouldVerifyAttestationCert (line 60) | @Test
    method shouldProtectAgainstClonedDevices (line 74) | @Test(expected = InvalidDeviceCounterException.class)
    method shouldVerifyChallenge (line 88) | @Test
    method tamperChallenge (line 106) | private String tamperChallenge(ClientData clientData) {
    method shouldVerifySignature (line 112) | @Test
    method shouldThrowSeparateExceptionForMalformedSignature (line 131) | @Test(expected = RuntimeException.class)
    method makeSignatureMalformed (line 148) | private String makeSignatureMalformed(String signature) {
    method tamperSignature (line 152) | private String tamperSignature(String signature) {
    method createClient (line 156) | private Client createClient() {
    method signUsing (line 160) | private void signUsing(Client client, DeviceRegistration registeredDev...

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/softkey/messages/RegisterRequest.java
  class RegisterRequest (line 3) | public class RegisterRequest {
    method RegisterRequest (line 7) | public RegisterRequest(byte[] applicationSha256, byte[] challengeSha25...
    method getChallengeSha256 (line 19) | public byte[] getChallengeSha256() {
    method getApplicationSha256 (line 27) | public byte[] getApplicationSha256() {

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/softkey/messages/SignRequest.java
  class SignRequest (line 3) | public class SignRequest {
    method SignRequest (line 10) | public SignRequest(byte control, byte[] challengeSha256, byte[] applic...
    method getControl (line 23) | public byte getControl() {
    method getChallengeSha256 (line 34) | public byte[] getChallengeSha256() {
    method getApplicationSha256 (line 42) | public byte[] getApplicationSha256() {
    method getKeyHandle (line 49) | public byte[] getKeyHandle() {

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/testdata/AcmeKey.java
  class AcmeKey (line 10) | public class AcmeKey {

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/testdata/GnubbyKey.java
  class GnubbyKey (line 9) | public class GnubbyKey {

FILE: u2flib-server-core/src/test/java/com/yubico/u2f/testdata/TestVectors.java
  class TestVectors (line 20) | final public class TestVectors {

FILE: u2flib-server-demo/src/main/java/demo/App.java
  class App (line 9) | public class App extends Application<Config> {
    method initialize (line 10) | @Override
    method run (line 16) | @Override
    method main (line 21) | public static void main(String... args) throws Exception {

FILE: u2flib-server-demo/src/main/java/demo/Config.java
  class Config (line 5) | public class Config extends Configuration {

FILE: u2flib-server-demo/src/main/java/demo/Resource.java
  class Resource (line 41) | @Path("/")
    method load (line 49) | @Override
    method startRegistration (line 57) | @Path("startRegistration")
    method finishRegistration (line 65) | @Path("finishRegistration")
    method startAuthentication (line 79) | @Path("startAuthentication")
    method finishAuthentication (line 91) | @Path("finishAuthentication")
    method getRegistrations (line 111) | private Iterable<DeviceRegistration> getRegistrations(String username)...
    method addRegistration (line 119) | private void addRegistration(String username, DeviceRegistration regis...

FILE: u2flib-server-demo/src/main/java/demo/U2fDemoException.java
  class U2fDemoException (line 6) | public class U2fDemoException extends WebApplicationException {
    method U2fDemoException (line 7) | public U2fDemoException() {
    method U2fDemoException (line 11) | public U2fDemoException(String message) {

FILE: u2flib-server-demo/src/main/java/demo/view/AuthenticationView.java
  class AuthenticationView (line 8) | public class AuthenticationView extends View {
    method getData (line 13) | public SignRequestData getData() {
    method getDataJson (line 17) | public String getDataJson() {
    method getUsername (line 21) | public String getUsername() {
    method AuthenticationView (line 25) | public AuthenticationView(SignRequestData data, String username) {

FILE: u2flib-server-demo/src/main/java/demo/view/FinishAuthenticationView.java
  class FinishAuthenticationView (line 8) | @Getter
    method FinishAuthenticationView (line 14) | public FinishAuthenticationView(boolean success, List<String> messages) {
    method FinishAuthenticationView (line 20) | public FinishAuthenticationView(boolean success, String message) {
    method FinishAuthenticationView (line 24) | public FinishAuthenticationView(boolean success) {

FILE: u2flib-server-demo/src/main/java/demo/view/FinishRegistrationView.java
  class FinishRegistrationView (line 8) | @Getter
    method FinishRegistrationView (line 14) | public FinishRegistrationView(Attestation attestation, DeviceRegistrat...

FILE: u2flib-server-demo/src/main/java/demo/view/RegistrationView.java
  class RegistrationView (line 7) | public class RegistrationView extends View {
    method getUsername (line 12) | public String getUsername() {
    method getData (line 16) | public String getData() {
    method RegistrationView (line 20) | public RegistrationView(String data, String username) {
Condensed preview — 129 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (346K chars).
[
  {
    "path": ".gitattributes",
    "chars": 152,
    "preview": "# Auto-detect text files\n* text=auto\n\n# Always treat these as LF\ngradlew text eol=lf\n*.sh text eol=lf\n\n# Always treat th"
  },
  {
    "path": ".github/workflows/scan.yml",
    "chars": 946,
    "preview": "name: static code analysis\n# Documentation: https://github.com/Yubico/yes-static-code-analysis\n\non:\n  push:\n  schedule:\n"
  },
  {
    "path": ".gitignore",
    "chars": 170,
    "preview": "# Eclipse\n.classpath\n.project\n.settings/\n\n# Intellij\n.idea/\nout/\n*.iml\n*.iws\n\n# Mac\n.DS_Store\n\n# Maven\nlog/\ntarget/\n*.ve"
  },
  {
    "path": ".travis.yml",
    "chars": 166,
    "preview": "language: java\njdk:\n  - openjdk8\nafter_success:\n  - ./gradlew coveralls\n\naddons:\n  hosts:\n    - travis-issue-5227-workar"
  },
  {
    "path": "COPYING",
    "chars": 2772,
    "preview": "Copyright (c) 2014, Yubico AB\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without m"
  },
  {
    "path": "NEWS",
    "chars": 5021,
    "preview": "== Version 0.19.12 ==\n\n* Deprecated all classes with note that the library is obsolete. This is planned\n  to be the fina"
  },
  {
    "path": "README",
    "chars": 3527,
    "preview": "== java-u2flib-server\n\nNOTE: _OBSOLETE: This project is no longer maintained.\nU2F has been superseded by https://www.w3."
  },
  {
    "path": "buildSrc/build.gradle",
    "chars": 188,
    "preview": "apply plugin: 'groovy'\n\nrepositories {\n  mavenCentral()\n}\n\ndependencies {\n  compile(\n    'commons-io:commons-io:2.5',\n  "
  },
  {
    "path": "buildSrc/src/main/groovy/com/yubico/gradle/pitest/tasks/PitestMergeTask.groovy",
    "chars": 1754,
    "preview": "package com.yubico.gradle.pitest.tasks\n\nimport groovy.xml.XmlUtil\n\nimport info.solidsoft.gradle.pitest.PitestTask\nimport"
  },
  {
    "path": "dev-util/example-authentication.py",
    "chars": 2099,
    "preview": "#!/usr/bin/python3\n#\n# Scratchpad for working with raw U2F messages, useful for creating raw messages as test data.\n# Ex"
  },
  {
    "path": "dev-util/example-registration.py",
    "chars": 6376,
    "preview": "#!/usr/bin/python3\n#\n# Scratchpad for working with raw U2F messages, useful for creating raw messages as test data.\n# Ex"
  },
  {
    "path": "lombok.config",
    "chars": 70,
    "preview": "config.stopBubbling = true\nlombok.addLombokGeneratedAnnotation = true\n"
  },
  {
    "path": "pom.xml",
    "chars": 8366,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2"
  },
  {
    "path": "u2flib-server-attestation/README.adoc",
    "chars": 1420,
    "preview": "== Device attestation  module\nModule for verifying attestation certificates and providing additional device metadata.\n\nT"
  },
  {
    "path": "u2flib-server-attestation/build.gradle",
    "chars": 103,
    "preview": "description = 'U2F attestation'\n\ndependencies {\n\n  compile(\n    project(':u2flib-server-core'),\n  )\n\n}\n"
  },
  {
    "path": "u2flib-server-attestation/gradle/wrapper/gradle-wrapper.properties",
    "chars": 201,
    "preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
  },
  {
    "path": "u2flib-server-attestation/gradlew",
    "chars": 5296,
    "preview": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up"
  },
  {
    "path": "u2flib-server-attestation/gradlew.bat",
    "chars": 2260,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
  },
  {
    "path": "u2flib-server-attestation/pom.xml",
    "chars": 758,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2"
  },
  {
    "path": "u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/Attestation.java",
    "chars": 1634,
    "preview": "/* Copyright 2015 Yubico */\n\npackage com.yubico.u2f.attestation;\n\nimport com.google.common.collect.ImmutableMap;\nimport "
  },
  {
    "path": "u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/DeviceMatcher.java",
    "chars": 465,
    "preview": "/* Copyright 2015 Yubico */\n\npackage com.yubico.u2f.attestation;\n\nimport com.fasterxml.jackson.databind.JsonNode;\n\nimpor"
  },
  {
    "path": "u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/MetadataObject.java",
    "chars": 4032,
    "preview": "/* Copyright 2015 Yubico */\n\npackage com.yubico.u2f.attestation;\n\nimport com.fasterxml.jackson.annotation.JsonCreator;\ni"
  },
  {
    "path": "u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/MetadataResolver.java",
    "chars": 398,
    "preview": "/* Copyright 2015 Yubico */\n\npackage com.yubico.u2f.attestation;\n\nimport java.security.cert.X509Certificate;\n\n/**\n * @de"
  },
  {
    "path": "u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/MetadataService.java",
    "chars": 7866,
    "preview": "/* Copyright 2015 Yubico */\n\npackage com.yubico.u2f.attestation;\n\nimport com.fasterxml.jackson.databind.JsonNode;\nimport"
  },
  {
    "path": "u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/Transport.java",
    "chars": 1185,
    "preview": "package com.yubico.u2f.attestation;\n\nimport java.util.Arrays;\nimport java.util.EnumSet;\nimport java.util.Set;\n\n/**\n * Cr"
  },
  {
    "path": "u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/matchers/ExtensionMatcher.java",
    "chars": 1488,
    "preview": "/* Copyright 2015 Yubico */\n\npackage com.yubico.u2f.attestation.matchers;\n\nimport com.fasterxml.jackson.databind.JsonNod"
  },
  {
    "path": "u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/matchers/FingerprintMatcher.java",
    "chars": 1375,
    "preview": "package com.yubico.u2f.attestation.matchers;\n\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.google.common.h"
  },
  {
    "path": "u2flib-server-attestation/src/main/java/com/yubico/u2f/attestation/resolvers/SimpleResolver.java",
    "chars": 2758,
    "preview": "/* Copyright 2015 Yubico */\n\npackage com.yubico.u2f.attestation.resolvers;\n\nimport com.google.common.collect.ArrayListMu"
  },
  {
    "path": "u2flib-server-attestation/src/main/resources/metadata.json",
    "chars": 4256,
    "preview": "{\n  \"identifier\": \"2fb54029-7613-4f1d-94f1-fb876c14a6fe\",\n  \"version\": 4,\n  \"vendorInfo\": {\n    \"url\": \"https://yubico.c"
  },
  {
    "path": "u2flib-server-attestation/src/test/java/com/yubico/u2f/attestation/MetadataObjectTest.java",
    "chars": 3281,
    "preview": "package com.yubico.u2f.attestation;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.google.common.collec"
  },
  {
    "path": "u2flib-server-attestation/src/test/java/com/yubico/u2f/attestation/MetadataServiceTest.java",
    "chars": 7138,
    "preview": "package com.yubico.u2f.attestation;\n\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.google.common.collect.Im"
  },
  {
    "path": "u2flib-server-attestation/src/test/java/com/yubico/u2f/attestation/TransportTest.java",
    "chars": 1691,
    "preview": "package com.yubico.u2f.attestation;\n\nimport org.junit.Test;\n\nimport java.util.EnumSet;\n\nimport static org.junit.Assert.a"
  },
  {
    "path": "u2flib-server-attestation/src/test/java/com/yubico/u2f/attestation/matchers/FingerprintMatcherTest.java",
    "chars": 3143,
    "preview": "package com.yubico.u2f.attestation.matchers;\n\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jacks"
  },
  {
    "path": "u2flib-server-attestation/src/test/java/com/yubico/u2f/attestation/resolvers/SimpleResolverTest.java",
    "chars": 4832,
    "preview": "package com.yubico.u2f.attestation.resolvers;\n\nimport com.yubico.u2f.attestation.MetadataObject;\nimport com.yubico.u2f.d"
  },
  {
    "path": "u2flib-server-core/build.gradle",
    "chars": 284,
    "preview": "description = 'U2F core'\n\ndependencies {\n\n  compile(\n    [group: 'org.bouncycastle', name: 'bcpkix-jdk15on', version:'1."
  },
  {
    "path": "u2flib-server-core/gradle/wrapper/gradle-wrapper.properties",
    "chars": 201,
    "preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
  },
  {
    "path": "u2flib-server-core/gradlew",
    "chars": 5296,
    "preview": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up"
  },
  {
    "path": "u2flib-server-core/gradlew.bat",
    "chars": 2260,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
  },
  {
    "path": "u2flib-server-core/pom.xml",
    "chars": 1112,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/AppId.java",
    "chars": 2631,
    "preview": "package com.yubico.u2f;\n\nimport com.google.common.net.InetAddresses;\nimport com.yubico.u2f.exceptions.U2fBadConfiguratio"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/U2F.java",
    "chars": 6207,
    "preview": "/* Copyright 2014 Yubico */\n\npackage com.yubico.u2f;\n\nimport com.google.common.base.Objects;\nimport com.google.common.ba"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/U2fPrimitives.java",
    "chars": 7731,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/crypto/BouncyCastleCrypto.java",
    "chars": 4147,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/crypto/ChallengeGenerator.java",
    "chars": 542,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/crypto/Crypto.java",
    "chars": 1068,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/crypto/RandomChallengeGenerator.java",
    "chars": 809,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/DeviceRegistration.java",
    "chars": 5462,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/ClientData.java",
    "chars": 3941,
    "preview": "package com.yubico.u2f.data.messages;\n\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.data"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/RegisterRequest.java",
    "chars": 2243,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/RegisterRequestData.java",
    "chars": 2732,
    "preview": "package com.yubico.u2f.data.messages;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport com.google.common.co"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/RegisterResponse.java",
    "chars": 2913,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/RegisteredKey.java",
    "chars": 1563,
    "preview": "package com.yubico.u2f.data.messages;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/SignRequest.java",
    "chars": 2351,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/SignRequestData.java",
    "chars": 3581,
    "preview": "package com.yubico.u2f.data.messages;\n\nimport com.fasterxml.jackson.annotation.JsonCreator;\nimport com.fasterxml.jackson"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/SignResponse.java",
    "chars": 3089,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/json/JsonSerializable.java",
    "chars": 1468,
    "preview": "package com.yubico.u2f.data.messages.json;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport com.fasterxml.jac"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/json/Persistable.java",
    "chars": 442,
    "preview": "package com.yubico.u2f.data.messages.json;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\n\nimport java.io.Serializ"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/key/RawRegisterResponse.java",
    "chars": 4912,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/key/RawSignResponse.java",
    "chars": 4145,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/key/util/ByteInputStream.java",
    "chars": 1281,
    "preview": "/*\n * Copyright 2014 Yubico.\n *\n * Use of this source code is governed by a BSD-style\n * license that can be found in th"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/key/util/CertificateParser.java",
    "chars": 2555,
    "preview": "package com.yubico.u2f.data.messages.key.util;\n\nimport com.google.common.io.BaseEncoding;\nimport com.yubico.u2f.crypto.B"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/data/messages/key/util/U2fB64Encoding.java",
    "chars": 917,
    "preview": "package com.yubico.u2f.data.messages.key.util;\n\nimport com.google.common.io.BaseEncoding;\nimport com.yubico.u2f.exceptio"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/DeviceCompromisedException.java",
    "chars": 817,
    "preview": "package com.yubico.u2f.exceptions;\n\nimport com.yubico.u2f.data.DeviceRegistration;\nimport lombok.Getter;\n\n/**\n * @deprec"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/InvalidDeviceCounterException.java",
    "chars": 590,
    "preview": "package com.yubico.u2f.exceptions;\n\nimport com.yubico.u2f.data.DeviceRegistration;\n\n/**\n * @deprecated The java-u2flib-s"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/NoEligableDevicesException.java",
    "chars": 869,
    "preview": "package com.yubico.u2f.exceptions;\n\nimport com.google.common.collect.ImmutableList;\nimport com.yubico.u2f.data.DeviceReg"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/NoEligibleDevicesException.java",
    "chars": 691,
    "preview": "package com.yubico.u2f.exceptions;\n\nimport com.yubico.u2f.data.DeviceRegistration;\n\n/**\n * @deprecated The java-u2flib-s"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/U2fAuthenticationException.java",
    "chars": 569,
    "preview": "package com.yubico.u2f.exceptions;\n\n/**\n * Base class for exceptions thrown when a U2F authentication ceremony fails.\n *"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/U2fBadConfigurationException.java",
    "chars": 483,
    "preview": "package com.yubico.u2f.exceptions;\n\n/**\n * @deprecated The java-u2flib-server library is obsolete. Use <a\n * href=\"https"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/U2fBadInputException.java",
    "chars": 743,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/U2fCeremonyException.java",
    "chars": 556,
    "preview": "package com.yubico.u2f.exceptions;\n\n/**\n * Base class for exceptions thrown when a U2F registration or authentication ce"
  },
  {
    "path": "u2flib-server-core/src/main/java/com/yubico/u2f/exceptions/U2fRegistrationException.java",
    "chars": 561,
    "preview": "package com.yubico.u2f.exceptions;\n\n/**\n * Base class for exceptions thrown when a U2F registration ceremony fails.\n *\n "
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/AppIdTest.java",
    "chars": 1650,
    "preview": "package com.yubico.u2f;\n\nimport com.yubico.u2f.exceptions.U2fBadConfigurationException;\nimport org.junit.Test;\n\nimport s"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/SystemTest.java",
    "chars": 2272,
    "preview": "package com.yubico.u2f;\n\nimport com.google.common.collect.ImmutableSet;\nimport com.yubico.u2f.data.DeviceRegistration;\ni"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/TestUtils.java",
    "chars": 4177,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/U2FTest.java",
    "chars": 9289,
    "preview": "package com.yubico.u2f;\n\nimport com.google.common.collect.ImmutableList;\nimport com.google.common.collect.ImmutableSet;\n"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/U2fPrimitivesTest.java",
    "chars": 12348,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/codec/RawCodecTest.java",
    "chars": 3178,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/codec/SerialCodecTest.java",
    "chars": 3123,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/data/DeviceRegistrationTest.java",
    "chars": 5103,
    "preview": "package com.yubico.u2f.data;\n\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/ClientDataTest.java",
    "chars": 1645,
    "preview": "package com.yubico.u2f.data.messages;\n\nimport com.google.common.base.Optional;\nimport com.google.common.collect.Immutabl"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/RegisterRequestDataTest.java",
    "chars": 4663,
    "preview": "package com.yubico.u2f.data.messages;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.google.common.coll"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/RegisterRequestTest.java",
    "chars": 1959,
    "preview": "package com.yubico.u2f.data.messages;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.yubico.u2f.TestUti"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/RegisterResponseTest.java",
    "chars": 4109,
    "preview": "package com.yubico.u2f.data.messages;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.yubico.u2f.TestUti"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/SignRequestDataTest.java",
    "chars": 4962,
    "preview": "package com.yubico.u2f.data.messages;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.google.common.coll"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/SignRequestTest.java",
    "chars": 1919,
    "preview": "package com.yubico.u2f.data.messages;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.yubico.u2f.TestUti"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/SignResponseTest.java",
    "chars": 3304,
    "preview": "package com.yubico.u2f.data.messages;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.yubico.u2f.TestUti"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/json/JsonSerializableTest.java",
    "chars": 535,
    "preview": "package com.yubico.u2f.data.messages.json;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport org.junit.Test;"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/key/Client.java",
    "chars": 5633,
    "preview": "package com.yubico.u2f.data.messages.key;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.google.common."
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/key/CodecTestUtils.java",
    "chars": 1886,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/key/util/CertificateParserTest.java",
    "chars": 1292,
    "preview": "package com.yubico.u2f.data.messages.key.util;\n\nimport java.security.cert.CertificateException;\nimport org.junit.Test;\n\n"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/data/messages/key/util/U2fB64EncodingTest.java",
    "chars": 1372,
    "preview": "package com.yubico.u2f.data.messages.key.util;\n\nimport org.junit.Test;\n\nimport com.yubico.u2f.exceptions.U2fBadInputExce"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/json/SerializationTest.java",
    "chars": 1006,
    "preview": "package com.yubico.u2f.json;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.yubico.u2f.data.messages.Si"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/softkey/SoftKey.java",
    "chars": 4503,
    "preview": "// Copyright 2014 Google Inc. All rights reserved.\n//\n// Use of this source code is governed by a BSD-style\n// license t"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/softkey/SoftKeyTest.java",
    "chars": 6000,
    "preview": "package com.yubico.u2f.softkey;\n\nimport com.yubico.u2f.U2fPrimitives;\nimport com.yubico.u2f.data.DeviceRegistration;\nimp"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/softkey/messages/RegisterRequest.java",
    "chars": 1010,
    "preview": "package com.yubico.u2f.softkey.messages;\n\npublic class RegisterRequest {\n    private final byte[] challengeSha256;\n    p"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/softkey/messages/SignRequest.java",
    "chars": 1564,
    "preview": "package com.yubico.u2f.softkey.messages;\n\npublic class SignRequest {\n\n    private final byte control;\n    private final "
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/testdata/AcmeKey.java",
    "chars": 2467,
    "preview": "package com.yubico.u2f.testdata;\n\nimport com.yubico.u2f.TestUtils;\nimport com.yubico.u2f.data.messages.key.util.U2fB64En"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/testdata/GnubbyKey.java",
    "chars": 614,
    "preview": "package com.yubico.u2f.testdata;\n\nimport java.security.PrivateKey;\nimport java.security.cert.X509Certificate;\n\nimport st"
  },
  {
    "path": "u2flib-server-core/src/test/java/com/yubico/u2f/testdata/TestVectors.java",
    "chars": 11392,
    "preview": "/*\n * Copyright 2014 Yubico.\n * Copyright 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governe"
  },
  {
    "path": "u2flib-server-core/src/test/resources/com/yubico/u2f/testdata/acme/attestation-certificate.der",
    "chars": 440,
    "preview": "MIIBRDCB6qADAgECAgkBkYn/////UYMwCgYIKoZIzj0EAwIwGzEZMBcGA1UEAxMQR251YmJ5IEhTTSBDQSAwMDAiGA8yMDEyMDYwMTAwMDAwMFoYDzIwNjIw"
  },
  {
    "path": "u2flib-server-core/src/test/resources/com/yubico/u2f/testdata/gnubby/attestation-certificate-private-key.hex",
    "chars": 64,
    "preview": "f3fccc0d00d8031954f90864d43c247f4bf5f0665c6b50cc17749a27d1cf7664"
  },
  {
    "path": "u2flib-server-core/src/test/resources/com/yubico/u2f/testdata/gnubby/attestation-certificate.der",
    "chars": 428,
    "preview": "MIIBPDCB5KADAgECAgpHkBKAABFVlXNSMAoGCCqGSM49BAMCMBcxFTATBgNVBAMTDEdudWJieSBQaWxvdDAeFw0xMjA4MTQxODI5MzJaFw0xMzA4MTQxODI5"
  },
  {
    "path": "u2flib-server-demo/README",
    "chars": 1258,
    "preview": "== u2flib-server-demo\nA simple self-contained demo server supporting multiple devices per user. The central part is the\n"
  },
  {
    "path": "u2flib-server-demo/build.gradle",
    "chars": 706,
    "preview": "description = 'U2F demo'\n\napply plugin: 'application'\n\nmainClassName = 'demo.App'\n\ndependencies {\n\n  compile(\n    projec"
  },
  {
    "path": "u2flib-server-demo/config.yml",
    "chars": 331,
    "preview": "server:\n  applicationConnectors:\n    - type: https\n      port: 8443\n      keyStorePath: keystore.jks\n      keyStorePassw"
  },
  {
    "path": "u2flib-server-demo/gradle/wrapper/gradle-wrapper.properties",
    "chars": 201,
    "preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
  },
  {
    "path": "u2flib-server-demo/gradlew",
    "chars": 5296,
    "preview": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up"
  },
  {
    "path": "u2flib-server-demo/gradlew.bat",
    "chars": 2260,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
  },
  {
    "path": "u2flib-server-demo/pom.xml",
    "chars": 3604,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2"
  },
  {
    "path": "u2flib-server-demo/src/main/java/demo/App.java",
    "chars": 686,
    "preview": "package demo;\n\nimport io.dropwizard.Application;\nimport io.dropwizard.assets.AssetsBundle;\nimport io.dropwizard.setup.Bo"
  },
  {
    "path": "u2flib-server-demo/src/main/java/demo/Config.java",
    "chars": 98,
    "preview": "package demo;\n\nimport io.dropwizard.Configuration;\n\npublic class Config extends Configuration {\n}\n"
  },
  {
    "path": "u2flib-server-demo/src/main/java/demo/Resource.java",
    "chars": 5831,
    "preview": "package demo;\n\nimport javax.ws.rs.FormParam;\nimport javax.ws.rs.GET;\nimport javax.ws.rs.POST;\nimport javax.ws.rs.Path;\ni"
  },
  {
    "path": "u2flib-server-demo/src/main/java/demo/U2fDemoException.java",
    "chars": 437,
    "preview": "package demo;\n\nimport javax.ws.rs.WebApplicationException;\nimport javax.ws.rs.core.Response;\n\npublic class U2fDemoExcept"
  },
  {
    "path": "u2flib-server-demo/src/main/java/demo/view/AuthenticationView.java",
    "chars": 704,
    "preview": "package demo.view;\n\nimport com.yubico.u2f.data.messages.SignRequestData;\nimport io.dropwizard.views.View;\n\nimport static"
  },
  {
    "path": "u2flib-server-demo/src/main/java/demo/view/FinishAuthenticationView.java",
    "chars": 719,
    "preview": "package demo.view;\n\nimport io.dropwizard.views.View;\nimport java.util.Collections;\nimport java.util.List;\nimport lombok."
  },
  {
    "path": "u2flib-server-demo/src/main/java/demo/view/FinishRegistrationView.java",
    "chars": 539,
    "preview": "package demo.view;\n\nimport com.yubico.u2f.attestation.Attestation;\nimport com.yubico.u2f.data.DeviceRegistration;\nimport"
  },
  {
    "path": "u2flib-server-demo/src/main/java/demo/view/RegistrationView.java",
    "chars": 545,
    "preview": "package demo.view;\n\nimport io.dropwizard.views.View;\n\nimport static com.google.common.base.Preconditions.checkNotNull;\n\n"
  },
  {
    "path": "u2flib-server-demo/src/main/resources/assets/loginIndex.html",
    "chars": 391,
    "preview": "<html>\n<body>\n<h2>Login</h2>\n\n<form method=\"GET\" action=\"/startAuthentication\" id=\"form\">\n    <label for=\"username\">User"
  },
  {
    "path": "u2flib-server-demo/src/main/resources/assets/registerIndex.html",
    "chars": 395,
    "preview": "<html>\n<body>\n<h2>Register</h2>\n\n<form method=\"GET\" action=\"/startRegistration\" id=\"form\">\n    <label for=\"username\">Use"
  },
  {
    "path": "u2flib-server-demo/src/main/resources/assets/u2f-api-1.1.js",
    "chars": 20880,
    "preview": "//Copyright 2014-2015 Google Inc. All rights reserved.\n\n//Use of this source code is governed by a BSD-style\n//license t"
  },
  {
    "path": "u2flib-server-demo/src/main/resources/demo/view/authenticate.ftl",
    "chars": 1550,
    "preview": "<html>\n<head>\n<title>Java U2F Demo</title>\n\n<script src=\"/assets/u2f-api-1.1.js\"></script>\n\n<script>\nvar request = JSON."
  },
  {
    "path": "u2flib-server-demo/src/main/resources/demo/view/finishAuthentication.ftl",
    "chars": 265,
    "preview": "<html>\n<head>\n<title>Java U2F Demo</title>\n</head>\n<body>\n\n    <#if success>\n      <p>\n        Successfully authenticate"
  },
  {
    "path": "u2flib-server-demo/src/main/resources/demo/view/finishRegistration.ftl",
    "chars": 941,
    "preview": "<html>\n<head>\n<title>Java U2F Demo</title>\n</head>\n<body>\n\n    <p>Successfully registered device:</p>\n\n    <#list attest"
  },
  {
    "path": "u2flib-server-demo/src/main/resources/demo/view/navigation.ftl",
    "chars": 148,
    "preview": "<h2>Navigation</h2>\n\n<ul>\n  <li><a href='/assets/registerIndex.html'>Register</a></li>\n  <li><a href='/assets/loginIndex"
  },
  {
    "path": "u2flib-server-demo/src/main/resources/demo/view/register.ftl",
    "chars": 1270,
    "preview": "<html>\n<head>\n<title>Java U2F Demo</title>\n\n<script src=\"/assets/u2f-api-1.1.js\"></script>\n\n<script>\nvar request = JSON."
  }
]

// ... and 4 more files (download for full content)

About this extraction

This page contains the full source code of the Yubico/java-u2flib-server GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 129 files (314.4 KB), approximately 86.9k tokens, and a symbol index with 456 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!