Add HASH/ASL1 registry descriptors and stub hook
This commit is contained in:
parent
b47b914224
commit
32e3ca4ade
|
|
@ -10,15 +10,42 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool (*digest)(void *ctx,
|
||||||
|
amduat_octets_t input,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t out_len);
|
||||||
|
void *ctx;
|
||||||
|
} amduat_hash_asl1_impl_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
amduat_hash_id_t hash_id;
|
amduat_hash_id_t hash_id;
|
||||||
const char *name;
|
const char *name;
|
||||||
size_t digest_len;
|
size_t digest_len;
|
||||||
void *impl;
|
amduat_hash_asl1_impl_t impl;
|
||||||
} amduat_hash_asl1_desc_t;
|
} amduat_hash_asl1_desc_t;
|
||||||
|
|
||||||
|
enum { AMDUAT_HASH_ASL1_ID_SHA256 = 0x0001 };
|
||||||
|
|
||||||
amduat_octets_t amduat_hash_asl1_key(amduat_hash_id_t hash_id, uint8_t out[2]);
|
amduat_octets_t amduat_hash_asl1_key(amduat_hash_id_t hash_id, uint8_t out[2]);
|
||||||
|
|
||||||
|
const amduat_hash_asl1_desc_t *amduat_hash_asl1_desc_lookup(
|
||||||
|
amduat_hash_id_t hash_id);
|
||||||
|
|
||||||
|
const amduat_hash_asl1_desc_t *amduat_hash_asl1_descs(size_t *out_len);
|
||||||
|
|
||||||
|
bool amduat_hash_asl1_register_impl(amduat_hash_id_t hash_id,
|
||||||
|
amduat_hash_asl1_impl_t impl);
|
||||||
|
|
||||||
|
bool amduat_hash_asl1_digest(amduat_hash_id_t hash_id,
|
||||||
|
amduat_octets_t input,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t out_len);
|
||||||
|
|
||||||
|
/* Optional: registers a non-conformant SHA-256 stub for wiring/tests.
|
||||||
|
* Define AMDUAT_HASH_ASL1_ENABLE_SHA256_STUB to enable. */
|
||||||
|
bool amduat_hash_asl1_register_sha256_stub(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
89
registry/README.md
Normal file
89
registry/README.md
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
# Registry Model (draft)
|
||||||
|
|
||||||
|
This directory documents how Amduat registries are represented in the repo
|
||||||
|
before the full stack and code generation are available. The goal is to keep
|
||||||
|
registry entries stable and machine-readable so they can drive docs, code, and
|
||||||
|
graph mappings later without rewriting identifiers.
|
||||||
|
|
||||||
|
## Core idea
|
||||||
|
|
||||||
|
- **Registry keys are concepts.** The key itself (for example a `HashId`) has a
|
||||||
|
stable handle like `amduat.hash.asl1.id.0001@1`.
|
||||||
|
- **Registry values are data.** Each entry has a descriptor row that is data
|
||||||
|
(name, digest length, status, notes). Values are not treated as concepts.
|
||||||
|
|
||||||
|
This matches MS/1: concept handles are stable identifiers; the descriptor bytes
|
||||||
|
are data nodes that can be hashed and referenced.
|
||||||
|
|
||||||
|
## JSONL manifests
|
||||||
|
|
||||||
|
Each registry has a `registry/<name>.jsonl` manifest. Each line is one entry.
|
||||||
|
The manifest is the source of truth for codegen and documentation tables.
|
||||||
|
|
||||||
|
Common fields (registry-specific schemas may add fields):
|
||||||
|
|
||||||
|
- `registry`: registry name (e.g. `HASH/ASL1`).
|
||||||
|
- `hash_id` (or other key field): registry key as hex string.
|
||||||
|
- `handle`: concept handle for the key.
|
||||||
|
- `name`, `digest_len`, `status`, `spec_ref`, `notes`: descriptor fields.
|
||||||
|
- `descriptor_sha256`: digest of the canonical descriptor (see below).
|
||||||
|
|
||||||
|
## Handle naming scheme
|
||||||
|
|
||||||
|
Handles are opaque identifiers in the `amduat` namespace and do **not** depend
|
||||||
|
on DNS:
|
||||||
|
|
||||||
|
```
|
||||||
|
amduat.<domain>.<registry>.<kind>.<id>@<version>
|
||||||
|
```
|
||||||
|
|
||||||
|
Example (HASH/ASL1):
|
||||||
|
|
||||||
|
```
|
||||||
|
amduat.hash.asl1.id.0001@1
|
||||||
|
```
|
||||||
|
|
||||||
|
`id` is the canonical key (often lowercase hex, zero-padded). `version` is
|
||||||
|
incremented only when the meaning of that key changes (rare).
|
||||||
|
|
||||||
|
## Descriptor digest rule
|
||||||
|
|
||||||
|
`descriptor_sha256` is computed over a canonical JSON object with fields in a
|
||||||
|
fixed order. Each registry schema defines the exact ordering; for HASH/ASL1
|
||||||
|
see `registry/hash-asl1.schema.md`.
|
||||||
|
|
||||||
|
This digest can be used as a stable Data-node hash to anchor graphs, evidence,
|
||||||
|
or generated artifacts without requiring a full ASL encoder yet.
|
||||||
|
|
||||||
|
## Canonical key encoding
|
||||||
|
|
||||||
|
Each registry defines the byte encoding of its key. This is the encoding used
|
||||||
|
when building an ASL registry artifact:
|
||||||
|
|
||||||
|
- HASH/ASL1: `hash_id` is encoded as big-endian `u16` (see
|
||||||
|
`amduat_hash_asl1_key`).
|
||||||
|
|
||||||
|
## Mapping into ASL
|
||||||
|
|
||||||
|
When the stack is available:
|
||||||
|
|
||||||
|
1. Encode each descriptor row as an ASL Artifact (data bytes).
|
||||||
|
2. Store it to obtain a `Reference`.
|
||||||
|
3. Build a registry value where each entry maps:
|
||||||
|
|
||||||
|
```
|
||||||
|
key_bytes -> value_ref
|
||||||
|
```
|
||||||
|
|
||||||
|
This uses the generic registry container in `amduat/asl/registry`.
|
||||||
|
|
||||||
|
## Current manifests
|
||||||
|
|
||||||
|
- `registry/hash-asl1.jsonl` — ASL1 HashId assignments.
|
||||||
|
|
||||||
|
## Design constraints
|
||||||
|
|
||||||
|
- Handles MUST be stable and immutable once published.
|
||||||
|
- Reserved IDs are explicit rows with `status = reserved`.
|
||||||
|
- The manifest should be sufficient to regenerate code tables and docs without
|
||||||
|
additional context.
|
||||||
4
registry/hash-asl1.jsonl
Normal file
4
registry/hash-asl1.jsonl
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{"registry":"HASH/ASL1","hash_id":"0x0000","handle":"amduat.hash.asl1.id.0000@1","name":null,"digest_len":null,"status":"reserved","spec_ref":"HASH/ASL1 v0.2.4","notes":"Reserved; never a valid algorithm.","descriptor_sha256":"aef821024f5ec2000b3920eaf6ea3a687690df87417a86b372359b064c7d1ac3"}
|
||||||
|
{"registry":"HASH/ASL1","hash_id":"0x0001","handle":"amduat.hash.asl1.id.0001@1","name":"HASH-ASL1-256","digest_len":32,"status":"mandatory","spec_ref":"HASH/ASL1 v0.2.4","notes":"Bit-for-bit SHA-256.","descriptor_sha256":"5082d8280750dc3cff48b48a7a2eda725a16f2902592f13eaf9b677908d7517e"}
|
||||||
|
{"registry":"HASH/ASL1","hash_id":"0x0002","handle":"amduat.hash.asl1.id.0002@1","name":"HASH-ASL1-512","digest_len":64,"status":"reserved","spec_ref":"HASH/ASL1 v0.2.4","notes":"Intended classical 512-bit algorithm.","descriptor_sha256":"2063bfe4878add4d2b6c575b95466d433f9c082df5284000ffde972f6a734f6d"}
|
||||||
|
{"registry":"HASH/ASL1","hash_id":"0x8001","handle":"amduat.hash.asl1.id.8001@1","name":"HASH-ASL1-PQ1","digest_len":null,"status":"reserved","spec_ref":"HASH/ASL1 v0.2.4","notes":"First PQ algorithm placeholder.","descriptor_sha256":"fca3b7afa0c3257cf0bbef7b8b338c76f0b7c3690e60c9a90ae4a1c0b99f25f0"}
|
||||||
52
registry/hash-asl1.schema.md
Normal file
52
registry/hash-asl1.schema.md
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
# HASH/ASL1 Registry Manifest (draft)
|
||||||
|
|
||||||
|
This file documents the JSONL rows in `registry/hash-asl1.jsonl`. Each line is
|
||||||
|
one entry descriptor for a single `HashId` assignment. The key is the `HashId`
|
||||||
|
itself (a concept); the descriptor is data.
|
||||||
|
|
||||||
|
## Field definitions
|
||||||
|
|
||||||
|
- `registry`: string. Constant `"HASH/ASL1"`.
|
||||||
|
- `hash_id`: string. Hex `u16` formatted as `0x0000`.
|
||||||
|
- `handle`: string. Stable concept handle for this HashId assignment, e.g.
|
||||||
|
`amduat.hash.asl1.id.0001@1`.
|
||||||
|
- `name`: string or null. Algorithm name if assigned (e.g. `HASH-ASL1-256`).
|
||||||
|
- `digest_len`: integer or null. Digest length in bytes; null if unknown.
|
||||||
|
- `status`: string. One of: `mandatory`, `reserved`, `deprecated`, `experimental`.
|
||||||
|
- `spec_ref`: string. Document/version that defines the assignment.
|
||||||
|
- `notes`: string. Short human-readable note.
|
||||||
|
- `descriptor_sha256`: string. Lowercase hex SHA-256 digest of the canonical
|
||||||
|
descriptor (see below).
|
||||||
|
|
||||||
|
## Canonical registry key
|
||||||
|
|
||||||
|
`hash_id` is the registry key. Its key bytes are the big-endian `u16` encoding
|
||||||
|
defined in `ENC/ASL1-CORE` (see `amduat_hash_asl1_key`).
|
||||||
|
|
||||||
|
## Handle naming scheme
|
||||||
|
|
||||||
|
Handles are opaque identifiers in the `amduat` namespace:
|
||||||
|
|
||||||
|
```
|
||||||
|
amduat.hash.asl1.id.<hex4>@1
|
||||||
|
```
|
||||||
|
|
||||||
|
`hex4` is the 4-digit lowercase hex of the `HashId` (zero-padded).
|
||||||
|
|
||||||
|
## Descriptor digest rule
|
||||||
|
|
||||||
|
`descriptor_sha256` is computed as SHA-256 over the UTF-8 bytes of the
|
||||||
|
canonical JSON object with these fields **in order**:
|
||||||
|
|
||||||
|
```
|
||||||
|
registry, hash_id, handle, name, digest_len, status, spec_ref, notes
|
||||||
|
```
|
||||||
|
|
||||||
|
The canonical JSON uses no extra whitespace and does **not** include the
|
||||||
|
`descriptor_sha256` field itself.
|
||||||
|
|
||||||
|
## Intended use
|
||||||
|
|
||||||
|
- Source of truth for codegen (C tables, enums) and documentation tables.
|
||||||
|
- `descriptor_sha256` can be treated as the stable digest for mapping entries
|
||||||
|
into graph references or evidence tables.
|
||||||
|
|
@ -1,7 +1,107 @@
|
||||||
#include "amduat/hash/asl1.h"
|
#include "amduat/hash/asl1.h"
|
||||||
|
|
||||||
|
static amduat_hash_asl1_desc_t g_hash_asl1_descs[] = {
|
||||||
|
{0x0000, NULL, 0, {NULL, NULL}},
|
||||||
|
{AMDUAT_HASH_ASL1_ID_SHA256, "HASH-ASL1-256", 32, {NULL, NULL}},
|
||||||
|
{0x0002, "HASH-ASL1-512", 64, {NULL, NULL}},
|
||||||
|
{0x8001, "HASH-ASL1-PQ1", 0, {NULL, NULL}}};
|
||||||
|
|
||||||
|
#ifdef AMDUAT_HASH_ASL1_ENABLE_SHA256_STUB
|
||||||
|
static bool amduat_hash_asl1_sha256_stub(void *ctx,
|
||||||
|
amduat_octets_t input,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t out_len) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
(void)ctx;
|
||||||
|
(void)input;
|
||||||
|
|
||||||
|
if (out == NULL || out_len < 32) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 32; ++i) {
|
||||||
|
out[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
amduat_octets_t amduat_hash_asl1_key(amduat_hash_id_t hash_id, uint8_t out[2]) {
|
amduat_octets_t amduat_hash_asl1_key(amduat_hash_id_t hash_id, uint8_t out[2]) {
|
||||||
out[0] = (uint8_t)(hash_id >> 8);
|
out[0] = (uint8_t)(hash_id >> 8);
|
||||||
out[1] = (uint8_t)(hash_id & 0xff);
|
out[1] = (uint8_t)(hash_id & 0xff);
|
||||||
return amduat_octets(out, 2);
|
return amduat_octets(out, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const amduat_hash_asl1_desc_t *amduat_hash_asl1_desc_lookup(
|
||||||
|
amduat_hash_id_t hash_id) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(g_hash_asl1_descs) / sizeof(g_hash_asl1_descs[0]);
|
||||||
|
++i) {
|
||||||
|
if (g_hash_asl1_descs[i].hash_id == hash_id) {
|
||||||
|
return &g_hash_asl1_descs[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const amduat_hash_asl1_desc_t *amduat_hash_asl1_descs(size_t *out_len) {
|
||||||
|
if (out_len != NULL) {
|
||||||
|
*out_len = sizeof(g_hash_asl1_descs) / sizeof(g_hash_asl1_descs[0]);
|
||||||
|
}
|
||||||
|
return g_hash_asl1_descs;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_hash_asl1_register_impl(amduat_hash_id_t hash_id,
|
||||||
|
amduat_hash_asl1_impl_t impl) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(g_hash_asl1_descs) / sizeof(g_hash_asl1_descs[0]);
|
||||||
|
++i) {
|
||||||
|
if (g_hash_asl1_descs[i].hash_id == hash_id) {
|
||||||
|
g_hash_asl1_descs[i].impl = impl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_hash_asl1_digest(amduat_hash_id_t hash_id,
|
||||||
|
amduat_octets_t input,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t out_len) {
|
||||||
|
const amduat_hash_asl1_desc_t *desc;
|
||||||
|
|
||||||
|
if (out == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc = amduat_hash_asl1_desc_lookup(hash_id);
|
||||||
|
if (desc == NULL || desc->digest_len == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (out_len < desc->digest_len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (desc->impl.digest == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return desc->impl.digest(desc->impl.ctx, input, out, desc->digest_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_hash_asl1_register_sha256_stub(void) {
|
||||||
|
#ifdef AMDUAT_HASH_ASL1_ENABLE_SHA256_STUB
|
||||||
|
amduat_hash_asl1_impl_t impl;
|
||||||
|
|
||||||
|
impl.digest = amduat_hash_asl1_sha256_stub;
|
||||||
|
impl.ctx = NULL;
|
||||||
|
return amduat_hash_asl1_register_impl(AMDUAT_HASH_ASL1_ID_SHA256, impl);
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue