// OpenPGP mail and files: a key pair made, a message encrypted to it, text signed in the clear, a
// detached signature, and a signature from the OpenPGP specification itself checked.
//
//   quillo run openpgp.qwe      then open http://localhost:8080/key, /secret, /signed, /detached, /sealed, /password, /standard and /refused
//
// openpgp_rfc9580_cert.asc and openpgp_rfc9580_signed.asc are RFC 9580's sample certificate and a
// message signed with it, from another implementation's hand. The keys here live as long as the
// program runs: a real one keeps `private` somewhere safe and shares `public`.

use "openpgp.qwer"

let ADA = openpgp_generate("Ada Lovelace <ada@example.com>", "correct horse")
let BOB = openpgp_generate("Bob <bob@example.com>", "")

route GET /key {
    let info = openpgp_key_info(ADA?.public)?
    {
        users: info.users, version: info.version, algorithm: info.algorithm, private: info.private,
        subkeys: info.subkeys | map((s) => { algorithm: s.algorithm, can_encrypt: s.can_encrypt }),
        same_print: info.fingerprint == ADA?.fingerprint, id_len: len(ADA?.key_id),
        private_info: openpgp_key_info(ADA?.private)?.private,
        derived: openpgp_key_info(openpgp_public_of(ADA?.private)?)?.fingerprint == ADA?.fingerprint,
    }
}

route GET /secret {
    let box = openpgp_encrypt("Meet at dawn. Ünïcödé too.", [ADA?.public, BOB?.public])?
    {
        armored: slice(box, 0, 27), kind: openpgp_inspect(box)?.type,
        ada: openpgp_decrypt(box, ADA?.private, "correct horse")?,
        bob: openpgp_decrypt(box, BOB?.private, "")?,
        wrong_pass: openpgp_decrypt(box, ADA?.private, "battery staple").error != null,
    }
}

route GET /signed {
    let s = openpgp_sign("I owe Bob 10 euros.\nSigned today.", ADA?.private, "correct horse")?
    {
        kind: openpgp_inspect(s)?.type,
        good: openpgp_verify(s, ADA?.public)?.text,
        signer_ok: openpgp_verify(s, ADA?.public)?.signer == ADA?.fingerprint,
        changed: openpgp_verify(replace(s, "10 euros", "99 euros"), ADA?.public).error,
        other_key: openpgp_verify(s, BOB?.public).error,
    }
}

route GET /detached {
    let sig = openpgp_sign_detached("release-1.2.3.tar.gz contents", BOB?.private, "")?
    {
        kind: openpgp_inspect(sig)?.type,
        good: openpgp_verify_detached("release-1.2.3.tar.gz contents", sig, BOB?.public)? == BOB?.fingerprint,
        changed: openpgp_verify_detached("release-1.2.4.tar.gz contents", sig, BOB?.public).error,
    }
}

route GET /sealed {
    let box = openpgp_encrypt_signed("Only you, and from me.", BOB?.public, ADA?.private, "correct horse")?
    let read = openpgp_decrypt_verify(box, BOB?.private, "", ADA?.public)?
    {
        text: read.text, from_ada: read.signer == ADA?.fingerprint,
        wrong_sender: openpgp_decrypt_verify(box, BOB?.private, "", BOB?.public).error,
    }
}

route GET /password {
    let box = openpgp_encrypt_password("the safe's code", "swordfish")?
    {
        open: openpgp_decrypt_password(box, "swordfish")?,
        wrong: openpgp_decrypt_password(box, "herring").error != null,
        empty: openpgp_encrypt_password("x", "").error,
    }
}

// From RFC 9580, Appendix A: a signature this plugin did not make, on a version 6 key.
route GET /standard {
    let cert = read_file("openpgp_rfc9580_cert.asc")
    let signed = read_file("openpgp_rfc9580_signed.asc")
    let info = openpgp_key_info(cert)?
    {
        fingerprint: info.fingerprint, version: info.version, algorithm: info.algorithm,
        text: openpgp_verify(signed, cert)?.text,
        tampered: openpgp_verify(replace(signed, "hello world", "hello there"), cert).error,
        to_it: len(openpgp_encrypt("to a version 6 key", [cert])?) > 100,
    }
}

route GET /refused = {
    not_key: openpgp_key_info("hello").error != null,
    not_message: openpgp_decrypt("hello", BOB?.private, "").error != null,
    no_user: openpgp_generate(" ", "").error,
    no_keys: openpgp_encrypt("x", []).error,
}
