Initial commit: Elydora Open Source — self-hosted audit platform for AI agents
Full self-hosted port of the Elydora tamper-evident audit protocol: - Hono API server with PostgreSQL, Redis, MinIO adapters - Ed25519 signed operations, chain hashing, Merkle epoch rollups - PBKDF2 password hashing, HMAC-SHA256 JWT, 5-role RBAC - Next.js management console - Node.js, Python, and Go SDKs - Docker Compose for local deployment - Helm chart for Kubernetes - Comprehensive security hardening and audit fixes applied Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
15547a8c35
commit
e390e68594
207 files changed
+32790
-63
No files matched your search
@@ -0,0 +1,59 @@
|
||||
"""Utility helpers: UUIDv7, nonce generation, base64url encoding."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import os
|
||||
import struct
|
||||
import time
|
||||
|
||||
|
||||
def base64url_encode(data: bytes) -> str:
|
||||
"""Encode bytes to base64url string with no padding."""
|
||||
return base64.urlsafe_b64encode(data).rstrip(b"=").decode("ascii")
|
||||
|
||||
|
||||
def base64url_decode(s: str) -> bytes:
|
||||
"""Decode a base64url string (with or without padding) to bytes."""
|
||||
s = s.replace("-", "+").replace("_", "/")
|
||||
padding = 4 - len(s) % 4
|
||||
if padding != 4:
|
||||
s += "=" * padding
|
||||
return base64.b64decode(s)
|
||||
|
||||
|
||||
def generate_nonce() -> str:
|
||||
"""Generate a 16-byte random nonce, base64url encoded."""
|
||||
return base64url_encode(os.urandom(16))
|
||||
|
||||
|
||||
def generate_uuidv7() -> str:
|
||||
"""Generate a UUIDv7 (time-ordered, random) as a string.
|
||||
|
||||
Layout (RFC 9562):
|
||||
- 48-bit Unix timestamp in milliseconds
|
||||
- 4-bit version (0b0111)
|
||||
- 12-bit random
|
||||
- 2-bit variant (0b10)
|
||||
- 62-bit random
|
||||
"""
|
||||
timestamp_ms = int(time.time() * 1000)
|
||||
|
||||
# 48-bit timestamp
|
||||
ts_bytes = struct.pack(">Q", timestamp_ms)[2:] # last 6 bytes of 8-byte big-endian
|
||||
|
||||
# 2 bytes: version (4 bits = 0x7) + 12 random bits
|
||||
rand_a = struct.unpack(">H", os.urandom(2))[0]
|
||||
rand_a = (rand_a & 0x0FFF) | 0x7000 # set version nibble
|
||||
|
||||
# 8 bytes: variant (2 bits = 0b10) + 62 random bits
|
||||
rand_b = bytearray(os.urandom(8))
|
||||
rand_b[0] = (rand_b[0] & 0x3F) | 0x80 # set variant bits
|
||||
|
||||
uuid_bytes = ts_bytes + struct.pack(">H", rand_a) + bytes(rand_b)
|
||||
|
||||
hex_str = uuid_bytes.hex()
|
||||
return (
|
||||
f"{hex_str[0:8]}-{hex_str[8:12]}-{hex_str[12:16]}-"
|
||||
f"{hex_str[16:20]}-{hex_str[20:32]}"
|
||||
)
|
||||
Reference in new issue
Block a user