Skip to content

nqcard(3)

nqcard, nqcardvrfy — make and check an identity card for a signing key

libnoqtis, -lnoqtis

#include <noqtis.h>

int
nqcard(nqsalg alg, const uint8_t *sk, size_t sklen, const uint8_t *pk, size_t pklen, const char *name, const char *orcid, const char *email, const char *url, const char *affil, int64_t created, char *out, size_t cap, size_t *outlen);

int
nqcardvrfy(const char *card, size_t n, const uint8_t *pk, size_t pklen, nqcardf *f);

() writes to out, of cap bytes, an identity card (‘noqtis-idcard-1, noqtis-capsule(5)’) in canonical JSON: the public key pk of alg with name and, when not NULL, orcid, email, url and affil, made at created (seconds since 1970-01-01T00:00:00Z) and signed by sk under the context ‘noqtis-idcard-1’. *outlen gets the card's size, also when cap is too small. The signature is verified before the card is written.

The fields, in bytes: name and affil are 1 to 255 bytes of UTF-8 with no control character (C0, DEL or C1) and no space at either end; orcid is an ORCID iD, ‘0000-0002-1825-0097’, or its ‘https://orcid.org/’ address, whose last character is its ISO 7064 MOD 11-2 check digit (‘X for 10’), a lower-case ‘x’ taken as ‘X’; the card holds the bare iD. email is ‘local@domain.tld’, at most NQCARDEMAIL (254) bytes; url an ‘https://’ address with a host, at most NQCARDURL (1024) bytes; neither has a space or a control character. The arguments and fields are checked before the algorithm, so a call refused for a field returns NQEARG whatever alg is.

() checks the n bytes at card (at most NQCARDMAX, 256 KiB): it must be a ‘noqtis-idcard-1’ card in canonical form, with exactly its members, fields within the limits above (the ORCID iD bare, its check digit right), a post-quantum algorithm, a key and a signature of that algorithm's sizes, and a signature that verifies under the key it carries with the context ‘noqtis-idcard-1’. With pk not NULL, the card's key must also be pk, of pklen bytes. On success *f gets the card:

typedef struct {
  nqsalg alg;
  uint8_t pk[NQCARDPK];   /* the card's public key, pklen bytes */
  size_t pklen;
  uint8_t fp[32];         /* its SHA-256 (nqinsp's info.key) */
  int64_t created;        /* seconds since 1970, UTC */
  char utc[21];           /* the same, YYYY-MM-DDTHH:MM:SSZ */
  char name[256];
  char orcid[20];         /* "" for a field the card has not */
  char email[NQCARDEMAIL + 1];
  char url[NQCARDURL + 1];
  char affil[256];
} nqcardf;

On any other result *f is zeroed. A card is self-signed: a card that verifies was written by whoever holds its key and is unchanged, which does not make the name true; compare fp with the one its holder published, or pin pk.

The card was written, or it verifies.
[NQEBUF]
cap is too small.
[NQENOSUP]
nqcard(): the algorithm is not a post-quantum signature (Ed25519 alone).
[NQEARG]
A NULL argument, a field out of its limits, keys of the wrong sizes or not a pair, or created before 1970 or after 9999.
[NQEVRFY]
nqcardvrfy(): the signature does not verify, or the card is not for pk.
[NQEDEC]
nqcardvrfy(): not a card as above.
[NQELIM]
nqcardvrfy(): more than NQCARDMAX bytes.
[NQEMEM]
The allocation hook returned NULL.

noqtis-check(1), noqtis-idcard(1), nqinsp(3), nqkstmt(3), noqtis-capsule(5)