@motebit/crypto-android-keystore 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/verify.js ADDED
@@ -0,0 +1,423 @@
1
+ /**
2
+ * Android Hardware-Backed Keystore Attestation verifier — the core
3
+ * judgment function this package exports.
4
+ *
5
+ * Flow (matches Google's published verification recipe at
6
+ * https://source.android.com/docs/security/features/keystore/attestation,
7
+ * plus the motebit-specific identity-key binding step):
8
+ *
9
+ * 1. Split the receipt into the leaf cert plus the rest of the chain
10
+ * (`{leafCertB64}.{intermediatesJoinedB64}` — comma-joined leaf-
11
+ * proximal-first base64url DER blobs in the second segment).
12
+ * 2. Parse the chain as X.509 certificates. Walk the chain leaf →
13
+ * intermediates → terminal anchor with `@peculiar/x509`'s
14
+ * `X509ChainBuilder`. Every non-leaf must carry
15
+ * `basicConstraints.cA === true`. Every signature must verify
16
+ * under its issuer's public key. Every cert must be within its
17
+ * validity window. The terminal cert's DER must equal one of the
18
+ * pinned Google attestation roots.
19
+ * 3. Read the Android Key Attestation extension (OID
20
+ * `1.3.6.1.4.1.11129.2.1.17`) from the LEAF cert only. The AOSP
21
+ * spec is explicit that later occurrences of this extension up
22
+ * the chain MUST be ignored — only the leaf's copy carries
23
+ * trustworthy data, because only the leaf is signed by the
24
+ * device's secure-hardware key.
25
+ * 4. Constrain the parsed `KeyDescription`:
26
+ * - `attestationSecurityLevel ≥ TRUSTED_ENVIRONMENT` (rejects
27
+ * software-only fallback, which is structurally not
28
+ * third-party meaningful)
29
+ * - `attestationVersion ≥ 3` (rejects pre-Android-7 / Keymaster
30
+ * v2; current production is 4 / Keymaster 4 through 400 /
31
+ * KeyMint 4.0)
32
+ * - `hardwareEnforced.rootOfTrust.verifiedBootState` is in the
33
+ * caller's allowlist (default: VERIFIED only)
34
+ * - `hardwareEnforced.attestationApplicationId` byte-equals
35
+ * the caller's expected package binding
36
+ * - leaf's serial number is not in the caller-supplied
37
+ * revocation snapshot
38
+ * 5. Cryptographically bind the leaf's `attestationChallenge` field
39
+ * to the motebit Ed25519 identity: re-derive
40
+ * `SHA-256(canonicalJson({ attested_at, device_id,
41
+ * identity_public_key, motebit_id, platform: "android_keystore",
42
+ * version: "1" }))` and byte-compare against the transmitted
43
+ * challenge. A malicious client that substitutes any other body
44
+ * fails here.
45
+ *
46
+ * Pure. No network. No filesystem. Deterministic given `now()` and
47
+ * the caller-supplied revocation snapshot.
48
+ */
49
+ import * as x509 from "@peculiar/x509";
50
+ import { ANDROID_KEY_ATTESTATION_OID, DEFAULT_ANDROID_KEYSTORE_TRUST_ANCHORS, } from "./google-roots.js";
51
+ import { parseKeyDescription, SECURITY_LEVEL_TRUSTED_ENVIRONMENT, VERIFIED_BOOT_STATE_VERIFIED, } from "./asn1.js";
52
+ /** Empty revocation snapshot — every leaf passes the revocation check. */
53
+ export const EMPTY_REVOCATION_SNAPSHOT = { entries: {} };
54
+ /**
55
+ * Android Hardware-Backed Keystore Attestation verifier.
56
+ *
57
+ * `claim.attestation_receipt` is the cert chain encoded as
58
+ * `{leafCertB64}.{intermediatesJoinedB64}` — leaf-first DER chain
59
+ * matching the wire format the Kotlin `expo-android-keystore` mint
60
+ * path emits. The intermediates segment is a comma-joined list of
61
+ * base64url-encoded DERs in leaf-proximal-first order; an empty
62
+ * second segment means the leaf chains directly to a pinned root.
63
+ */
64
+ export async function verifyAndroidKeystoreAttestation(claim, opts) {
65
+ const errors = [];
66
+ let cert_chain_valid = false;
67
+ let attestation_extension_valid = false;
68
+ let identity_bound = false;
69
+ let attestation_security_level = null;
70
+ let verified_boot_state = null;
71
+ if (!claim.attestation_receipt) {
72
+ errors.push({ message: "android_keystore claim missing `attestation_receipt`" });
73
+ return finalize();
74
+ }
75
+ const parts = claim.attestation_receipt.split(".");
76
+ if (parts.length !== 2) {
77
+ errors.push({
78
+ message: `attestation_receipt must be 2 base64url parts (leafCert.intermediates); got ${parts.length}`,
79
+ });
80
+ return finalize();
81
+ }
82
+ const [leafB64, intermediatesB64] = parts;
83
+ let leafBytes;
84
+ let intermediatesBytes;
85
+ try {
86
+ leafBytes = fromBase64Url(leafB64);
87
+ intermediatesBytes =
88
+ intermediatesB64.length === 0 ? [] : intermediatesB64.split(",").map((p) => fromBase64Url(p));
89
+ }
90
+ catch (err) {
91
+ errors.push({ message: `base64url decode failed: ${messageOf(err)}` });
92
+ return finalize();
93
+ }
94
+ let leaf;
95
+ let intermediates;
96
+ let rootCerts;
97
+ try {
98
+ leaf = new x509.X509Certificate(toArrayBuffer(leafBytes));
99
+ intermediates = intermediatesBytes.map((b) => new x509.X509Certificate(toArrayBuffer(b)));
100
+ const pems = opts.rootPems ?? DEFAULT_ANDROID_KEYSTORE_TRUST_ANCHORS;
101
+ rootCerts = pems.map((pem) => new x509.X509Certificate(pem));
102
+ }
103
+ catch (err) {
104
+ errors.push({ message: `x509 parse: ${messageOf(err)}` });
105
+ return finalize();
106
+ }
107
+ const nowDate = new Date(opts.now ? opts.now() : Date.now());
108
+ // ── Chain verification ────────────────────────────────────────────
109
+ try {
110
+ const chainResult = await verifyChain({ leaf, intermediates, pinnedRoots: rootCerts, nowDate });
111
+ cert_chain_valid = chainResult.valid;
112
+ if (!cert_chain_valid) {
113
+ errors.push({ message: chainResult.reason });
114
+ }
115
+ }
116
+ catch (err) {
117
+ errors.push({ message: `chain verify crashed: ${messageOf(err)}` });
118
+ return finalize();
119
+ }
120
+ // ── Revocation lookup (leaf serial) ──────────────────────────────
121
+ // The leaf serial is the device-attestation key's serial; Google
122
+ // adds it to https://android.googleapis.com/attestation/status when
123
+ // a leaked keybox is detected. Caller-supplied snapshot.
124
+ const snapshot = opts.revocationSnapshot ?? EMPTY_REVOCATION_SNAPSHOT;
125
+ const leafSerialLower = leaf.serialNumber.toLowerCase();
126
+ const revocation = snapshot.entries[leafSerialLower];
127
+ if (revocation) {
128
+ errors.push({
129
+ message: `leaf cert revoked (serial=${leafSerialLower}, status=${revocation.status}${revocation.reason ? `, reason=${revocation.reason}` : ""})`,
130
+ });
131
+ }
132
+ const revocationOk = !revocation;
133
+ // ── Key Attestation extension ─────────────────────────────────────
134
+ let keyDescription = null;
135
+ const extension = leaf.getExtension(ANDROID_KEY_ATTESTATION_OID);
136
+ if (!extension) {
137
+ errors.push({
138
+ message: `leaf cert missing Android Key Attestation extension (OID ${ANDROID_KEY_ATTESTATION_OID}) — not a hardware-attested leaf`,
139
+ });
140
+ }
141
+ else {
142
+ try {
143
+ keyDescription = parseKeyDescription(new Uint8Array(extension.value));
144
+ attestation_security_level = keyDescription.attestationSecurityLevel;
145
+ verified_boot_state = keyDescription.hardwareEnforced.rootOfTrust?.verifiedBootState ?? null;
146
+ const constraintsOk = applyExtensionConstraints(keyDescription, opts, errors);
147
+ attestation_extension_valid = constraintsOk && revocationOk;
148
+ }
149
+ catch (err) {
150
+ errors.push({ message: `Key Attestation extension parse: ${messageOf(err)}` });
151
+ }
152
+ }
153
+ // ── Identity binding ──────────────────────────────────────────────
154
+ if (keyDescription) {
155
+ identity_bound = await applyIdentityBinding(keyDescription.attestationChallenge, opts, errors);
156
+ }
157
+ return finalize();
158
+ function finalize() {
159
+ return {
160
+ valid: cert_chain_valid && attestation_extension_valid && identity_bound,
161
+ cert_chain_valid,
162
+ attestation_extension_valid,
163
+ identity_bound,
164
+ attestation_security_level,
165
+ verified_boot_state,
166
+ errors,
167
+ };
168
+ }
169
+ }
170
+ /**
171
+ * Apply the policy constraints to the parsed `KeyDescription`. Returns
172
+ * `true` only if every constraint passed; returns `false` and pushes
173
+ * a structured error otherwise. Multiple failures accumulate so the
174
+ * caller sees the full picture.
175
+ */
176
+ function applyExtensionConstraints(kd, opts, errors) {
177
+ let ok = true;
178
+ // attestationVersion floor
179
+ const minAttestationVersion = opts.minAttestationVersion ?? 3;
180
+ if (kd.attestationVersion < minAttestationVersion) {
181
+ errors.push({
182
+ message: `attestationVersion ${kd.attestationVersion} below minimum ${minAttestationVersion} (Keymaster 3 / Android 7+)`,
183
+ });
184
+ ok = false;
185
+ }
186
+ // attestationSecurityLevel floor — software-only fallback rejected
187
+ const minSecurityLevel = opts.minSecurityLevel ?? SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
188
+ if (kd.attestationSecurityLevel < minSecurityLevel) {
189
+ errors.push({
190
+ message: `attestationSecurityLevel ${kd.attestationSecurityLevel} below minimum ${minSecurityLevel} (TRUSTED_ENVIRONMENT or higher required for canonical hardware attestation)`,
191
+ });
192
+ ok = false;
193
+ }
194
+ // hardwareEnforced.rootOfTrust must be present with allowlisted
195
+ // verifiedBootState. The default allowlist is [VERIFIED] —
196
+ // user-unlocked devices are rejected at the canonical floor;
197
+ // GrapheneOS-style SELF_SIGNED can be opted in by the operator.
198
+ const allowlist = opts.verifiedBootStateAllowlist ?? [VERIFIED_BOOT_STATE_VERIFIED];
199
+ const rot = kd.hardwareEnforced.rootOfTrust;
200
+ if (!rot) {
201
+ errors.push({
202
+ message: "hardwareEnforced.rootOfTrust missing — cannot certify boot-image state",
203
+ });
204
+ ok = false;
205
+ }
206
+ else if (allowlist.length > 0 && !allowlist.includes(rot.verifiedBootState)) {
207
+ errors.push({
208
+ message: `verifiedBootState ${rot.verifiedBootState} not in allowlist [${allowlist.join(", ")}]`,
209
+ });
210
+ ok = false;
211
+ }
212
+ // attestationApplicationId binding — exact byte match. Per AOSP
213
+ // convention since Keymaster 4 (2018), the field lives in
214
+ // `softwareEnforced` because the framework computes the package
215
+ // signing-cert hash, not the TEE. Older Keymaster 3 chains placed
216
+ // it in `hardwareEnforced`. Accept either; software-enforcement is
217
+ // sufficient because the framework binding is not the attack surface
218
+ // motebit gates on (chain + boot state + identity binding are).
219
+ const expectedAppId = opts.expectedAttestationApplicationId;
220
+ const actualAppId = kd.hardwareEnforced.attestationApplicationId ?? kd.softwareEnforced.attestationApplicationId;
221
+ if (!actualAppId) {
222
+ errors.push({
223
+ message: "attestationApplicationId missing from both hardwareEnforced and softwareEnforced — cannot bind to package identity",
224
+ });
225
+ ok = false;
226
+ }
227
+ else if (!bytesEq(actualAppId, expectedAppId)) {
228
+ errors.push({
229
+ message: `attestationApplicationId does not match expected package binding (${actualAppId.length}B leaf vs ${expectedAppId.length}B expected)`,
230
+ });
231
+ ok = false;
232
+ }
233
+ return ok;
234
+ }
235
+ /**
236
+ * Apply the cross-stack identity binding: SHA-256 the JCS canonical
237
+ * body naming the caller's identity, byte-compare against the leaf's
238
+ * `attestationChallenge`. Returns true on success; pushes structured
239
+ * errors on each missing or mismatched field.
240
+ */
241
+ async function applyIdentityBinding(challenge, opts, errors) {
242
+ if (typeof opts.expectedIdentityPublicKeyHex !== "string" ||
243
+ opts.expectedIdentityPublicKeyHex.length === 0) {
244
+ errors.push({ message: "identity_bound: expectedIdentityPublicKeyHex not supplied" });
245
+ return false;
246
+ }
247
+ if (typeof opts.expectedMotebitId !== "string" || opts.expectedMotebitId.length === 0) {
248
+ errors.push({
249
+ message: "identity_bound: expectedMotebitId not supplied (required for body re-derivation)",
250
+ });
251
+ return false;
252
+ }
253
+ if (typeof opts.expectedDeviceId !== "string" || opts.expectedDeviceId.length === 0) {
254
+ errors.push({
255
+ message: "identity_bound: expectedDeviceId not supplied (required for body re-derivation)",
256
+ });
257
+ return false;
258
+ }
259
+ if (typeof opts.expectedAttestedAt !== "number" || !Number.isFinite(opts.expectedAttestedAt)) {
260
+ errors.push({
261
+ message: "identity_bound: expectedAttestedAt not supplied (required for body re-derivation)",
262
+ });
263
+ return false;
264
+ }
265
+ const canonicalBody = buildCanonicalAttestationBody({
266
+ attested_at: opts.expectedAttestedAt,
267
+ device_id: opts.expectedDeviceId,
268
+ identity_public_key: opts.expectedIdentityPublicKeyHex.toLowerCase(),
269
+ motebit_id: opts.expectedMotebitId,
270
+ });
271
+ const derived = await sha256Bytes(new TextEncoder().encode(canonicalBody));
272
+ if (bytesEq(derived, challenge))
273
+ return true;
274
+ errors.push({
275
+ message: "identity_bound: reconstructed SHA256(canonical body) does not equal leaf attestationChallenge — body naming the caller's identity was not the body the device attested over",
276
+ });
277
+ return false;
278
+ }
279
+ // ── Helpers ──────────────────────────────────────────────────────────
280
+ /** OID for X.509 basic-constraints extension. */
281
+ const BASIC_CONSTRAINTS_OID = "2.5.29.19";
282
+ /**
283
+ * Walk the cert chain from leaf → intermediates → pinned anchor.
284
+ * Mirrors the App Attest / TPM chain verifier invariants:
285
+ * 1. `X509ChainBuilder.build(leaf)` returns a chain terminating at
286
+ * a self-signed cert reachable from the supplied + pinned pool.
287
+ * 2. The terminal cert's DER byte-equals one of the pinned roots.
288
+ * 3. Every non-leaf cert carries `basicConstraints.cA === true`.
289
+ * 4. Every signature verifies under its issuer's public key.
290
+ * 5. Every cert is within its validity window at `nowDate`.
291
+ */
292
+ async function verifyChain(input) {
293
+ const { leaf, intermediates, pinnedRoots, nowDate } = input;
294
+ if (pinnedRoots.length === 0) {
295
+ return { valid: false, reason: "no pinned trust anchors configured" };
296
+ }
297
+ const builder = new x509.X509ChainBuilder({
298
+ certificates: [leaf, ...intermediates, ...pinnedRoots],
299
+ });
300
+ const chain = await builder.build(leaf);
301
+ const terminal = chain[chain.length - 1];
302
+ const terminalSelfSigned = await terminal.isSelfSigned();
303
+ if (!terminalSelfSigned) {
304
+ return { valid: false, reason: "chain does not terminate at a self-signed root" };
305
+ }
306
+ const terminalDer = new Uint8Array(terminal.rawData);
307
+ const matchesPinned = pinnedRoots.some((root) => bytesEq(terminalDer, new Uint8Array(root.rawData)));
308
+ if (!matchesPinned) {
309
+ return {
310
+ valid: false,
311
+ reason: "chain terminal cert DER does not match any pinned Google Hardware Attestation root (RSA / ECDSA P-384)",
312
+ };
313
+ }
314
+ for (let i = 0; i < chain.length; i++) {
315
+ const cert = chain[i];
316
+ if (nowDate < cert.notBefore || nowDate > cert.notAfter) {
317
+ return {
318
+ valid: false,
319
+ reason: `cert at chain position ${i} is outside its validity window at ${nowDate.toISOString()}`,
320
+ };
321
+ }
322
+ const isLeaf = i === 0;
323
+ if (!isLeaf && !certHasCaTrue(cert)) {
324
+ return {
325
+ valid: false,
326
+ reason: `cert at chain position ${i} lacks basicConstraints.cA=true (CA constraint not enforced)`,
327
+ };
328
+ }
329
+ const issuer = i === chain.length - 1 ? cert : chain[i + 1];
330
+ const sigOk = await cert.verify({ publicKey: issuer.publicKey, date: nowDate });
331
+ if (!sigOk) {
332
+ return {
333
+ valid: false,
334
+ reason: `cert at chain position ${i} signature did not verify under its issuer's public key`,
335
+ };
336
+ }
337
+ }
338
+ return { valid: true, reason: "ok" };
339
+ }
340
+ function certHasCaTrue(cert) {
341
+ const ext = cert.getExtension(BASIC_CONSTRAINTS_OID);
342
+ if (!ext)
343
+ return false;
344
+ return ext.ca === true;
345
+ }
346
+ /**
347
+ * Reconstruct the byte-identical canonical body the Kotlin
348
+ * `expo-android-keystore` mint path composes at attestation time.
349
+ *
350
+ * Ordering: alphabetical (JCS):
351
+ * attested_at, device_id, identity_public_key, motebit_id, platform,
352
+ * version.
353
+ *
354
+ * `platform` is always `"android_keystore"` and `version` is always
355
+ * `"1"` — both constants, matching the App Attest / TPM canonical-body
356
+ * shape exactly.
357
+ */
358
+ function buildCanonicalAttestationBody(input) {
359
+ return (`{"attested_at":${input.attested_at}` +
360
+ `,"device_id":${jsonEscapeString(input.device_id)}` +
361
+ `,"identity_public_key":${jsonEscapeString(input.identity_public_key)}` +
362
+ `,"motebit_id":${jsonEscapeString(input.motebit_id)}` +
363
+ `,"platform":"android_keystore"` +
364
+ `,"version":"1"}`);
365
+ }
366
+ function jsonEscapeString(s) {
367
+ let out = '"';
368
+ for (const ch of s) {
369
+ const code = ch.codePointAt(0);
370
+ if (ch === '"')
371
+ out += '\\"';
372
+ else if (ch === "\\")
373
+ out += "\\\\";
374
+ else if (ch === "\n")
375
+ out += "\\n";
376
+ else if (ch === "\r")
377
+ out += "\\r";
378
+ else if (ch === "\t")
379
+ out += "\\t";
380
+ else if (code < 0x20)
381
+ out += `\\u${code.toString(16).padStart(4, "0")}`;
382
+ else
383
+ out += ch;
384
+ }
385
+ out += '"';
386
+ return out;
387
+ }
388
+ async function sha256Bytes(data) {
389
+ const buf = await globalThis.crypto.subtle.digest("SHA-256", data);
390
+ return new Uint8Array(buf);
391
+ }
392
+ function bytesEq(a, b) {
393
+ if (a.length !== b.length)
394
+ return false;
395
+ for (let i = 0; i < a.length; i++)
396
+ if (a[i] !== b[i])
397
+ return false;
398
+ return true;
399
+ }
400
+ function toArrayBuffer(bytes) {
401
+ const copy = new Uint8Array(bytes.length);
402
+ copy.set(bytes);
403
+ return copy.buffer;
404
+ }
405
+ function fromBase64Url(str) {
406
+ let b64 = str.replace(/-/g, "+").replace(/_/g, "/");
407
+ const pad = b64.length % 4;
408
+ if (pad === 2)
409
+ b64 += "==";
410
+ else if (pad === 3)
411
+ b64 += "=";
412
+ else if (pad === 1)
413
+ throw new Error("invalid base64url length");
414
+ const binary = atob(b64);
415
+ const out = new Uint8Array(binary.length);
416
+ for (let i = 0; i < binary.length; i++)
417
+ out[i] = binary.charCodeAt(i);
418
+ return out;
419
+ }
420
+ function messageOf(err) {
421
+ return err instanceof Error ? err.message : String(err);
422
+ }
423
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAEH,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AAIvC,OAAO,EACL,2BAA2B,EAC3B,sCAAsC,GACvC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mBAAmB,EACnB,kCAAkC,EAClC,4BAA4B,GAE7B,MAAM,WAAW,CAAC;AAuBnB,0EAA0E;AAC1E,MAAM,CAAC,MAAM,yBAAyB,GAAsC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;AA0G5F;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,KAA+B,EAC/B,IAAkC;IAElC,MAAM,MAAM,GAAiC,EAAE,CAAC;IAChD,IAAI,gBAAgB,GAAG,KAAK,CAAC;IAC7B,IAAI,2BAA2B,GAAG,KAAK,CAAC;IACxC,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,IAAI,0BAA0B,GAAkB,IAAI,CAAC;IACrD,IAAI,mBAAmB,GAAkB,IAAI,CAAC;IAE9C,IAAI,CAAC,KAAK,CAAC,mBAAmB,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,sDAAsD,EAAE,CAAC,CAAC;QACjF,OAAO,QAAQ,EAAE,CAAC;IACpB,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,mBAAmB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC;YACV,OAAO,EAAE,+EAA+E,KAAK,CAAC,MAAM,EAAE;SACvG,CAAC,CAAC;QACH,OAAO,QAAQ,EAAE,CAAC;IACpB,CAAC;IACD,MAAM,CAAC,OAAO,EAAE,gBAAgB,CAAC,GAAG,KAAyB,CAAC;IAE9D,IAAI,SAAqB,CAAC;IAC1B,IAAI,kBAAgC,CAAC;IACrC,IAAI,CAAC;QACH,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACnC,kBAAkB;YAChB,gBAAgB,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAClG,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,4BAA4B,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QACvE,OAAO,QAAQ,EAAE,CAAC;IACpB,CAAC;IAED,IAAI,IAA0B,CAAC;IAC/B,IAAI,aAAqC,CAAC;IAC1C,IAAI,SAAiC,CAAC;IACtC,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;QAC1D,aAAa,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1F,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,IAAI,sCAAsC,CAAC;QACrE,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,eAAe,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1D,OAAO,QAAQ,EAAE,CAAC;IACpB,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAE7D,qEAAqE;IACrE,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;QAChG,gBAAgB,GAAG,WAAW,CAAC,KAAK,CAAC;QACrC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,yBAAyB,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QACpE,OAAO,QAAQ,EAAE,CAAC;IACpB,CAAC;IAED,oEAAoE;IACpE,iEAAiE;IACjE,oEAAoE;IACpE,yDAAyD;IACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,IAAI,yBAAyB,CAAC;IACtE,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;IACxD,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IACrD,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC;YACV,OAAO,EAAE,6BAA6B,eAAe,YAAY,UAAU,CAAC,MAAM,GAChF,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EACxD,GAAG;SACJ,CAAC,CAAC;IACL,CAAC;IACD,MAAM,YAAY,GAAG,CAAC,UAAU,CAAC;IAEjC,qEAAqE;IACrE,IAAI,cAAc,GAA0B,IAAI,CAAC;IACjD,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,2BAA2B,CAAC,CAAC;IACjE,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC;YACV,OAAO,EAAE,4DAA4D,2BAA2B,kCAAkC;SACnI,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,IAAI,CAAC;YACH,cAAc,GAAG,mBAAmB,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;YACtE,0BAA0B,GAAG,cAAc,CAAC,wBAAwB,CAAC;YACrE,mBAAmB,GAAG,cAAc,CAAC,gBAAgB,CAAC,WAAW,EAAE,iBAAiB,IAAI,IAAI,CAAC;YAC7F,MAAM,aAAa,GAAG,yBAAyB,CAAC,cAAc,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAC9E,2BAA2B,GAAG,aAAa,IAAI,YAAY,CAAC;QAC9D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,oCAAoC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAED,qEAAqE;IACrE,IAAI,cAAc,EAAE,CAAC;QACnB,cAAc,GAAG,MAAM,oBAAoB,CAAC,cAAc,CAAC,oBAAoB,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACjG,CAAC;IAED,OAAO,QAAQ,EAAE,CAAC;IAElB,SAAS,QAAQ;QACf,OAAO;YACL,KAAK,EAAE,gBAAgB,IAAI,2BAA2B,IAAI,cAAc;YACxE,gBAAgB;YAChB,2BAA2B;YAC3B,cAAc;YACd,0BAA0B;YAC1B,mBAAmB;YACnB,MAAM;SACP,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,yBAAyB,CAChC,EAAkB,EAClB,IAAkC,EAClC,MAAoC;IAEpC,IAAI,EAAE,GAAG,IAAI,CAAC;IAEd,2BAA2B;IAC3B,MAAM,qBAAqB,GAAG,IAAI,CAAC,qBAAqB,IAAI,CAAC,CAAC;IAC9D,IAAI,EAAE,CAAC,kBAAkB,GAAG,qBAAqB,EAAE,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC;YACV,OAAO,EAAE,sBAAsB,EAAE,CAAC,kBAAkB,kBAAkB,qBAAqB,6BAA6B;SACzH,CAAC,CAAC;QACH,EAAE,GAAG,KAAK,CAAC;IACb,CAAC;IAED,mEAAmE;IACnE,MAAM,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,IAAI,kCAAkC,CAAC;IACrF,IAAI,EAAE,CAAC,wBAAwB,GAAG,gBAAgB,EAAE,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC;YACV,OAAO,EAAE,4BAA4B,EAAE,CAAC,wBAAwB,kBAAkB,gBAAgB,8EAA8E;SACjL,CAAC,CAAC;QACH,EAAE,GAAG,KAAK,CAAC;IACb,CAAC;IAED,gEAAgE;IAChE,2DAA2D;IAC3D,6DAA6D;IAC7D,gEAAgE;IAChE,MAAM,SAAS,GAAG,IAAI,CAAC,0BAA0B,IAAI,CAAC,4BAA4B,CAAC,CAAC;IACpF,MAAM,GAAG,GAAG,EAAE,CAAC,gBAAgB,CAAC,WAAW,CAAC;IAC5C,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,CAAC,IAAI,CAAC;YACV,OAAO,EAAE,wEAAwE;SAClF,CAAC,CAAC;QACH,EAAE,GAAG,KAAK,CAAC;IACb,CAAC;SAAM,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC9E,MAAM,CAAC,IAAI,CAAC;YACV,OAAO,EAAE,qBAAqB,GAAG,CAAC,iBAAiB,sBAAsB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;SACjG,CAAC,CAAC;QACH,EAAE,GAAG,KAAK,CAAC;IACb,CAAC;IAED,gEAAgE;IAChE,0DAA0D;IAC1D,gEAAgE;IAChE,kEAAkE;IAClE,mEAAmE;IACnE,qEAAqE;IACrE,gEAAgE;IAChE,MAAM,aAAa,GAAG,IAAI,CAAC,gCAAgC,CAAC;IAC5D,MAAM,WAAW,GACf,EAAE,CAAC,gBAAgB,CAAC,wBAAwB,IAAI,EAAE,CAAC,gBAAgB,CAAC,wBAAwB,CAAC;IAC/F,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,CAAC,IAAI,CAAC;YACV,OAAO,EACL,oHAAoH;SACvH,CAAC,CAAC;QACH,EAAE,GAAG,KAAK,CAAC;IACb,CAAC;SAAM,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,aAAa,CAAC,EAAE,CAAC;QAChD,MAAM,CAAC,IAAI,CAAC;YACV,OAAO,EAAE,qEAAqE,WAAW,CAAC,MAAM,aAAa,aAAa,CAAC,MAAM,aAAa;SAC/I,CAAC,CAAC;QACH,EAAE,GAAG,KAAK,CAAC;IACb,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,oBAAoB,CACjC,SAAqB,EACrB,IAAkC,EAClC,MAAoC;IAEpC,IACE,OAAO,IAAI,CAAC,4BAA4B,KAAK,QAAQ;QACrD,IAAI,CAAC,4BAA4B,CAAC,MAAM,KAAK,CAAC,EAC9C,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,2DAA2D,EAAE,CAAC,CAAC;QACtF,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,IAAI,CAAC,iBAAiB,KAAK,QAAQ,IAAI,IAAI,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtF,MAAM,CAAC,IAAI,CAAC;YACV,OAAO,EAAE,kFAAkF;SAC5F,CAAC,CAAC;QACH,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,IAAI,CAAC,gBAAgB,KAAK,QAAQ,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpF,MAAM,CAAC,IAAI,CAAC;YACV,OAAO,EAAE,iFAAiF;SAC3F,CAAC,CAAC;QACH,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,IAAI,CAAC,kBAAkB,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC7F,MAAM,CAAC,IAAI,CAAC;YACV,OAAO,EAAE,mFAAmF;SAC7F,CAAC,CAAC;QACH,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,aAAa,GAAG,6BAA6B,CAAC;QAClD,WAAW,EAAE,IAAI,CAAC,kBAAkB;QACpC,SAAS,EAAE,IAAI,CAAC,gBAAgB;QAChC,mBAAmB,EAAE,IAAI,CAAC,4BAA4B,CAAC,WAAW,EAAE;QACpE,UAAU,EAAE,IAAI,CAAC,iBAAiB;KACnC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;IAC3E,IAAI,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAE7C,MAAM,CAAC,IAAI,CAAC;QACV,OAAO,EACL,6KAA6K;KAChL,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,wEAAwE;AAExE,iDAAiD;AACjD,MAAM,qBAAqB,GAAG,WAAW,CAAC;AAO1C;;;;;;;;;GASG;AACH,KAAK,UAAU,WAAW,CAAC,KAK1B;IACC,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAE5D,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,oCAAoC,EAAE,CAAC;IACxE,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,gBAAgB,CAAC;QACxC,YAAY,EAAE,CAAC,IAAI,EAAE,GAAG,aAAa,EAAE,GAAG,WAAW,CAAC;KACvD,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAExC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;IAC1C,MAAM,kBAAkB,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,CAAC;IACzD,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,gDAAgD,EAAE,CAAC;IACpF,CAAC;IACD,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACrD,MAAM,aAAa,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAC9C,OAAO,CAAC,WAAW,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CACnD,CAAC;IACF,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,MAAM,EACJ,wGAAwG;SAC3G,CAAC;IACJ,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACvB,IAAI,OAAO,GAAG,IAAI,CAAC,SAAS,IAAI,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxD,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,0BAA0B,CAAC,sCAAsC,OAAO,CAAC,WAAW,EAAE,EAAE;aACjG,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC;QACvB,IAAI,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,0BAA0B,CAAC,8DAA8D;aAClG,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;QAC7D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAChF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,0BAA0B,CAAC,yDAAyD;aAC7F,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACvC,CAAC;AAED,SAAS,aAAa,CAAC,IAA0B;IAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAiC,qBAAqB,CAAC,CAAC;IACrF,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,OAAO,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,6BAA6B,CAAC,KAKtC;IACC,OAAO,CACL,kBAAkB,KAAK,CAAC,WAAW,EAAE;QACrC,gBAAgB,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE;QACnD,0BAA0B,gBAAgB,CAAC,KAAK,CAAC,mBAAmB,CAAC,EAAE;QACvE,iBAAiB,gBAAgB,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE;QACrD,gCAAgC;QAChC,iBAAiB,CAClB,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,CAAS;IACjC,IAAI,GAAG,GAAG,GAAG,CAAC;IACd,KAAK,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;QACnB,MAAM,IAAI,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC;QAChC,IAAI,EAAE,KAAK,GAAG;YAAE,GAAG,IAAI,KAAK,CAAC;aACxB,IAAI,EAAE,KAAK,IAAI;YAAE,GAAG,IAAI,MAAM,CAAC;aAC/B,IAAI,EAAE,KAAK,IAAI;YAAE,GAAG,IAAI,KAAK,CAAC;aAC9B,IAAI,EAAE,KAAK,IAAI;YAAE,GAAG,IAAI,KAAK,CAAC;aAC9B,IAAI,EAAE,KAAK,IAAI;YAAE,GAAG,IAAI,KAAK,CAAC;aAC9B,IAAI,IAAI,GAAG,IAAI;YAAE,GAAG,IAAI,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;;YACnE,GAAG,IAAI,EAAE,CAAC;IACjB,CAAC;IACD,GAAG,IAAI,GAAG,CAAC;IACX,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,IAAgB;IACzC,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAoB,CAAC,CAAC;IACnF,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,OAAO,CAAC,CAAa,EAAE,CAAa;IAC3C,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;IACnE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,KAAiB;IACtC,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAChB,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,IAAI,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACpD,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,IAAI,GAAG,KAAK,CAAC;QAAE,GAAG,IAAI,IAAI,CAAC;SACtB,IAAI,GAAG,KAAK,CAAC;QAAE,GAAG,IAAI,GAAG,CAAC;SAC1B,IAAI,GAAG,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACtE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,SAAS,CAAC,GAAY;IAC7B,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC"}
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "@motebit/crypto-android-keystore",
3
+ "version": "1.1.0",
4
+ "description": "Apache-2.0 verifier for Android Hardware-Backed Keystore Attestation hardware-attestation credentials — offline X.509 chain verification against pinned Google Hardware Attestation roots (RSA-4096 + ECDSA P-384), plus ASN.1 extraction of the KeyDescription extension. Plugs into @motebit/crypto's HardwareAttestationVerifiers dispatcher to validate Android device-attested motebit identities.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist/**/*.js",
16
+ "dist/**/*.js.map",
17
+ "dist/**/*.d.ts",
18
+ "dist/**/*.d.ts.map",
19
+ "LICENSE",
20
+ "NOTICE",
21
+ "README.md"
22
+ ],
23
+ "sideEffects": false,
24
+ "license": "Apache-2.0",
25
+ "keywords": [
26
+ "motebit",
27
+ "android",
28
+ "keystore",
29
+ "key-attestation",
30
+ "hardware-attestation",
31
+ "attestation",
32
+ "trusted-environment",
33
+ "strongbox",
34
+ "x509",
35
+ "verify"
36
+ ],
37
+ "homepage": "https://github.com/motebit/motebit/tree/main/packages/crypto-android-keystore#readme",
38
+ "bugs": {
39
+ "url": "https://github.com/motebit/motebit/issues"
40
+ },
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/motebit/motebit",
44
+ "directory": "packages/crypto-android-keystore"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "motebit": {
50
+ "implements": [
51
+ "spec/credential-v1.md"
52
+ ]
53
+ },
54
+ "dependencies": {
55
+ "@peculiar/asn1-schema": "^2.6.0",
56
+ "@peculiar/x509": "^1.12.0",
57
+ "@motebit/protocol": "1.1.0",
58
+ "@motebit/crypto": "1.1.0"
59
+ },
60
+ "devDependencies": {
61
+ "@noble/curves": "~1.9.0",
62
+ "@noble/hashes": "~1.6.0",
63
+ "@peculiar/webcrypto": "^1.5.0",
64
+ "@types/node": "^22.0.0",
65
+ "typescript": "^5.6.0",
66
+ "vitest": "^2.1.0"
67
+ },
68
+ "engines": {
69
+ "node": ">=20"
70
+ },
71
+ "scripts": {
72
+ "build": "tsc -b",
73
+ "test": "vitest run",
74
+ "test:coverage": "vitest run --coverage",
75
+ "typecheck": "tsc --noEmit",
76
+ "lint": "eslint --parser-options=project:tsconfig.eslint.json src/",
77
+ "lint:pack": "publint --strict && attw --pack --profile esm-only",
78
+ "clean": "rm -rf dist .turbo *.tsbuildinfo"
79
+ }
80
+ }