public final class PinSet
- Object
- PinSet
An immutable set of certificate pins, keyed by host, as published by the attestation service.
Pins are over the subject public key info, not the whole certificate, so a host can renew its certificate on the same key pair without invalidating the pin. A chain matches if any certificate in it matches any pin for the host, which is what makes it safe to pin an issuing CA as the backup.
The never-brick rules
Client-side pinning is the one part of the shield that can take an app offline for reasons the developer cannot fix without an app store release, so the failure behaviour is deliberately asymmetric:
- A host with no pins is never enforced. That covers first run, a cold start with no network, and any host the service has not published pins for.
- A failed pin fetch never fails a request. The last known set is kept.
- Pins carry a soft expiry, after which a refresh is attempted, and a much later hard expiry. Past the hard expiry the set is dropped and enforcement stops. A device that cannot reach the service for weeks loses pinning; it does not lose the app.
- Only an actual mismatch – a host that has pins presenting a chain that matches none of them – fails a request, and it fails before any request body is written.
Fields
public static final PinSet EMPTY | A pin set with no hosts. |
Constructors
public PinSet(Hashtable hostToPins, int version, long softExpiry, long hardExpiry) |
Methods
public int getVersion() | |
public boolean isStale() | True once the set should be refreshed. |
public boolean isExpired() | True once the set is too old to keep enforcing. |
public boolean isEnforcedFor(String host) | True when this set has at least one pin for the host and has not hard-expired, i.e. when a chain for this host is actually going to be checked. |
public int hostCount() | Number of hosts with at least one pin. |
public Vector pinsFor(String host) | The pins registered for a host, honouring a leading *. wildcard, or null when the host is not pinned. |
public boolean matches(String host, String[] chainSpkiDigests) | True when at least one of the supplied chain digests matches a pin for the host. |
public boolean isEmpty() | True when no host is pinned. |
public String toString() | Returns a string representation of the object. |
Inherited methods
Field details
EMPTY
public static final PinSet EMPTYConstructor details
PinSet
public PinSet(Hashtable hostToPins, int version, long softExpiry, long hardExpiry)Parameters
hostToPinsHashtable- host (lowercase) to a
Vectorof base64 SHA-256 SPKI digests versionint- monotonic version from the service, used to detect a newer published set
softExpirylong- local millis after which a refresh should be attempted, 0 for never
hardExpirylong- local millis after which the set is discarded entirely, 0 for never
Method details
getVersion
public int getVersion()isStale
public boolean isStale()isExpired
public boolean isExpired()isEnforcedFor
public boolean isEnforcedFor(String host)hostCount
public int hostCount()pinsFor
public Vector pinsFor(String host)*. wildcard, or null when the host is
not pinned.matches
public boolean matches(String host, String[] chainSpkiDigests)True when at least one of the supplied chain digests matches a pin for the host.
Returns true when the host is not pinned at all – “no opinion” must never be reported as a mismatch, or an unpinned host would start failing.
isEmpty
public boolean isEmpty()toString
public String toString()