crossmate

A collaborative crossword app for iOS
Log | Files | Refs | LICENSE

commit e61aa56e05f2da8cb3af1665a7834e78c8783afe
parent a4ecc2c17f7e9bd0cb0c93e3ca346f6c58667d28
Author: Michael Camilleri <[email protected]>
Date:   Fri, 12 Jun 2026 05:44:56 +0900

Remove diagnostic logging in Cloudflare Worker

Diffstat:
MWorkers/push-worker.js | 205-------------------------------------------------------------------------------
1 file changed, 0 insertions(+), 205 deletions(-)

diff --git a/Workers/push-worker.js b/Workers/push-worker.js @@ -128,7 +128,6 @@ export class PushRegistry { // as an ECDSA-SHA256 *message*, so the digest under the signature is // SHA256(nonce). WebCrypto applies that second hash. const assertionNonce = await sha256Bytes(signedBytes); - const keySource = registration.publicKeySPKI ? "spki" : "jwk"; const publicKey = await this.importAppAttestPublicKey(registration); const verified = await crypto.subtle.verify( { name: "ECDSA", hash: "SHA-256" }, @@ -137,104 +136,6 @@ export class PushRegistry { assertionNonce ); if (!verified) { - const diagnostic = { - signatureLength: assertion.signature.length, - authenticatorDataLength: assertion.authenticatorData.length, - clientDataHashLength: clientDataHash.length, - signedBytesLength: signedBytes.length, - keySource, - hasPublicKeySPKI: Boolean(registration.publicKeySPKI), - signCount: authData.signCount, - storedSignCount: registration.signCount || 0, - rawOverDoubleHash: false, - derOverCanonicalHash: false, - rawOverCanonicalString: false, - rawSha384OverCanonicalHash: false, - rawSha512OverCanonicalHash: false, - rawOverPrehashedNonce: false, - rawOverClientDataHashOnly: false, - rawOverAuthenticatorDataOnly: false - }; - try { - diagnostic.rawOverDoubleHash = await crypto.subtle.verify( - { name: "ECDSA", hash: "SHA-256" }, - publicKey, - derECDSASignatureToRaw(assertion.signature), - concatBytes(assertion.authenticatorData, await sha256Bytes(clientDataHash)) - ); - } catch { - diagnostic.rawOverDoubleHash = "error"; - } - try { - diagnostic.derOverCanonicalHash = await crypto.subtle.verify( - { name: "ECDSA", hash: "SHA-256" }, - publicKey, - assertion.signature, - signedBytes - ); - } catch { - diagnostic.derOverCanonicalHash = "error"; - } - try { - diagnostic.rawOverCanonicalString = await crypto.subtle.verify( - { name: "ECDSA", hash: "SHA-256" }, - publicKey, - derECDSASignatureToRaw(assertion.signature), - concatBytes(assertion.authenticatorData, new TextEncoder().encode(canonical)) - ); - } catch { - diagnostic.rawOverCanonicalString = "error"; - } - try { - diagnostic.rawSha384OverCanonicalHash = await crypto.subtle.verify( - { name: "ECDSA", hash: "SHA-384" }, - publicKey, - derECDSASignatureToRaw(assertion.signature), - signedBytes - ); - } catch { - diagnostic.rawSha384OverCanonicalHash = "error"; - } - try { - diagnostic.rawSha512OverCanonicalHash = await crypto.subtle.verify( - { name: "ECDSA", hash: "SHA-512" }, - publicKey, - derECDSASignatureToRaw(assertion.signature), - signedBytes - ); - } catch { - diagnostic.rawSha512OverCanonicalHash = "error"; - } - try { - diagnostic.rawOverPrehashedNonce = verifyP256ECDSADigest( - registration.publicKeyJWK, - derECDSASignatureToRaw(assertion.signature), - await sha256Bytes(signedBytes) - ); - } catch { - diagnostic.rawOverPrehashedNonce = "error"; - } - try { - diagnostic.rawOverClientDataHashOnly = await crypto.subtle.verify( - { name: "ECDSA", hash: "SHA-256" }, - publicKey, - derECDSASignatureToRaw(assertion.signature), - clientDataHash - ); - } catch { - diagnostic.rawOverClientDataHashOnly = "error"; - } - try { - diagnostic.rawOverAuthenticatorDataOnly = await crypto.subtle.verify( - { name: "ECDSA", hash: "SHA-256" }, - publicKey, - derECDSASignatureToRaw(assertion.signature), - assertion.authenticatorData - ); - } catch { - diagnostic.rawOverAuthenticatorDataOnly = "error"; - } - console.warn("App Attest assertion verification failed", diagnostic); return { ok: false, status: 401, message: "Bad App Attest assertion" }; } @@ -1082,112 +983,6 @@ function derIntegerToFixed(bytes, length) { return result; } -const P256 = { - p: 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffffn, - n: 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551n, - a: -3n, - gx: 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296n, - gy: 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5n -}; - -function verifyP256ECDSADigest(publicKeyJWK, rawSignature, digest) { - if (!publicKeyJWK || publicKeyJWK.crv !== "P-256" || rawSignature.length !== 64 || digest.length !== 32) { - return false; - } - const r = bytesToBigInt(rawSignature.slice(0, 32)); - const s = bytesToBigInt(rawSignature.slice(32)); - if (r <= 0n || r >= P256.n || s <= 0n || s >= P256.n) return false; - const q = { - x: bytesToBigInt(base64URLDecode(publicKeyJWK.x)), - y: bytesToBigInt(base64URLDecode(publicKeyJWK.y)) - }; - if (!p256IsOnCurve(q)) return false; - const z = bytesToBigInt(digest) % P256.n; - const w = modInverse(s, P256.n); - const u1 = mod(z * w, P256.n); - const u2 = mod(r * w, P256.n); - const point = p256Add( - p256Multiply({ x: P256.gx, y: P256.gy }, u1), - p256Multiply(q, u2) - ); - return Boolean(point) && mod(point.x, P256.n) === r; -} - -function p256IsOnCurve(point) { - if (!point || point.x < 0n || point.x >= P256.p || point.y < 0n || point.y >= P256.p) { - return false; - } - const left = mod(point.y * point.y, P256.p); - const right = mod(point.x * point.x * point.x + P256.a * point.x + p256B(), P256.p); - return left === right; -} - -function p256B() { - return 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604bn; -} - -function p256Add(left, right) { - if (!left) return right; - if (!right) return left; - if (left.x === right.x) { - if (mod(left.y + right.y, P256.p) === 0n) return null; - return p256Double(left); - } - const slope = mod((right.y - left.y) * modInverse(right.x - left.x, P256.p), P256.p); - const x = mod(slope * slope - left.x - right.x, P256.p); - const y = mod(slope * (left.x - x) - left.y, P256.p); - return { x, y }; -} - -function p256Double(point) { - if (!point || point.y === 0n) return null; - const slope = mod((3n * point.x * point.x + P256.a) * modInverse(2n * point.y, P256.p), P256.p); - const x = mod(slope * slope - 2n * point.x, P256.p); - const y = mod(slope * (point.x - x) - point.y, P256.p); - return { x, y }; -} - -function p256Multiply(point, scalar) { - let result = null; - let addend = point; - let value = scalar; - while (value > 0n) { - if ((value & 1n) === 1n) result = p256Add(result, addend); - addend = p256Double(addend); - value >>= 1n; - } - return result; -} - -function mod(value, modulus) { - const result = value % modulus; - return result >= 0n ? result : result + modulus; -} - -function modInverse(value, modulus) { - let low = mod(value, modulus); - let high = modulus; - let lowCoefficient = 1n; - let highCoefficient = 0n; - while (low > 1n) { - const ratio = high / low; - [low, high] = [high - low * ratio, low]; - [lowCoefficient, highCoefficient] = [ - highCoefficient - lowCoefficient * ratio, - lowCoefficient - ]; - } - return mod(lowCoefficient, modulus); -} - -function bytesToBigInt(bytes) { - let value = 0n; - for (const byte of bytes) { - value = (value << 8n) + BigInt(byte); - } - return value; -} - async function signProviderJWT({ keyPEM, keyID, teamID, issuedAt }) { if (!keyPEM || !keyID || !teamID) { throw new Error("APNS_KEY, APNS_KEY_ID, APNS_TEAM_ID must all be set");