Files
zeekayandHanzo Dev 64519916bf the corporate name is Lux Industries Inc
Lux Partners Limited is not the entity behind this work. Every place the
old name stood — copyright lines, site footers, brand config, legal and
compliance text — now names the company that actually holds it.

lux.fund is the exception and is not renamed to match: that site belongs
to Lux Assets Management LLC, a different company, and it says so.

Two kinds of line were left for a person rather than rewritten. A dated
news item recording that Lux Partners Limited was established in the Isle
of Man is a historical fact, and renaming it would falsify the record. And
a sentence asserting that the company is domiciled in the Isle of Man is a
claim about a jurisdiction, not a name — an Inc or an LLC is not an Isle
of Man company, so swapping the name there would assert something untrue.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-28 13:01:04 -07:00

728 lines
24 KiB
Go

// Copyright (c) 2025 Lux Industries Inc
// SPDX-License-Identifier: MIT
// Package kchain provides the K-Chain (KMS) adapter for the DAG indexer.
// Handles distributed key management, threshold signatures, and post-quantum algorithms.
package key
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/luxfi/indexer/dag"
"github.com/luxfi/indexer/storage"
)
const (
// DefaultPort for K-Chain indexer API
DefaultPort = 4900
// DefaultDatabase name
DefaultDatabase = "explorer_kchain"
)
// KeyStatus represents key lifecycle state
type KeyStatus string
const (
KeyStatusActive KeyStatus = "active"
KeyStatusInactive KeyStatus = "inactive"
KeyStatusRotating KeyStatus = "rotating"
KeyStatusRevoked KeyStatus = "revoked"
KeyStatusPending KeyStatus = "pending"
)
// AlgorithmType represents cryptographic algorithm categories
type AlgorithmType string
const (
AlgorithmTypeKeyExchange AlgorithmType = "key-exchange"
AlgorithmTypeSigning AlgorithmType = "signing"
AlgorithmTypeEncryption AlgorithmType = "encryption"
)
// Key represents a distributed cryptographic key
type Key struct {
ID string `json:"id"`
Name string `json:"name"`
Algorithm string `json:"algorithm"`
KeyType string `json:"keyType"`
PublicKey string `json:"publicKey"`
Threshold int `json:"threshold"`
TotalShares int `json:"totalShares"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Status KeyStatus `json:"status"`
Tags []string `json:"tags"`
}
// KeyOperation represents a key lifecycle operation
type KeyOperation struct {
ID string `json:"id"`
KeyID string `json:"keyId"`
Operation string `json:"operation"` // create, rotate, revoke, delete
Initiator string `json:"initiator"`
Participants []string `json:"participants"`
Success bool `json:"success"`
Error string `json:"error,omitempty"`
Timestamp time.Time `json:"timestamp"`
}
// EncryptionRequest represents an encryption operation
type EncryptionRequest struct {
ID string `json:"id"`
KeyID string `json:"keyId"`
Requester string `json:"requester"`
DataSize int64 `json:"dataSize"`
Success bool `json:"success"`
Timestamp time.Time `json:"timestamp"`
}
// SignatureRequest represents a signing operation
type SignatureRequest struct {
ID string `json:"id"`
KeyID string `json:"keyId"`
Signers []string `json:"signers"`
MessageHash string `json:"messageHash"`
Algorithm string `json:"algorithm"`
Success bool `json:"success"`
Timestamp time.Time `json:"timestamp"`
}
// Algorithm represents a supported cryptographic algorithm
type Algorithm struct {
Name string `json:"name"`
Type string `json:"type"`
SecurityLevel int `json:"securityLevel"`
KeySize int `json:"keySize"`
SignatureSize int `json:"signatureSize"`
PostQuantum bool `json:"postQuantum"`
ThresholdSupport bool `json:"thresholdSupport"`
Description string `json:"description"`
Standards []string `json:"standards"`
}
// vertexData is the parsed vertex content
type vertexData struct {
Keys []Key `json:"keys,omitempty"`
KeyOperations []KeyOperation `json:"keyOperations,omitempty"`
EncryptionRequests []EncryptionRequest `json:"encryptionRequests,omitempty"`
SignatureRequests []SignatureRequest `json:"signatureRequests,omitempty"`
}
// Adapter implements the DAG adapter interface for K-Chain
type Adapter struct {
rpcEndpoint string
httpClient *http.Client
}
// New creates a new K-Chain adapter
func New(rpcEndpoint string) *Adapter {
return &Adapter{
rpcEndpoint: rpcEndpoint,
httpClient: &http.Client{
Timeout: 30 * time.Second,
},
}
}
// ParseVertex parses K-Chain vertex data
func (a *Adapter) ParseVertex(data json.RawMessage) (*dag.Vertex, error) {
var raw struct {
ID string `json:"id"`
ParentIDs []string `json:"parentIds"`
Height uint64 `json:"height"`
Timestamp int64 `json:"timestamp"`
Status string `json:"status"`
Data json.RawMessage `json:"data"`
}
if err := json.Unmarshal(data, &raw); err != nil {
return nil, fmt.Errorf("unmarshal vertex: %w", err)
}
vertex := &dag.Vertex{
ID: raw.ID,
ParentIDs: raw.ParentIDs,
Height: raw.Height,
Timestamp: time.Unix(raw.Timestamp, 0),
Status: dag.Status(raw.Status),
Data: raw.Data,
Type: a.inferVertexType(raw.Data),
}
return vertex, nil
}
// inferVertexType determines the vertex type from its data
func (a *Adapter) inferVertexType(data json.RawMessage) string {
var v vertexData
if err := json.Unmarshal(data, &v); err != nil {
return "unknown"
}
if len(v.Keys) > 0 {
return "keys"
}
if len(v.KeyOperations) > 0 {
return "key_operations"
}
if len(v.EncryptionRequests) > 0 {
return "encryption"
}
if len(v.SignatureRequests) > 0 {
return "signatures"
}
return "generic"
}
// GetRecentVertices fetches recent vertices from K-Chain RPC
func (a *Adapter) GetRecentVertices(ctx context.Context, limit int) ([]json.RawMessage, error) {
return a.call(ctx, "kvm.getRecentVertices", map[string]interface{}{
"limit": limit,
})
}
// GetVertexByID fetches a specific vertex by ID
func (a *Adapter) GetVertexByID(ctx context.Context, id string) (json.RawMessage, error) {
results, err := a.call(ctx, "kvm.getVertex", map[string]interface{}{
"id": id,
})
if err != nil {
return nil, err
}
if len(results) == 0 {
return nil, fmt.Errorf("vertex not found: %s", id)
}
return results[0], nil
}
// ListKeys fetches all keys from K-Chain
func (a *Adapter) ListKeys(ctx context.Context, algorithm, status string, offset, limit int) ([]Key, error) {
results, err := a.call(ctx, "kvm.listKeys", map[string]interface{}{
"algorithm": algorithm,
"status": status,
"offset": offset,
"limit": limit,
})
if err != nil {
return nil, err
}
if len(results) == 0 {
return nil, nil
}
var resp struct {
Keys []Key `json:"keys"`
Total int `json:"total"`
}
if err := json.Unmarshal(results[0], &resp); err != nil {
return nil, fmt.Errorf("unmarshal keys: %w", err)
}
return resp.Keys, nil
}
// GetKeyByID fetches a specific key by ID
func (a *Adapter) GetKeyByID(ctx context.Context, id string) (*Key, error) {
results, err := a.call(ctx, "kvm.getKeyByID", map[string]interface{}{
"id": id,
})
if err != nil {
return nil, err
}
if len(results) == 0 {
return nil, fmt.Errorf("key not found: %s", id)
}
var key Key
if err := json.Unmarshal(results[0], &key); err != nil {
return nil, fmt.Errorf("unmarshal key: %w", err)
}
return &key, nil
}
// ListAlgorithms fetches supported algorithms
func (a *Adapter) ListAlgorithms(ctx context.Context) ([]Algorithm, error) {
results, err := a.call(ctx, "kvm.listAlgorithms", map[string]interface{}{})
if err != nil {
return nil, err
}
if len(results) == 0 {
return nil, nil
}
var resp struct {
Algorithms []Algorithm `json:"algorithms"`
}
if err := json.Unmarshal(results[0], &resp); err != nil {
return nil, fmt.Errorf("unmarshal algorithms: %w", err)
}
return resp.Algorithms, nil
}
// call makes a JSON-RPC call to the K-Chain node
func (a *Adapter) call(ctx context.Context, method string, params interface{}) ([]json.RawMessage, error) {
reqBody, err := json.Marshal(map[string]interface{}{
"jsonrpc": "2.0",
"method": method,
"params": params,
"id": 1,
})
if err != nil {
return nil, fmt.Errorf("marshal request: %w", err)
}
req, err := http.NewRequestWithContext(ctx, "POST", a.rpcEndpoint, bytes.NewReader(reqBody))
if err != nil {
return nil, fmt.Errorf("create request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
resp, err := a.httpClient.Do(req)
if err != nil {
return nil, fmt.Errorf("http request: %w", err)
}
defer resp.Body.Close()
var result struct {
Result json.RawMessage `json:"result"`
Error *struct {
Code int `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("decode response: %w", err)
}
if result.Error != nil {
return nil, fmt.Errorf("rpc error %d: %s", result.Error.Code, result.Error.Message)
}
// Try to decode as array
var vertices []json.RawMessage
if err := json.Unmarshal(result.Result, &vertices); err != nil {
// Single result
return []json.RawMessage{result.Result}, nil
}
return vertices, nil
}
// InitSchema creates K-Chain specific database tables using unified storage
func (a *Adapter) InitSchema(ctx context.Context, store storage.Store) error {
schema := storage.Schema{
Name: "kchain",
Tables: []storage.Table{
{
Name: "kchain_keys",
Columns: []storage.Column{
{Name: "id", Type: storage.TypeText, Primary: true},
{Name: "name", Type: storage.TypeText, Nullable: false},
{Name: "algorithm", Type: storage.TypeText, Nullable: false},
{Name: "key_type", Type: storage.TypeText, Nullable: false},
{Name: "public_key", Type: storage.TypeText},
{Name: "threshold", Type: storage.TypeInt, Default: "1"},
{Name: "total_shares", Type: storage.TypeInt, Default: "1"},
{Name: "status", Type: storage.TypeText, Default: "'pending'"},
{Name: "tags", Type: storage.TypeText, Default: "'[]'"},
{Name: "created_at", Type: storage.TypeTimestamp, Nullable: false},
{Name: "updated_at", Type: storage.TypeTimestamp, Nullable: false},
},
},
{
Name: "kchain_key_operations",
Columns: []storage.Column{
{Name: "id", Type: storage.TypeText, Primary: true},
{Name: "key_id", Type: storage.TypeText, Nullable: false},
{Name: "operation", Type: storage.TypeText, Nullable: false},
{Name: "initiator", Type: storage.TypeText},
{Name: "participants", Type: storage.TypeText, Default: "'[]'"},
{Name: "success", Type: storage.TypeBool, Default: "true"},
{Name: "error_msg", Type: storage.TypeText},
{Name: "timestamp", Type: storage.TypeTimestamp, Nullable: false},
},
},
{
Name: "kchain_encryption_requests",
Columns: []storage.Column{
{Name: "id", Type: storage.TypeText, Primary: true},
{Name: "key_id", Type: storage.TypeText, Nullable: false},
{Name: "requester", Type: storage.TypeText, Nullable: false},
{Name: "data_size", Type: storage.TypeBigInt, Default: "0"},
{Name: "success", Type: storage.TypeBool, Default: "true"},
{Name: "timestamp", Type: storage.TypeTimestamp, Nullable: false},
},
},
{
Name: "kchain_signature_requests",
Columns: []storage.Column{
{Name: "id", Type: storage.TypeText, Primary: true},
{Name: "key_id", Type: storage.TypeText, Nullable: false},
{Name: "signers", Type: storage.TypeText, Default: "'[]'"},
{Name: "message_hash", Type: storage.TypeText, Nullable: false},
{Name: "algorithm", Type: storage.TypeText, Nullable: false},
{Name: "success", Type: storage.TypeBool, Default: "true"},
{Name: "timestamp", Type: storage.TypeTimestamp, Nullable: false},
},
},
{
Name: "kchain_algorithms",
Columns: []storage.Column{
{Name: "name", Type: storage.TypeText, Primary: true},
{Name: "type", Type: storage.TypeText, Nullable: false},
{Name: "security_level", Type: storage.TypeInt, Default: "128"},
{Name: "key_size", Type: storage.TypeInt},
{Name: "signature_size", Type: storage.TypeInt},
{Name: "post_quantum", Type: storage.TypeBool, Default: "false"},
{Name: "threshold_support", Type: storage.TypeBool, Default: "false"},
{Name: "description", Type: storage.TypeText},
{Name: "standards", Type: storage.TypeText, Default: "'[]'"},
},
},
{
Name: "kchain_extended_stats",
Columns: []storage.Column{
{Name: "id", Type: storage.TypeInt, Primary: true},
{Name: "total_keys", Type: storage.TypeBigInt, Default: "0"},
{Name: "active_keys", Type: storage.TypeBigInt, Default: "0"},
{Name: "total_operations", Type: storage.TypeBigInt, Default: "0"},
{Name: "total_encryptions", Type: storage.TypeBigInt, Default: "0"},
{Name: "total_signatures", Type: storage.TypeBigInt, Default: "0"},
{Name: "pq_keys_count", Type: storage.TypeBigInt, Default: "0"},
{Name: "threshold_keys_count", Type: storage.TypeBigInt, Default: "0"},
{Name: "algorithm_distribution", Type: storage.TypeText, Default: "'{}'"},
{Name: "updated_at", Type: storage.TypeTimestamp, Default: "CURRENT_TIMESTAMP"},
},
},
},
Indexes: []storage.Index{
{Name: "idx_kchain_keys_name", Table: "kchain_keys", Columns: []string{"name"}},
{Name: "idx_kchain_keys_algorithm", Table: "kchain_keys", Columns: []string{"algorithm"}},
{Name: "idx_kchain_keys_status", Table: "kchain_keys", Columns: []string{"status"}},
{Name: "idx_kchain_keys_created", Table: "kchain_keys", Columns: []string{"created_at"}},
{Name: "idx_kchain_ops_key", Table: "kchain_key_operations", Columns: []string{"key_id"}},
{Name: "idx_kchain_ops_operation", Table: "kchain_key_operations", Columns: []string{"operation"}},
{Name: "idx_kchain_ops_timestamp", Table: "kchain_key_operations", Columns: []string{"timestamp"}},
{Name: "idx_kchain_enc_key", Table: "kchain_encryption_requests", Columns: []string{"key_id"}},
{Name: "idx_kchain_enc_requester", Table: "kchain_encryption_requests", Columns: []string{"requester"}},
{Name: "idx_kchain_enc_timestamp", Table: "kchain_encryption_requests", Columns: []string{"timestamp"}},
{Name: "idx_kchain_sig_key", Table: "kchain_signature_requests", Columns: []string{"key_id"}},
{Name: "idx_kchain_sig_timestamp", Table: "kchain_signature_requests", Columns: []string{"timestamp"}},
},
}
if err := store.InitSchema(ctx, schema); err != nil {
return err
}
// Initialize stats row
if err := store.Exec(ctx, "INSERT INTO kchain_extended_stats (id) VALUES (1) ON CONFLICT DO NOTHING"); err != nil {
return err
}
// Seed algorithms reference data - simpler INSERT OR IGNORE
algorithms := []string{
"INSERT INTO kchain_algorithms (name, type, security_level, key_size, signature_size, post_quantum, threshold_support, description, standards) VALUES ('ml-kem-768', 'key-exchange', 192, 2400, 0, 1, 0, 'ML-KEM-768 post-quantum key encapsulation', '[\"NIST FIPS 203\"]') ON CONFLICT DO NOTHING",
"INSERT INTO kchain_algorithms (name, type, security_level, key_size, signature_size, post_quantum, threshold_support, description, standards) VALUES ('ml-dsa-65', 'signing', 192, 0, 3309, 1, 0, 'ML-DSA-65 post-quantum digital signature', '[\"NIST FIPS 204\"]') ON CONFLICT DO NOTHING",
"INSERT INTO kchain_algorithms (name, type, security_level, key_size, signature_size, post_quantum, threshold_support, description, standards) VALUES ('bls-threshold', 'signing', 128, 0, 96, 0, 1, 'BLS12-381 threshold signatures', '[\"IETF BLS Signature\"]') ON CONFLICT DO NOTHING",
"INSERT INTO kchain_algorithms (name, type, security_level, key_size, signature_size, post_quantum, threshold_support, description, standards) VALUES ('secp256k1', 'signing', 128, 0, 64, 0, 0, 'ECDSA on secp256k1 (Ethereum compatible)', '[\"SEC 2\"]') ON CONFLICT DO NOTHING",
"INSERT INTO kchain_algorithms (name, type, security_level, key_size, signature_size, post_quantum, threshold_support, description, standards) VALUES ('frost-secp256k1', 'signing', 128, 0, 64, 0, 1, 'FROST threshold Schnorr on secp256k1', '[\"IETF FROST\", \"BIP-340\"]') ON CONFLICT DO NOTHING",
}
for _, q := range algorithms {
_ = store.Exec(ctx, q)
}
return nil
}
// GetStats returns K-Chain specific statistics using unified storage
func (a *Adapter) GetStats(ctx context.Context, store storage.Store) (map[string]interface{}, error) {
stats := make(map[string]interface{})
// Get extended stats
rows, err := store.Query(ctx, `
SELECT total_keys, active_keys, total_operations, total_encryptions,
total_signatures, pq_keys_count, threshold_keys_count, algorithm_distribution, updated_at
FROM kchain_extended_stats WHERE id = 1
`)
if err != nil {
return nil, err
}
if len(rows) > 0 {
row := rows[0]
stats["total_keys"] = row["total_keys"]
stats["active_keys"] = row["active_keys"]
stats["total_operations"] = row["total_operations"]
stats["total_encryptions"] = row["total_encryptions"]
stats["total_signatures"] = row["total_signatures"]
stats["post_quantum_keys"] = row["pq_keys_count"]
stats["threshold_keys"] = row["threshold_keys_count"]
stats["updated_at"] = row["updated_at"]
// Parse algorithm distribution if present
if algDist, ok := row["algorithm_distribution"].(string); ok && algDist != "" {
var dist map[string]int64
if err := json.Unmarshal([]byte(algDist), &dist); err == nil {
stats["algorithm_distribution"] = dist
}
}
}
// Get recent operations
opRows, err := store.Query(ctx, `
SELECT key_id, operation, success, timestamp
FROM kchain_key_operations
ORDER BY timestamp DESC
LIMIT 10
`)
if err != nil {
return nil, err
}
var recentOps []map[string]interface{}
for _, row := range opRows {
recentOps = append(recentOps, map[string]interface{}{
"key_id": row["key_id"],
"operation": row["operation"],
"success": row["success"],
"timestamp": row["timestamp"],
})
}
stats["recent_operations"] = recentOps
// Get algorithm usage
algRows, err := store.Query(ctx, `
SELECT algorithm, COUNT(*) as count
FROM kchain_keys
GROUP BY algorithm
ORDER BY count DESC
`)
if err != nil {
return nil, err
}
var algUsage []map[string]interface{}
for _, row := range algRows {
algUsage = append(algUsage, map[string]interface{}{
"algorithm": row["algorithm"],
"count": row["count"],
})
}
stats["algorithm_usage"] = algUsage
return stats, nil
}
// StoreKey stores a key
func (a *Adapter) StoreKey(ctx context.Context, store storage.Store, k Key) error {
tagsJSON, _ := json.Marshal(k.Tags)
return store.Exec(ctx, `
INSERT INTO kchain_keys
(id, name, algorithm, key_type, public_key, threshold, total_shares, status, tags, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (id) DO UPDATE SET
public_key = EXCLUDED.public_key,
status = EXCLUDED.status,
tags = EXCLUDED.tags,
updated_at = EXCLUDED.updated_at
`, k.ID, k.Name, k.Algorithm, k.KeyType, k.PublicKey, k.Threshold, k.TotalShares,
k.Status, tagsJSON, k.CreatedAt, k.UpdatedAt)
}
// StoreKeyOperation stores a key operation
func (a *Adapter) StoreKeyOperation(ctx context.Context, store storage.Store, op KeyOperation) error {
participantsJSON, _ := json.Marshal(op.Participants)
return store.Exec(ctx, `
INSERT INTO kchain_key_operations
(id, key_id, operation, initiator, participants, success, error_msg, timestamp)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (id) DO NOTHING
`, op.ID, op.KeyID, op.Operation, op.Initiator, participantsJSON, op.Success, op.Error, op.Timestamp)
}
// StoreEncryptionRequest stores an encryption request
func (a *Adapter) StoreEncryptionRequest(ctx context.Context, store storage.Store, req EncryptionRequest) error {
return store.Exec(ctx, `
INSERT INTO kchain_encryption_requests
(id, key_id, requester, data_size, success, timestamp)
VALUES (?, ?, ?, ?, ?, ?)
ON CONFLICT (id) DO NOTHING
`, req.ID, req.KeyID, req.Requester, req.DataSize, req.Success, req.Timestamp)
}
// StoreSignatureRequest stores a signature request
func (a *Adapter) StoreSignatureRequest(ctx context.Context, store storage.Store, req SignatureRequest) error {
signersJSON, _ := json.Marshal(req.Signers)
return store.Exec(ctx, `
INSERT INTO kchain_signature_requests
(id, key_id, signers, message_hash, algorithm, success, timestamp)
VALUES (?, ?, ?, ?, ?, ?, ?)
ON CONFLICT (id) DO NOTHING
`, req.ID, req.KeyID, signersJSON, req.MessageHash, req.Algorithm, req.Success, req.Timestamp)
}
// StoreVertex stores vertex data
func (a *Adapter) StoreVertex(ctx context.Context, store storage.Store, v *dag.Vertex) error {
var data vertexData
if err := json.Unmarshal(v.Data, &data); err != nil {
return fmt.Errorf("unmarshal vertex data: %w", err)
}
// Store keys
for _, k := range data.Keys {
if err := a.StoreKey(ctx, store, k); err != nil {
return fmt.Errorf("store key: %w", err)
}
}
// Store key operations
for _, op := range data.KeyOperations {
if err := a.StoreKeyOperation(ctx, store, op); err != nil {
return fmt.Errorf("store key operation: %w", err)
}
}
// Store encryption requests
for _, req := range data.EncryptionRequests {
if err := a.StoreEncryptionRequest(ctx, store, req); err != nil {
return fmt.Errorf("store encryption request: %w", err)
}
}
// Store signature requests
for _, req := range data.SignatureRequests {
if err := a.StoreSignatureRequest(ctx, store, req); err != nil {
return fmt.Errorf("store signature request: %w", err)
}
}
return nil
}
// UpdateExtendedStats updates K-Chain specific statistics
func (a *Adapter) UpdateExtendedStats(ctx context.Context, store storage.Store) error {
rows, err := store.Query(ctx, `
SELECT algorithm, COUNT(*) as count FROM kchain_keys GROUP BY algorithm
`)
if err != nil {
return err
}
algDist := make(map[string]int64)
for _, row := range rows {
if alg, ok := row["algorithm"].(string); ok {
if count, ok := row["count"].(int64); ok {
algDist[alg] = count
}
}
}
algDistJSON, _ := json.Marshal(algDist)
return store.Exec(ctx, `
UPDATE kchain_extended_stats SET
total_keys = (SELECT COUNT(*) FROM kchain_keys),
active_keys = (SELECT COUNT(*) FROM kchain_keys WHERE status = 'active'),
total_operations = (SELECT COUNT(*) FROM kchain_key_operations),
total_encryptions = (SELECT COUNT(*) FROM kchain_encryption_requests),
total_signatures = (SELECT COUNT(*) FROM kchain_signature_requests),
pq_keys_count = (SELECT COUNT(*) FROM kchain_keys WHERE algorithm LIKE 'ml-%' OR algorithm = 'corona'),
threshold_keys_count = (SELECT COUNT(*) FROM kchain_keys WHERE threshold > 1),
algorithm_distribution = ?,
updated_at = CURRENT_TIMESTAMP
WHERE id = 1
`, algDistJSON)
}
// GetKeysByAlgorithm returns keys filtered by algorithm
func (a *Adapter) GetKeysByAlgorithm(ctx context.Context, store storage.Store, algorithm string, limit, offset int) ([]Key, error) {
rows, err := store.Query(ctx, `
SELECT id, name, algorithm, key_type, public_key, threshold, total_shares,
status, tags, created_at, updated_at
FROM kchain_keys
WHERE algorithm = ?
ORDER BY created_at DESC
LIMIT ? OFFSET ?
`, algorithm, limit, offset)
if err != nil {
return nil, err
}
return a.scanKeys(rows), nil
}
// GetPostQuantumKeys returns all post-quantum keys
func (a *Adapter) GetPostQuantumKeys(ctx context.Context, store storage.Store, limit, offset int) ([]Key, error) {
rows, err := store.Query(ctx, `
SELECT id, name, algorithm, key_type, public_key, threshold, total_shares,
status, tags, created_at, updated_at
FROM kchain_keys
WHERE algorithm LIKE 'ml-%' OR algorithm = 'corona'
ORDER BY created_at DESC
LIMIT ? OFFSET ?
`, limit, offset)
if err != nil {
return nil, err
}
return a.scanKeys(rows), nil
}
// GetThresholdKeys returns all threshold keys (threshold > 1)
func (a *Adapter) GetThresholdKeys(ctx context.Context, store storage.Store, limit, offset int) ([]Key, error) {
rows, err := store.Query(ctx, `
SELECT id, name, algorithm, key_type, public_key, threshold, total_shares,
status, tags, created_at, updated_at
FROM kchain_keys
WHERE threshold > 1
ORDER BY created_at DESC
LIMIT ? OFFSET ?
`, limit, offset)
if err != nil {
return nil, err
}
return a.scanKeys(rows), nil
}
// scanKeys converts query result rows into Key structs
func (a *Adapter) scanKeys(rows []map[string]interface{}) []Key {
var keys []Key
for _, row := range rows {
k := Key{
ID: fmt.Sprintf("%v", row["id"]),
Name: fmt.Sprintf("%v", row["name"]),
Algorithm: fmt.Sprintf("%v", row["algorithm"]),
KeyType: fmt.Sprintf("%v", row["key_type"]),
PublicKey: fmt.Sprintf("%v", row["public_key"]),
}
if v, ok := row["threshold"].(int64); ok {
k.Threshold = int(v)
}
if v, ok := row["total_shares"].(int64); ok {
k.TotalShares = int(v)
}
if v, ok := row["status"].(string); ok {
k.Status = KeyStatus(v)
}
if v, ok := row["tags"].(string); ok && v != "" {
json.Unmarshal([]byte(v), &k.Tags)
}
if v, ok := row["created_at"].(time.Time); ok {
k.CreatedAt = v
}
if v, ok := row["updated_at"].(time.Time); ok {
k.UpdatedAt = v
}
keys = append(keys, k)
}
return keys
}