Skip to content

Key Management

Keys live in two sets: current (what’s on the tag now) and target (what you want after changeKeys()). A key config is { masterKey, diversify, systemIdentifier?, applicationId?, keyVersion? }keyVersion applies to target keys. When diversify is true, the effective key is derived per-tag from the master key + UID (AN10922); setSystemIdentifier / setApplicationId set the global diversification inputs.

Typical key-change flow: load the current keys (so the tag can authenticate), set the target keys, then changeKeys().

Loading Key Sets

loadKeyConfig(config)

Load a complete configuration in one call. config.currentKeys is { keyNo: { masterKey, diversify, ... } }, config.targetKeys is { keyNo: { masterKey, diversify, keyVersion, ... } }, and config.systemIdentifier / config.applicationId are optional global inputs.

const res = tag.loadKeyConfig({
currentKeys: { 0: { masterKey: '00000000000000000000000000000000' } },
targetKeys: { 0: { masterKey: 'D3F7A91C5E08B264A1F9C7E03B5D8A42' } },
});

Returns

{
success: true,
data: {
configuration: {
currentKeys: { 0: { masterKey: '00000000000000000000000000000000' } },
targetKeys: { 0: { masterKey: 'D3F7A91C5E08B264A1F9C7E03B5D8A42' } },
systemIdentifier: 'CRYPTAG',
applicationId: '3042F5'
}
}
}

loadFactoryDefaults()

Reset the KeyManager to factory defaults (all keys 00…00). Affects the in-memory key config only, not the tag.

const res = tag.loadFactoryDefaults();

Returns

{
success: true,
data: { message: 'Factory defaults loaded' }
}

Setting Individual Keys

setCurrentKey(keyNo, config)

Set a single current key (what the tag holds, used to authenticate). keyNo is 0–4; config is { masterKey, diversify, ... }.

const res = tag.setCurrentKey(0, { masterKey: '00000000000000000000000000000000' });

Returns

{
success: true,
data: {
keyType: 'current',
keyNo: 0,
configuration: { masterKey: '00000000000000000000000000000000', systemIdentifier: 'CRYPTAG', applicationId: '3042F5' }
}
}

setTargetKey(keyNo, config)

Set a single target key (the desired key after changeKeys()). keyNo is 0–4; config is { masterKey, diversify, keyVersion, ... }.

const res = tag.setTargetKey(1, { masterKey: 'D3F7A91C5E08B264A1F9C7E03B5D8A42', diversify: true });

Returns

{
success: true,
data: {
keyType: 'target',
keyNo: 1,
configuration: { masterKey: 'D3F7A91C5E08B264A1F9C7E03B5D8A42', diversify: true, systemIdentifier: 'CRYPTAG', applicationId: '3042F5' }
}
}

getCurrentKey(keyNo)

The current key in hex (diversified if configured and a UID is cached). Returns the 32-hex string, or null if unset.

tag.getCurrentKey(0);
// → '00000000000000000000000000000000'

getTargetKey(keyNo)

The target key in hex (diversified if configured and a UID is cached). Returns the 32-hex string, or null if unset.

tag.getTargetKey(1);
// → 'D3F7A91C5E08B264A1F9C7E03B5D8A42'

getCurrentKeys()

The full current keys object (all 5 slots).

tag.getCurrentKeys();

Returns

{
0: { type: 'current', masterKey: '00000000000000000000000000000000', diversify: false, systemIdentifier: 'CRYPTAG', applicationId: '3042F5' },
1: { type: 'current', masterKey: '00000000000000000000000000000000', diversify: false, systemIdentifier: 'CRYPTAG', applicationId: '3042F5' },
2: { type: 'current', masterKey: '00000000000000000000000000000000', diversify: false, systemIdentifier: 'CRYPTAG', applicationId: '3042F5' },
3: { type: 'current', masterKey: '00000000000000000000000000000000', diversify: false, systemIdentifier: 'CRYPTAG', applicationId: '3042F5' },
4: { type: 'current', masterKey: '00000000000000000000000000000000', diversify: false, systemIdentifier: 'CRYPTAG', applicationId: '3042F5' }
}

getTargetKeys()

The full target keys object (all 5 slots).

tag.getTargetKeys();

Returns

{
0: { type: 'target', masterKey: 'D3F7A91C5E08B264A1F9C7E03B5D8A42', diversify: false, systemIdentifier: 'CRYPTAG', applicationId: '3042F5', keyVersion: 1 },
1: { type: 'target', masterKey: 'D3F7A91C5E08B264A1F9C7E03B5D8A42', diversify: true, systemIdentifier: 'CRYPTAG', applicationId: '3042F5', keyVersion: 1 },
2: { type: 'target', masterKey: '00000000000000000000000000000000', diversify: false, systemIdentifier: 'CRYPTAG', applicationId: '3042F5', keyVersion: 0 },
3: { type: 'target', masterKey: '00000000000000000000000000000000', diversify: false, systemIdentifier: 'CRYPTAG', applicationId: '3042F5', keyVersion: 0 },
4: { type: 'target', masterKey: '00000000000000000000000000000000', diversify: false, systemIdentifier: 'CRYPTAG', applicationId: '3042F5', keyVersion: 0 }
}

Changing Keys on the Tag

