Skip to content

Library for dealing with HQSL data, creation and verification thereof.

License

Notifications You must be signed in to change notification settings

hamlog-online/hqsl-ts

Repository files navigation

HQSL parser and verifier in TypeScript

See HQSL.net for detailed information on what an HQSL is and why would one want to use this.

This is a TypeScript library for parsing, signing, verifying and creating HQSL cards, as used in the HQSL.net card verifier and on Hamlog.Online, meant for web use, WebView-based mobile apps, and Node.js.

Usage

npm install hqsl-ts

If you're using TypeScript, you might want to use the TypeScript source code directly instead of the compiled versions:

// tsconfig.json
...
    "paths": {
      "hqsl-ts": ["./node_modules/hqsl-ts/src"],
    }
...

Using this library without a bundler or from a CDN is not currently supported, due to the dependencies involved introducing a significant number of hoops that need jumping. (Pull requests rectifying this situation are welcome.) Since it is assumed you're using a bundler, no pre-minified versions are included. You can still load, e.g. openpgpjs from CDN, by adding it as an external dependency and using https://cdn.jsdelivr.net/npm/openpgp@5.11.1/dist/openpgp.min.mjs for the URL.

Examples

Refer to API documentation for full details. Here are some brief examples:

Creating a card from ADIF

import { HQSL } from "hqsl-ts";

const adif = `
ADIF export from CQRLOG for Linux version 2.5.2, slightly edited.

<ADIF_VER:5>3.1.0
<CREATED_TIMESTAMP:15>20240416 114238
<PROGRAMID:6>CQRLOG
<PROGRAMVERSION:11>2.5.2 (001)
<EOH>
<QSO_DATE:8>20210924<TIME_ON:4>1038<TIME_OFF:4>1039<STATION_CALLSIGN:5>AC1PZ<CALL:6>EA2ESN<MODE:3>FT8<FREQ:7>28.0759<BAND:3>10M<RST_SENT:3>-06<RST_RCVD:3>-13<QSL_SENT:1>N
<QSL_RCVD:1>N<GRIDSQUARE:6>IN91dv<MY_GRIDSQUARE:6>FN42gv<TX_PWR:2>20
<EOR>`; 

// This parses the ADIF string and supplies defaults for fields not necessarily included.
const hqsl = HQSL.fromADIF(adif, "AC1PZ", "FN42");
// The result is every QSO in the ADIF string transformed into an HQSL object:
console.log(hqsl[0].toString());

Creating a card from scratch and signing it

import { HQSL, HQSLOpenPGP } from "hqsl-ts";
import { UTCDateMini } from "@date-fns/utc";

const secretKey = `
-----BEGIN PGP PRIVATE KEY BLOCK-----

lFgEZcSkgRYJKwYBBAHaRw8BAQdA2HVnF04A6dQuF2ID5hh5W7KHRCllqZQHn9kF
...
=crTM
-----END PGP PRIVATE KEY BLOCK-----`;

// Here we are creating a card by manually supplying the required data.
const card = new HQSL({
    from: "AC1PZ",
    to: "W1KOT",
    freq: 14.074,
    where: "FN42",
    signal: "+00",
    mode: "FT8",
    when: new UTCDateMini(2022, 2, 13, 16, 10),
});

(async () => {
    // This sets up the signer. Since we're not verifying anything,
    // we don't need to supply trusted certifier keys.
    const client = await HQSLOpenPGP.setup([]);
    // Actually sign the card.
    await client.sign(card, signingKey);
    // The result is a signed card body, and we point it at the HQSL.net verifier
    // by attaching the URL header.
    console.log(`https://hqsl.net/h#${card.toString()}`);

    // If you need to generate a QR code in the browser or in Node.js,
    // the recommended library is
    // tiny-qrcode-svg (https://github.com/withaspoon/tiny-qrcode-svg)
    // because it handles the optimized multi-block QR codes automatically.
})();

Verifying a card

import { HQSL, HQSLOpenPGP, HQSLState } from "hqsl-ts";

const trustedKey = `
-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEZbigARYJKwYBBAHaRw8BAQdAJNNtGMTfd6lLFQDhf1Rh2DDqACwQyd1VTF2R
...
=D6ih
-----END PGP PUBLIC KEY BLOCK-----
`;
const card = "https://hqsl.net/h#AC1PZ,FN42gv,W1KOT," +
             "202402081323,+00,18.101,FT8,59_05,," + 
             "19H4V9DABY5VH3WE05MV34Z5JBEBJRD9Q7V" + 
             "TLB98L789GFL79P56QWFX0JHV3U6VSEXROD" + 
             "MYLOZ40UM798EV4FSPVY8YVMQ0WLZA66Q38" + 
             "VW0G6PV23O6Y65PK94NZE5B381MHOPR4NJJ" +
             "U67QC25JW85JL23V644BLP0HD8KBY2MODEBRICTZ5C0LC";

(async () => {
    // This gets you a parsed card object.
    const hqsl = HQSL.fromString(card);

    // At this point, you can already access properties on the object, if it got parsed correctly.
    // If it didn't, the fromString method will throw an error.
    
    // This sets up the verifier and feeds it the certifier key we trust.
    const client = await HQSLOpenPGP.setup([trustedKey]);

    // This actually adds the verification verdict to the card object.
    await client.verify(hqsl);

    // If the card is completely legit, this will print 'true'!
    console.log(hqsl.verification.verdict == HQSLState.Valid)

})();

Tooling

  • npm run build to build for consumption. This will also build API documentation.
  • npm run test to run unit tests.
  • npm run doc to generate API documentation.

License

This library is released under the terms of MIT license. See LICENSE.