Store Keys

Key storage and cryptographic data

Store Keys

Reference for OctoMY™'s key storage system, cryptographic data formats, and identity management.

Security Consideration

The keystore.json file contains your node's private key. Never share this file - losing control of your private key means someone can impersonate your node. Back it up securely, and if compromised, regenerate keys (which will require re-pairing with all peers).


Store architecture

The run-time data of each OctoMY node is kept in a Store. The store is a QVariantMap tree with wrappers to manipulate the data asynchronously.

Core concepts

Concept Description
Async Access All store operations are asynchronous for non-blocking UI
Auto-persistence Store automatically loads at startup and persists on changes
Generators Some data items are backed by generators that create values on-demand
Multi-file Persistence can span multiple files while appearing as one store
Stackable Interface can be stacked for caching, muxing, network forwarding

Store API interface

The basic interface:

// Get data asynchronously
get(Key key, Callback(Status status, Data *data))

// Put data with mode
put(Key key, Data *data, Mode mode)

Where:

  • Key - Identifier for the data (XPath-like path)
  • Callback - Function called on completion
  • Status - Result state (success, not found, error, etc.)
  • Data - The actual data, or null
  • Mode - How to put the data (create, update, replace, etc.)

Key paths

Keys use an XPath-like syntax to navigate the store tree:

keystore.localkey.pub          # Local public key
keystore.remotekey[CAFEBABE]   # Remote key by ID
personality.name               # Personality name
peers[0].trustLevel            # First peer's trust level

Key store overview

OctoMY™ uses a secure key storage system for cryptographic material:

Key Store Architecture


Key types

Local keypair

The node's RSA-2048 keypair for identity and encryption:

Field Size Description
localKey.public 2048 bits Public key (shared with peers)
localKey.private 2048 bits Private key (never shared)
localKey.created timestamp Generation timestamp
localKey.algorithm string "RSA-2048"

Personality identity

The node's unique identity derived from the public key:

Field Size Description
personality.id 64 bytes SHA-512 hash of public key
personality.name string Human-readable name
personality.created timestamp Creation timestamp
personality.nodeType enum Agent, Remote, Hub

Peer keys

Public keys of trusted peers:

Field Size Description
peers[].id 64 bytes Peer personality ID
peers[].publicKey 2048 bits Peer's public key
peers[].name string Peer's name
peers[].trustLevel enum Trust level (0-5)
peers[].lastSeen timestamp Last successful connection

Trust levels

Peers are assigned trust levels that determine capabilities:

Trust Levels

Trust level capabilities

Level Discovery Pairing Sessions Control Plans
BLOCK No No No No No
IGNORE Yes No No No No
MEET Yes Initiate No No No
HANDSHAKE Yes Continue Pending No No
TRUST Yes Complete Yes Limited No
DEPEND Yes Complete Yes Full Yes

Key store format

JSON structure

{
  "version": 1,
  "created": "2024-01-15T10:30:00Z",
  "modified": "2024-01-20T14:45:00Z",
  "localKey": {
    "algorithm": "RSA-2048",
    "publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkq...",
    "privateKey": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADAN...",
    "created": "2024-01-15T10:30:00Z"
  },
  "personality": {
    "id": "a1b2c3d4e5f6...",
    "name": "MyRobot",
    "nodeType": "Agent",
    "created": "2024-01-15T10:30:00Z"
  },
  "peers": [
    {
      "id": "f6e5d4c3b2a1...",
      "name": "MyRemote",
      "nodeType": "Remote",
      "publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkq...",
      "trustLevel": 5,
      "firstSeen": "2024-01-16T09:00:00Z",
      "lastSeen": "2024-01-20T14:45:00Z",
      "addresses": [
        "192.168.1.100:8125",
        "10.0.0.50:8125"
      ]
    }
  ],
  "sessions": []
}

Key store API

Loading and saving

#include "sec/KeyStore.hpp"

// Create key store
KeyStore store;

// Load from file
if (!store.load("/path/to/keystore.json")) {
    qWarning() << "Failed to load key store";
}

// Save to file
if (!store.save("/path/to/keystore.json")) {
    qWarning() << "Failed to save key store";
}

Local key management

// Check if local key exists
if (!store.hasLocalKey()) {
    // Generate new keypair
    store.generateLocalKey(2048);  // RSA-2048
}

// Get local public key
QByteArray publicKey = store.localPublicKey();

// Get personality ID
QString personalityId = store.personalityId();

Peer management

// Add new peer
Peer peer;
peer.id = "abc123...";
peer.name = "NewPeer";
peer.publicKey = peerPublicKey;
peer.trustLevel = TrustLevel::MEET;
store.addPeer(peer);

// Find peer by ID
Peer* found = store.findPeer("abc123...");
if (found) {
    qDebug() << "Found peer:" << found->name;
}

// Update trust level
store.setTrustLevel("abc123...", TrustLevel::TRUST);

// Remove peer
store.removePeer("abc123...");

// Get all peers
QList<Peer> peers = store.allPeers();

// Get peers by trust level
QList<Peer> trusted = store.peersByTrustLevel(TrustLevel::TRUST);

Key operations

// Sign data
QByteArray signature = store.sign(data);

