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,74 @@
|
||||
package elydora
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
// base64urlEncode encodes bytes to base64url without padding (RFC 4648 section 5).
|
||||
func base64urlEncode(data []byte) string {
|
||||
return base64.RawURLEncoding.EncodeToString(data)
|
||||
}
|
||||
|
||||
// base64urlDecode decodes a base64url string (with or without padding).
|
||||
func base64urlDecode(s string) ([]byte, error) {
|
||||
return base64.RawURLEncoding.DecodeString(s)
|
||||
}
|
||||
|
||||
// generateNonce generates a 16-byte cryptographically random nonce, base64url encoded.
|
||||
func generateNonce() (string, error) {
|
||||
b := make([]byte, 16)
|
||||
if _, err := io.ReadFull(rand.Reader, b); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return base64urlEncode(b), nil
|
||||
}
|
||||
|
||||
// generateUUIDv7 generates a UUIDv7 (time-ordered) as a string.
|
||||
func generateUUIDv7() (string, error) {
|
||||
now := time.Now()
|
||||
ms := now.UnixMilli()
|
||||
|
||||
var uuid [16]byte
|
||||
|
||||
// Timestamp: 48 bits in big-endian
|
||||
binary.BigEndian.PutUint16(uuid[0:2], uint16(ms>>32))
|
||||
binary.BigEndian.PutUint16(uuid[2:4], uint16(ms>>16))
|
||||
binary.BigEndian.PutUint16(uuid[4:6], uint16(ms))
|
||||
|
||||
// Fill the rest with random data
|
||||
if _, err := io.ReadFull(rand.Reader, uuid[6:]); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Set version 7 (bits 48-51)
|
||||
uuid[6] = (uuid[6] & 0x0F) | 0x70
|
||||
// Set variant 10 (bits 64-65)
|
||||
uuid[8] = (uuid[8] & 0x3F) | 0x80
|
||||
|
||||
return formatUUID(uuid), nil
|
||||
}
|
||||
|
||||
// formatUUID formats a 16-byte UUID as a canonical string.
|
||||
func formatUUID(uuid [16]byte) string {
|
||||
buf := make([]byte, 36)
|
||||
hex := "0123456789abcdef"
|
||||
positions := [16]int{0, 2, 4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 28, 30, 32, 34}
|
||||
for i, p := range positions {
|
||||
buf[p] = hex[uuid[i]>>4]
|
||||
buf[p+1] = hex[uuid[i]&0x0F]
|
||||
}
|
||||
buf[8] = '-'
|
||||
buf[13] = '-'
|
||||
buf[18] = '-'
|
||||
buf[23] = '-'
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
// nowUnixMs returns the current time as Unix milliseconds.
|
||||
func nowUnixMs() int64 {
|
||||
return time.Now().UnixMilli()
|
||||
}
|
||||
Reference in new issue
Block a user