Skip to content

swift-app-attest 1.0.0

Choose a tag to compare

@tixster tixster released this 18 Aug 19:54
· 4 commits to main since this release

Initial release: full coverage of Apple's App Attest API, on both sides of the wire.

AppAttestClient — iOS 14+ / macOS 11+ / tvOS 15+ / watchOS 9+ / visionOS 1+

  • AppAttestService: a thin async wrapper over DCAppAttestServiceisSupported,
    generateKey(), attestKey, generateAssertion.
  • Typed errors: every method is async throws(AppAttestClientError), mapping all
    DCError codes with recovery guidance in the docs (e.g. re-attest on .invalidKey).
  • Convenience overloads attestKey(_:challenge:) and generateAssertion(_:clientData:)
    hash with SHA-256 for you; raw clientDataHash: pass-throughs remain.

AppAttestServer — macOS 11+ / Linux

  • AttestationVerifier implements every step of Apple's Validating apps that
    connect to your server
    : certificate chain to the pinned Apple App Attest Root CA,
    nonce extension (OID 1.2.840.113635.100.8.2), key identifier, App ID (RP ID) hash,
    counter, environment AAGUID, credential ID — plus the macOS access-control policy
    check (aclBlob, OID 1.2.840.113635.100.8.6).
  • AssertionVerifier: ECDSA signature over SHA256(authData || SHA256(clientData)),
    RP ID, strictly increasing counter, and challenge validation with a pluggable
    extractor for app-specific client-data formats.
  • Both verifiers surface the apple_validation_category_01 (distribution category) and
    apple_bundle_version_01 (app version) authenticator-data extensions.
  • ReceiptVerifier: PKCS #7 receipts verified up to Apple Root CA - G3, decoded
    into typed fields (App ID, attested certificate, receipt type, creation/not-before/
    expiration times, risk metric).
  • FraudAssessmentClient: the receipt exchange with
    data{-development}.appattest.apple.com, authenticated with an ES256 JWT from an
    App Store Connect key; all documented response codes are mapped to typed errors.
    Transport sits behind the AppAttestHTTPClient protocol — URLSession by default,
    AsyncHTTPClient pluggable.
  • AppAttestChallenge.generate() for issuing server challenges.
  • Typed throws throughout: AppAttestVerificationError and AppAttestReceiptError
    name the exact check that failed.

Shared core

  • AppAttestKeyID, AppAttestEnvironment, and optional Codable transport DTOs
    (AttestationPayload, AssertionPayload) are shared by both products, so the
    client and server always agree on the wire format.

Under the hood

  • Dependencies: only Apple's swift-crypto, swift-certificates, and swift-asn1;
    CBOR is decoded by a small internal reader.
  • 78 tests run fully offline against synthetic attestation chains, CMS-signed
    receipts, and cryptographically verified JWTs; every verifier failure branch
    is covered.
  • CI on macOS and Linux (Swift 6.1 and latest); API documentation is published
    at https://tixster.github.io/swift-app-attest/documentation/

Installation

.package(url: "https://github.com/tixster/swift-app-attest.git", from: "1.0.0"),