// Verify signature
bool valid = store.verify(data, signature, peerPublicKey);

// Encrypt for peer
QByteArray encrypted = store.encryptForPeer("abc123...", plaintext);

// Decrypt from peer
QByteArray decrypted = store.decryptFromPeer("abc123...", ciphertext);

Address book integration

The key store integrates with the AddressBook for peer management:

AddressBook Integration

Associate structure

class Associate {
public:
    // Identity (from KeyStore)
    QString id() const;            // Personality ID
    QString name() const;          // Display name
    NodeType nodeType() const;     // Agent/Remote/Hub
    QByteArray publicKey() const;  // RSA public key
    TrustLevel trustLevel() const; // Trust level

    // Addresses (from AddressBook)
    QList<CarrierAddress> addresses() const;
    CarrierAddress bestAddress() const;

    // Connection state
    bool isConnected() const;
    quint64 lastSeen() const;
};

Key store keys reference

Root keys

Key Type Required Description
version int Yes Store format version
created ISO8601 Yes Store creation time
modified ISO8601 Yes Last modification time
localKey object Yes Local keypair
personality object Yes Node identity
peers array No Trusted peers
sessions array No Active session keys

localKey object

Key Type Required Description
algorithm string Yes "RSA-2048"
publicKey PEM Yes PEM-encoded public key
privateKey PEM Yes PEM-encoded private key
created ISO8601 Yes Key generation time

personality object

Key Type Required Description
id hex Yes 64-byte SHA-512 hash
name string Yes Display name
nodeType enum Yes Agent, Remote, Hub
created ISO8601 Yes Creation time

peers array item

Key Type Required Description
id hex Yes Peer personality ID
name string Yes Peer display name
nodeType enum Yes Peer node type
publicKey PEM Yes Peer public key
trustLevel int Yes 0-5 trust level
firstSeen ISO8601 Yes First encounter
lastSeen ISO8601 Yes Last successful contact
addresses array No Known addresses
notes string No User notes

Security considerations

Private key protection

Private Key Security

File permissions

# Recommended permissions
chmod 600 ~/.local/share/OctoMY™/*/keystore.json
chmod 700 ~/.local/share/OctoMY™/*/

Backup and recovery

# Backup key store (keep secure!)
cp ~/.local/share/OctoMY™/OctoMY\ Agent/keystore.json \
   ~/secure-backup/keystore-backup.json

# Restore key store
cp ~/secure-backup/keystore-backup.json \
   ~/.local/share/OctoMY™/OctoMY\ Agent/keystore.json

Warning: Losing your private key means losing your identity. All peers will need to re-pair with your new identity.


Key generation

Generating new identity

// Generate completely new identity
void generateNewIdentity(KeyStore& store, const QString& name) {
    // Generate RSA-2048 keypair
    store.generateLocalKey(2048);

    // Set personality name
    store.setPersonalityName(name);

    // Save to disk
    store.save();

    qDebug() << "New identity:" << store.personalityId();
}

Regenerating keys

// Regenerate keys (loses pairing!)
void regenerateKeys(KeyStore& store) {
    // Warning: This invalidates all peer relationships
    qWarning() << "Regenerating keys - all pairings will be lost!";

    // Generate new keypair
    store.generateLocalKey(2048);

    // Clear peer list (they won't recognize us)
    store.clearPeers();

    // Save
    store.save();
}

Migration

Upgrading store format

void migrateKeyStore(KeyStore& store) {
    int version = store.version();

    if (version < 2) {
        // Migrate from v1 to v2
        // Add new fields, convert formats
        store.setVersion(2);
    }

    store.save();
}

Exporting/importing peers

// Export peer list (for sharing)
QJsonArray exportPeers(const KeyStore& store) {
    QJsonArray peers;
    for (const Peer& p : store.allPeers()) {
        QJsonObject obj;
        obj["id"] = p.id;
        obj["name"] = p.name;
        obj["publicKey"] = QString(p.publicKey.toBase64());
        peers.append(obj);
    }
    return peers;
}

// Import peer list
void importPeers(KeyStore& store, const QJsonArray& peers) {
    for (const QJsonValue& v : peers) {
        QJsonObject obj = v.toObject();
        Peer p;
        p.id = obj["id"].toString();
        p.name = obj["name"].toString();
        p.publicKey = QByteArray::fromBase64(
            obj["publicKey"].toString().toUtf8());
        p.trustLevel = TrustLevel::MEET;  // Default to MEET
        store.addPeer(p);
    }
    store.save();
}

Debugging

Inspecting key store

# View key store (JSON formatted)
cat ~/.local/share/OctoMY™/OctoMY\ Agent/keystore.json | python3 -m json.tool

# Extract personality ID
jq '.personality.id' ~/.local/share/OctoMY™/OctoMY\ Agent/keystore.json

# List peers
jq '.peers[] | {name, trustLevel}' ~/.local/share/OctoMY™/OctoMY\ Agent/keystore.json

Common issues

Issue Cause Solution
Pairing fails Key mismatch Re-pair from scratch
Identity lost Corrupted store Restore from backup
Permission denied File permissions Fix with chmod 600
Parse error Corrupted JSON Delete and regenerate

In this section
Topics
reference security cryptography keys identity
See also