### GET /openpgpkey/{email_address} Source: https://github.com/jonatanmgit/wkd-checker/blob/main/draft-koch-openpgp-webkey-service-21.txt Retrieves the OpenPGP key for a given email address. The key must have a User ID packet matching the email address. The server may return revoked or expired keys. ```APIDOC ## GET /openpgpkey/{email_address} ### Description Retrieves the OpenPGP key for a given email address. The key must have a User ID packet matching the email address. The server may return revoked or expired keys. ### Method GET ### Endpoint /openpgpkey/{email_address} ### Parameters #### Path Parameters - **email_address** (string) - Required - The email address for which to retrieve the OpenPGP key. #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **key_block** (string) - The OpenPGP key block in octet-stream format. #### Response Example ``` -----BEGIN PGP PUBLIC KEY BLOCK----- ... -----END PGP PUBLIC KEY BLOCK----- ``` ``` -------------------------------- ### Define KeyCheckResult Interface and Example Usage (TypeScript) Source: https://context7.com/jonatanmgit/wkd-checker/llms.txt Defines the KeyCheckResult interface for WKD lookup results, including policy status, key availability, validation, and metadata. Includes an example function `comprehensiveCheck` that performs a full WKD validation for an email address and returns the key fingerprint. ```typescript import { checkKey, KeyCheckResult, KeyType, PolicyFlags } from 'wkd-checker'; // KeyCheckResult structure interface KeyCheckResult { policy_location: string; // URL of the policy file policyAvailable: boolean; // Whether policy file exists policyCorsValid: boolean; // Whether CORS headers are set correctly policy: PolicyFlags | null; // Parsed policy flags key_location: string | null; // URL where key was found key_available: boolean; // Whether key exists keyCorsValid: boolean; // Whether key endpoint has CORS keyType: KeyType; // 'BinaryKey', 'ArmoredKey', or 'Invalid' keyTypeValid: boolean; // True only if BinaryKey (per WKD spec) fingerprint: string | null; // Key fingerprint in uppercase emailInKey: boolean; // Whether email matches key User ID expired: boolean; // Whether key is expired revoked: boolean; // Whether key is revoked policyCompliant: boolean; // Whether key complies with policy valid: boolean; // Overall validity } // PolicyFlags structure interface PolicyFlags { mailboxOnly: boolean; // Key must contain only email, no name daneOnly: boolean; // DANE must be used authSubmit: boolean; // Authenticated submission required protocolVersion: number | null; submissionAddress: string | null; others: Array<{ key: string, value: string | null }>; } // KeyType enum enum KeyType { Invalid = 'Invalid', BinaryKey = 'BinaryKey', // Valid per WKD spec ArmoredKey = 'ArmoredKey', // Invalid per WKD spec (but parseable) } // Example: Comprehensive validation async function comprehensiveCheck(email: string) { const result = await checkKey(email); // Determine best result const best = result.advanced.valid ? result.advanced : result.direct.valid ? result.direct : null; if (!best) { console.log('No valid WKD configuration found'); console.log('Direct issues:', !result.direct.policyAvailable ? 'No policy' : !result.direct.key_available ? 'No key' : !result.direct.keyTypeValid ? 'Wrong key format' : !result.direct.emailInKey ? 'Email mismatch' : 'Unknown'); return null; } // Warn about potential issues even if valid if (best.expired) console.warn('Warning: Key is expired'); if (best.revoked) console.warn('Warning: Key is revoked'); if (!best.keyCorsValid) console.warn('Warning: CORS not configured'); return best.fingerprint; } ``` -------------------------------- ### Validate WKD Setup for an Email Address with Node.js Source: https://context7.com/jonatanmgit/wkd-checker/llms.txt The `checkKey` function validates the Web Key Directory (WKD) setup for a given email address using both Advanced and Direct lookup methods. It verifies policy availability, CORS headers, key format (binary), expiration, revocation status, and User ID matching. The function returns detailed results for each method. ```javascript const { checkKey } = require('wkd-checker'); async function validateWKD() { try { const result = await checkKey('user@example.com'); // Check if either method returned a valid key const isValid = result.direct.valid || result.advanced.valid; console.log('WKD Valid:', isValid); // Inspect Direct method results console.log('Direct Method:'); console.log(' Valid:', result.direct.valid); console.log(' Policy URL:', result.direct.policy_location); console.log(' Policy Available:', result.direct.policyAvailable); console.log(' Policy CORS Valid:', result.direct.policyCorsValid); console.log(' Key URL:', result.direct.key_location); console.log(' Key Available:', result.direct.key_available); console.log(' Key CORS Valid:', result.direct.keyCorsValid); console.log(' Key Type:', result.direct.keyType); // 'BinaryKey', 'ArmoredKey', or 'Invalid' console.log(' Key Type Valid:', result.direct.keyTypeValid); // Must be BinaryKey per spec console.log(' Fingerprint:', result.direct.fingerprint); console.log(' Email in Key:', result.direct.emailInKey); console.log(' Expired:', result.direct.expired); console.log(' Revoked:', result.direct.revoked); console.log(' Policy Compliant:', result.direct.policyCompliant); // Inspect Advanced method results console.log('Advanced Method:'); console.log(' Valid:', result.advanced.valid); console.log(' Fingerprint:', result.advanced.fingerprint); // Check policy flags if available if (result.direct.policy) { console.log('Policy Flags:'); console.log(' mailbox-only:', result.direct.policy.mailboxOnly); console.log(' dane-only:', result.direct.policy.daneOnly); console.log(' auth-submit:', result.direct.policy.authSubmit); console.log(' protocol-version:', result.direct.policy.protocolVersion); console.log(' submission-address:', result.direct.policy.submissionAddress); } } catch (error) { console.error('Error checking WKD:', error.message); } } validateWKD(); ``` -------------------------------- ### Retrieve Raw Public Key Data using JavaScript Source: https://context7.com/jonatanmgit/wkd-checker/llms.txt The `getKey` function retrieves the raw OpenPGP public key data for a given email address. It supports both Advanced and Direct methods, returning the key as a Uint8Array. The example demonstrates parsing the key using the 'openpgp' library and accessing its properties. ```javascript const { getKey } = require('wkd-checker'); const { readKey } = require('openpgp'); async function retrieveKey() { try { // Retrieve the raw key data const keyData = await getKey('user@example.com'); console.log('Key retrieved, size:', keyData.length, 'bytes'); // Parse the key using openpgp library const key = await readKey({ binaryKey: keyData }); // Access key information console.log('Fingerprint:', key.getFingerprint().toUpperCase()); console.log('User IDs:', await key.getUserIDs()); console.log('Creation Time:', key.getCreationTime()); const expirationTime = await key.getExpirationTime(); console.log('Expiration:', expirationTime === Infinity ? 'Never' : expirationTime); console.log('Is Revoked:', await key.isRevoked()); // Get armor format for display or storage const armoredKey = key.armor(); console.log('Armored Key:\n', armoredKey); } catch (error) { if (error.message === 'No keys found') { console.log('No WKD key found for this email address'); } else if (error.message === 'Invalid e-mail address.') { console.log('Invalid email format provided'); } else { console.error('Error:', error.message); } } } retrieveKey(); ``` -------------------------------- ### Key Discovery - Direct Method Source: https://github.com/jonatanmgit/wkd-checker/blob/main/draft-koch-openpgp-webkey-service-21.txt This endpoint retrieves an OpenPGP public key using the direct method. This method is a fallback if the advanced method's subdomain does not exist and does not require additional DNS entries. ```APIDOC ## GET /.well-known/openpgpkey/hu/ ### Description Retrieves an OpenPGP public key using the direct method. This is a fallback method that does not require a dedicated subdomain. ### Method GET ### Endpoint `https:///.well-known/openpgpkey/hu/?l=` ### Parameters #### Path Parameters - **domain-part** (string) - Required - The domain part of the email address. - **sha1-zbase32-hash** (string) - Required - The 32-octet Z-Base-32 encoded SHA-1 hash of the User ID (local-part mapped to lowercase, non-ASCII unchanged). #### Query Parameters - **l** (string) - Required - The original, percent-escaped local-part of the email address. ### Request Example ``` GET https://example.org/.well-known/openpgpkey/hu/iy9q119eutrkn8s1mk4r39qejnbu3n5q?l=Joe.Doe ``` ### Response #### Success Response (200) - **binary** (binary) - The binary representation of the OpenPGP public key. ``` -------------------------------- ### Key Discovery - Advanced Method Source: https://github.com/jonatanmgit/wkd-checker/blob/main/draft-koch-openpgp-webkey-service-21.txt This endpoint retrieves an OpenPGP public key using the advanced method, which involves a specific subdomain and path structure. Implementations must try this method first. ```APIDOC ## GET /.well-known/openpgpkey/ ### Description Retrieves an OpenPGP public key using the advanced method. This method requires a specific subdomain (`openpgpkey`) and a structured path. ### Method GET ### Endpoint `https://openpgpkey./.well-known/openpgpkey//hu/?l=` ### Parameters #### Path Parameters - **domain-part** (string) - Required - The domain part of the email address. - **sha1-zbase32-hash** (string) - Required - The 32-octet Z-Base-32 encoded SHA-1 hash of the User ID (local-part mapped to lowercase, non-ASCII unchanged). #### Query Parameters - **l** (string) - Required - The original, percent-escaped local-part of the email address. ### Request Example ``` GET https://openpgpkey.example.org/.well-known/openpgpkey/example.org/hu/iy9q119eutrkn8s1mk4r39qejnbu3n5q?l=Joe.Doe ``` ### Response #### Success Response (200) - **binary** (binary) - The binary representation of the OpenPGP public key. ``` -------------------------------- ### Web Key Directory Update Protocol Source: https://github.com/jonatanmgit/wkd-checker/blob/main/draft-koch-openpgp-webkey-service-21.txt This section outlines the protocol for submitting and publishing OpenPGP keys to a Web Key Directory using email. ```APIDOC ## Web Key Directory Update Protocol ### Description This protocol automates the task of putting keys into the key directory. It is based on email and assumes a mail provider can securely deliver mail to a user's inbox. The process involves several steps to verify key ownership before publication. ### Steps for Key Submission: 1. **Retrieve Submission Address**: Fetch the `submission-address` file from the provider's WELLKNOWN URI. * **URI**: `WELLKNOWN/submission-address` * **Content**: A single line containing the submission email address. 2. **Send Key**: Send the target key using SMTP (or other transport) to the submission address in PGP/MIME format. 3. **Provider Verification**: The provider checks if the received key's User ID matches an account name. 4. **Nonce Verification**: The provider sends an encrypted message with a nonce and key fingerprint to the user's email account. 5. **User Decryption**: The user decrypts the message using their private key. 6. **Confirmation**: The user sends the decrypted nonce back to the submission address, encrypted with the provider's public key. 7. **Publication**: The provider verifies the nonce, publishes the key, and notifies the user. ### Example Submission Address File Content: ``` key-submission-example.org@directory.example.org ``` ```