getKeyChangePlan(uid?)

Compare current vs target and report what will change before you run changeKeys(). uid (default null) is a 14-hex UID for diversified keys (defaults to the cached tag UID).

const res = await tag.getKeyChangePlan('04A1B2C3D4E580');

Returns

{
success: true,
data: {
plan: [
{ keyNo: 0, current: '00000000000000000000000000000000', target: 'D3F7A91C5E08B264A1F9C7E03B5D8A42', diversified: false, newKeyVersion: 1, willChange: true },
{ keyNo: 1, current: '00000000000000000000000000000000', target: 'D3F7A91C5E08B264A1F9C7E03B5D8A42', diversified: true, newKeyVersion: 1, willChange: true },
{ keyNo: 2, current: '00000000000000000000000000000000', target: '00000000000000000000000000000000', diversified: false, newKeyVersion: 0, willChange: false },
{ keyNo: 3, current: '00000000000000000000000000000000', target: '00000000000000000000000000000000', diversified: false, newKeyVersion: 0, willChange: false },
{ keyNo: 4, current: '00000000000000000000000000000000', target: '00000000000000000000000000000000', diversified: false, newKeyVersion: 0, willChange: false }
]
},
duration: 11
}

changeKeys()

Change all keys on the tag to match the target configuration. Changes keys 1–4 first, then Key 0 (auth: Key 0, automatic).

tag.setTargetKey(0, { masterKey: 'D3F7A91C5E08B264A1F9C7E03B5D8A42' });
const res = await tag.changeKeys();
if (res.data.allSuccess) console.log('all keys changed');

Returns

{
success: true,
data: {
changed: [
{ keyNo: 1, success: true, version: 1, error: null },
{ keyNo: 2, success: true, version: 0, error: null },
{ keyNo: 3, success: true, version: 0, error: null },
{ keyNo: 4, success: true, version: 0, error: null },
{ keyNo: 0, success: true, version: 1, error: null }
],
totalChanged: 5,
allSuccess: true
},
duration: 38
}

Diversification Inputs

setSystemIdentifier(systemIdentifier)

Set the global system ID (ASCII, max 8 chars).

const res = tag.setSystemIdentifier('CRYPTAG');

Returns

{
success: true,
data: { systemIdentifier: 'CRYPTAG' }
}

getSystemIdentifier()

Read the global system ID back.

tag.getSystemIdentifier();
// → 'CRYPTAG'

setApplicationId(applicationId)

Set the global application ID (6 hex chars / 3 bytes).

const res = tag.setApplicationId('3042F5');

Returns

{
success: true,
data: { applicationId: '3042F5' }
}

getApplicationId()

Read the global application ID back.

tag.getApplicationId();
// → '3042F5'

Generating Keys

generateRandomKey()

A cryptographically secure random 128-bit AES key (32-hex, uppercase).

tag.generateRandomKey();
// → 'D3F7A91C5E08B264A1F9C7E03B5D8A42'

generateRandomKeySet()

Five random keys, one per slot.

tag.generateRandomKeySet();

Returns

{
0: 'D3F7A91C5E08B264A1F9C7E03B5D8A42',
1: '7B2E9F40A1C8D356E0F94B7A2C5D8E13',
2: 'A1F9C7E03B5D8A42D3F7A91C5E08B264',
3: 'C5D8E1377B2E9F40A1C8D356E0F94B7A',
4: 'E0F94B7AA1C8D3567B2E9F40C5D8E137'
}

Saving & Loading Keysets

setKeysetsFolder(folderPath)

Base folder for exportKeyConfig / importKeyConfig. Pass an absolute path to decouple keyset files from the process CWD — recommended for desktop apps (e.g. an Electron userData directory).

import { app } from 'electron';
const res = tag.setKeysetsFolder(`${app.getPath('userData')}/keysets`);

Returns

{
success: true,
data: { keysetsFolder: '/home/user/.config/cryptag/keysets' }
}

exportKeyConfig(fileName)

Write the full key configuration to <folder>/<fileName>.keyset.json. fileName is a bare name — no path separators or ...

const res = await tag.exportKeyConfig('site-a'); // -> <folder>/site-a.keyset.json

Returns

{
success: true,
data: {
message: 'Key configuration exported successfully',
filePath: '/home/user/.config/cryptag/keysets/site-a.keyset.json',
fileName: 'site-a.keyset.json',
location: '/home/user/.config/cryptag/keysets',
fileSize: 842
},
duration: 9
}

importKeyConfig(fileName)

Read the full key configuration from <folder>/<fileName>.keyset.json. Resets to factory first (replace, not merge) and fully rolls back on any error.

const res = await tag.importKeyConfig('site-a');

Returns

{
success: true,
data: {
message: 'Key configuration imported successfully',
filePath: '/home/user/.config/cryptag/keysets/site-a.keyset.json',
fileName: 'site-a.keyset.json',
location: '/home/user/.config/cryptag/keysets',
metaData: {
exportDate: '2026-06-01T10:15:42.000Z',
exportTimestamp: 1780042542000,
version: '1.0',
description: 'CrypTag keyset export'
},
status: {
currentIsFactoryDefault: true,
targetIsFactoryDefault: false,
needsKeyChange: true,
hasTagUID: false
}
},
duration: 12
}