appattest

module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Apr 15, 2021 License: BSD-3-Clause

README

AppAttest

Since iOS 14, Apple offers a new way to attest the integrity of a device. This is based on the WebAuthn specification. This go module implements the server-side validation of both attestations and assertions that can be obtained using the DCAppAttestService.

Installation

Get the module with go get github.com/bas-d/appattest.

Usage

The module offers a packge for attestation and for assertion.

Attestation

Generate a key pair and attestation in your app as specified in the documentation.

The validate the attestation, create an AuthenticatorAttestationResponse object, for example:

attestation = `{
	"attestationObject": "o2NmbXRv...WUHFMII",
	"keyID": "AcP/pnpoNVPIJYZOvmIvWzDvmxkFoQCE4Uu7Nk6WiAA=",
	"clientData": "YXR0ZXN0YXRpb24tdGVzdA"
}`

The attestationObject should be URL-safe base64 encoded (as it is generated by DCAppAttestService). The keyID should be normal base64-encoded (also as it is generated by DCAppAttestService). The clientData should also be URL-safe base64 encoded. This should be encoded by you. It should contain a randomly generated challenge that your obtained from the server before starting the attestation.

After creating the AuthenticatorAttestationResponse, validate the attestation by calling:

pk, clientDataHash, err := aar.Verify("<TEAMID.reverse.dns.app.id>", isProduction)
if err != nil {
    // Handle error
}

You should specify whether this called in a production environment, because Apple uses a different value for attestation objects in a live app and a development build.
The function returns the public key and receipt if the validation succeeds. If not, err is not nil. The public key and receipt should be saved in your database.

Assertion

Assuming attestation was succesful and you have the public key stored in your database, create an assertion in your app as specificied in the documentation.

To validate the assertion, create an AuthenticatorAssertionResponse object, for example:

const assertion = `{
	"assertion": "omlzaW...n9wdEAAAAAD",
	"clientData": "eyJjaGFsbGVuZ2UiOiJhc3NlcnRpb24tdGVzdCJ9"
}`

The assertion should be URL-safe base64 encoded (as it is generated by DCAppAttestService). The clientData should be a URL-safe base64 encoded JSON-object and should contain a string with key challenge, which should have been obtained from the server before starting the assertion in your app. It may contain other data that you want to assert as well.

Verify the assertion by calling:

counter, err = aar.Verify("<your_stored_challenge>", "<TEAMID.reverse.dns.app.id>", initialCounter, pubKey)
if err != nil {
    // Handle error
}

You should provide the challenge you shared earlier to your app. It should be a string and is expected to be the same as the challenge in the clientData also a string. Second argument is your App ID. Furthermore, provide the current counter (prevents replay attacks) and decoded public key (retrieved from your database). When the assertion succeeds, you get the new counter that you should store in your database.

Contributing

This is the first time I use Go, so any feedback and suggestions are welcome, also on how to make this module more go-idiomatic. Pull requests are welcome, please create them to dev branch.

Acknowledgements

Most of the code has been based on the WebAuthn Library by Duo Labs, so most of the works was aleady done by them!

License

BSD 3-Clause License. See LICENSE.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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