Go API Reference

Side-channel claim limit. Nothing on this page claims constant-time behaviour or side-channel resistance for any target: the side-channel harness covers nothing (finding A48) and no measurement exists. The Rust and C cores are designed for constant time and unmeasured; managed runtimes (JIT, GC, bounds checks) make no timing claim. Where this page names constant-time or side-channel techniques, in prose or in code, they are design intent or recommendations, not measured properties.

Complete API documentation for MetaMUI Crypto Primitives in Go.

Installation

No package is published on a public registry yet (release candidate 1.0.0-rc.7); the coordinates below are the decided public names. Until the launch publishes them, build from the source tree (see the Installation Guide) or install a locally built candidate. The snippet was run against such a candidate; the run is recorded in the source repository’s documents/public-release/evidence/229-documentation.md.

go get github.com/SovereignWallet-Network/metamui-crypto/metamui-crypto-go@v1.0.0-rc.7

There is no root package: import the package of the algorithm you use (mlkem, falcon, mldsa, slhdsa, smaugt, haetae, aimer, ntruplus, blake3, ed25519, sr25519, …). Pure Go, CGO_ENABLED=0.

Quick Start

package main

import (
	"bytes"
	"fmt"

	"github.com/SovereignWallet-Network/metamui-crypto/metamui-crypto-go/mlkem"
)

func main() {
	kem := mlkem.New(mlkem.MLKEM768)
	pk, sk, err := kem.GenerateKeyPair()
	if err != nil {
		panic(err)
	}
	ct, ss, err := kem.Encapsulate(pk)
	if err != nil {
		panic(err)
	}
	ss2, err := kem.Decapsulate(sk, ct)
	if err != nil {
		panic(err)
	}
	fmt.Println(bytes.Equal(ss, ss2))
}

API Documentation

For detailed API documentation, see:

Package Organization

// Core packages
import (
    "github.com/SovereignWallet-Network/metamui-crypto-go"           // Core types and interfaces
    "github.com/SovereignWallet-Network/metamui-crypto-go/hash"      // Hash functions
    "github.com/SovereignWallet-Network/metamui-crypto-go/signature" // Digital signatures
    "github.com/SovereignWallet-Network/metamui-crypto-go/encryption"// Symmetric encryption
    "github.com/SovereignWallet-Network/metamui-crypto-go/kex"       // Key exchange
    "github.com/SovereignWallet-Network/metamui-crypto-go/kdf"       // Key derivation
    "github.com/SovereignWallet-Network/metamui-crypto-go/pqc"       // Post-quantum algorithms
    "github.com/SovereignWallet-Network/metamui-crypto-go/random"    // Secure random
    "github.com/SovereignWallet-Network/metamui-crypto-go/encoding"  // Encoding utilities
)

Goroutine Safety

All functions in the MetaMUI Crypto library are goroutine-safe unless explicitly noted.

Concurrent Operations

package main

import (
    "sync"
    "github.com/SovereignWallet-Network/metamui-crypto-go/hash/blake3"
)

func processFiles(files []string) [][]byte {
    var wg sync.WaitGroup
    hashes := make([][]byte, len(files))
    
    for i, file := range files {
        wg.Add(1)
        go func(index int, filename string) {
            defer wg.Done()
            
            data, _ := os.ReadFile(filename)
            hashes[index] = blake3.Sum256(data)
        }(i, file)
    }
    
    wg.Wait()
    return hashes
}

Thread-Safe Contexts

// Each goroutine needs its own hasher instance
func hashConcurrently(chunks [][]byte) [][]byte {
    results := make([][]byte, len(chunks))
    var wg sync.WaitGroup
    
    for i, chunk := range chunks {
        wg.Add(1)
        go func(index int, data []byte) {
            defer wg.Done()
            
            // Create hasher per goroutine
            h := blake3.New()
            h.Write(data)
            results[index] = h.Sum(nil)
        }(i, chunk)
    }
    
    wg.Wait()
    return results
}

Error Handling

Error Types

import "github.com/SovereignWallet-Network/metamui-crypto-go/errors"

// Common error types
var (
    ErrInvalidKey       = errors.New("invalid key size or format")
    ErrDecryptionFailed = errors.New("decryption failed")
    ErrInvalidSignature = errors.New("signature verification failed")
    ErrInvalidNonce     = errors.New("invalid nonce size")
)

// Error checking
result, err := someOperation()
if err != nil {
    switch {
    case errors.Is(err, crypto.ErrInvalidKey):
        // Handle invalid key
    case errors.Is(err, crypto.ErrDecryptionFailed):
        // Handle decryption failure
    default:
        // Handle other errors
    }
}

Error Wrapping

func processData(data []byte) error {
    key, err := generateKey()
    if err != nil {
        return fmt.Errorf("key generation failed: %w", err)
    }
    
    encrypted, err := encrypt(data, key)
    if err != nil {
        return fmt.Errorf("encryption failed: %w", err)
    }
    
    return nil
}

Interface Design

Common Interfaces

// Hasher interface
type Hasher interface {
    Write(p []byte) (n int, err error)
    Sum(b []byte) []byte
    Reset()
    Size() int
    BlockSize() int
}

// Signer interface
type Signer interface {
    Sign(message []byte) ([]byte, error)
    PublicKey() PublicKey
}

// Cipher interface
type Cipher interface {
    Encrypt(plaintext []byte) ([]byte, error)
    Decrypt(ciphertext []byte) ([]byte, error)
}

Interface Implementation

// Ensure type implements interface
var _ Hasher = (*Blake3)(nil)
var _ Signer = (*Ed25519PrivateKey)(nil)
var _ Cipher = (*ChaCha20Poly1305)(nil)

Hash Functions

SHA-256/512

import "github.com/SovereignWallet-Network/metamui-crypto-go/hash/sha256"
import "github.com/SovereignWallet-Network/metamui-crypto-go/hash/sha512"

// Simple hashing
hash256 := sha256.Sum256(data)
hash512 := sha512.Sum512(data)

// Streaming hash
h := sha256.New()
h.Write(chunk1)
h.Write(chunk2)
hash := h.Sum(nil)

// HMAC
mac := sha256.HMAC(key, message)
valid := sha256.VerifyHMAC(key, message, mac)

BLAKE2b/2s

import "github.com/SovereignWallet-Network/metamui-crypto-go/hash/blake2b"
import "github.com/SovereignWallet-Network/metamui-crypto-go/hash/blake2s"

// Standard BLAKE2b (64 bytes)
hash := blake2b.Sum512(data)

// Custom output size
hash32 := blake2b.Sum256(data)

// Keyed hashing
mac, err := blake2b.SumKeyed(data, key)

// With personalization
h, _ := blake2b.NewWithParams(&blake2b.Config{
    Size:   32,
    Key:    key,
    Salt:   salt,
    Person: []byte("MyApp"),
})
h.Write(data)
hash := h.Sum(nil)

BLAKE3

import "github.com/SovereignWallet-Network/metamui-crypto-go/hash/blake3"

// Standard hash
hash := blake3.Sum256(data)

// Keyed hash
keyedHash := blake3.SumKeyed(data, key)

// Derive key
derivedKey := blake3.DeriveKey(
    "my-context",
    inputKeyMaterial,
    32, // output size
)

// Streaming with New()
h := blake3.New()
for _, chunk := range chunks {
    h.Write(chunk)
}
hash := h.Sum(nil)

// Extended output (XOF)
xof := blake3.NewXOF()
xof.Write(data)
output := make([]byte, 100) // Any size
xof.Read(output)

Digital Signatures

Ed25519

import "github.com/SovereignWallet-Network/metamui-crypto-go/signature/ed25519"

// Generate keypair
keypair, err := ed25519.GenerateKeypair()

// Generate from seed
seed := make([]byte, 32)
rand.Read(seed)
keypair = ed25519.NewKeypairFromSeed(seed)

// Sign
signature, err := keypair.Sign(message)

// Verify
valid := keypair.PublicKey.Verify(message, signature)

// Export/Import keys
publicBytes := keypair.PublicKey.Bytes()
privateBytes := keypair.PrivateKey.Bytes()

publicKey, err := ed25519.PublicKeyFromBytes(publicBytes)
privateKey, err := ed25519.PrivateKeyFromBytes(privateBytes)

// Batch verification
signatures := [][]byte{sig1, sig2, sig3}
messages := [][]byte{msg1, msg2, msg3}
publicKeys := []*ed25519.PublicKey{pk1, pk2, pk3}

results := ed25519.BatchVerify(signatures, messages, publicKeys)

Sr25519

import "github.com/SovereignWallet-Network/metamui-crypto-go/signature/sr25519"

// Generate keypair
keypair, err := sr25519.GenerateKeypair()

// Mini secret key from seed
miniSecret := sr25519.MiniSecretFromSeed(seed)
keypair = miniSecret.ExpandToKeypair()

// Sign with context
signature, err := keypair.SignWithContext(message, []byte("substrate"))

// Verify with context
valid := keypair.PublicKey.VerifyWithContext(
    message, signature, []byte("substrate"))

// VRF (Verifiable Random Function)
output, proof, err := keypair.VRFSign(message)
valid, output2 := keypair.PublicKey.VRFVerify(message, proof)

Encryption

ChaCha20-Poly1305

import "github.com/SovereignWallet-Network/metamui-crypto-go/encryption/chacha20poly1305"

// Create cipher
cipher, err := chacha20poly1305.New(key)

// Generate nonce
nonce := make([]byte, chacha20poly1305.NonceSize)
rand.Read(nonce)

// Encrypt with associated data
ciphertext := cipher.Seal(nil, nonce, plaintext, associatedData)

// Decrypt and verify
plaintext, err := cipher.Open(nil, nonce, ciphertext, associatedData)

// Using XChaCha20-Poly1305 (24-byte nonce)
xcipher, err := chacha20poly1305.NewX(key)
xnonce := make([]byte, chacha20poly1305.XNonceSize)

AES-256-GCM

import "github.com/SovereignWallet-Network/metamui-crypto-go/encryption/aes"

// Create cipher
block, err := aes.NewCipher(key)
gcm, err := aes.NewGCM(block)

// Generate nonce
nonce := make([]byte, gcm.NonceSize())
rand.Read(nonce)

// Encrypt
ciphertext := gcm.Seal(nil, nonce, plaintext, associatedData)

// Decrypt
plaintext, err := gcm.Open(nil, nonce, ciphertext, associatedData)

// Check hardware support
if aes.HasAESNI() {
    fmt.Println("Using AES-NI hardware acceleration")
}

Key Exchange

X25519

import "github.com/SovereignWallet-Network/metamui-crypto-go/kex/x25519"

// Generate keypairs
alicePrivate, alicePublic, _ := x25519.GenerateKeypair()
bobPrivate, bobPublic, _ := x25519.GenerateKeypair()

// Compute shared secrets
aliceShared, _ := x25519.SharedSecret(alicePrivate, bobPublic)
bobShared, _ := x25519.SharedSecret(bobPrivate, alicePublic)

// aliceShared == bobShared

// From seed
privateKey := x25519.NewPrivateKeyFromSeed(seed)
publicKey := x25519.PublicKeyFromPrivate(privateKey)

Post-Quantum Algorithms

ML-KEM-768

import "github.com/SovereignWallet-Network/metamui-crypto-go/pqc/mlkem"

// Generate keypair
keypair, err := mlkem.GenerateKeypair768()

// Encapsulation (sender)
ciphertext, sharedSecret, err := mlkem.Encapsulate768(
    keypair.PublicKey)

// Decapsulation (receiver)
sharedSecret2, err := mlkem.Decapsulate768(
    ciphertext, keypair.PrivateKey)

// Both parties have same shared secret
if !bytes.Equal(sharedSecret, sharedSecret2) {
    panic("shared secrets don't match")
}

// Serialize keys
publicBytes := keypair.PublicKey.Bytes()
privateBytes := keypair.PrivateKey.Bytes()

Dilithium

import "github.com/SovereignWallet-Network/metamui-crypto-go/pqc/dilithium"

// Generate keypair
keypair, err := dilithium.GenerateKeypair3()

// Sign message
signature, err := dilithium.Sign3(message, keypair.PrivateKey)

// Verify signature
valid := dilithium.Verify3(message, signature, keypair.PublicKey)

// Deterministic signatures
signature = dilithium.SignDeterministic3(
    message, keypair.PrivateKey)

// Serialize
publicBytes := keypair.PublicKey.Marshal()
privateBytes := keypair.PrivateKey.Marshal()

// Deserialize
publicKey, _ := dilithium.UnmarshalPublicKey3(publicBytes)
privateKey, _ := dilithium.UnmarshalPrivateKey3(privateBytes)

Key Derivation

Argon2

import "github.com/SovereignWallet-Network/metamui-crypto-go/kdf/argon2"

// Generate salt
salt := make([]byte, 16)
rand.Read(salt)

// Hash password
hash := argon2.Hash(
    password,
    salt,
    &argon2.Config{
        Time:    3,      // iterations
        Memory:  64*1024,// 64 MB
        Threads: 4,      // parallelism
        KeyLen:  32,     // output length
    },
)

// Verify password
valid := argon2.Verify(password, hash)

// IDKey variant
key := argon2.IDKey(
    password, salt,
    3, 64*1024, 4, 32,
)

PBKDF2

import "github.com/SovereignWallet-Network/metamui-crypto-go/kdf/pbkdf2"

// Derive key
key := pbkdf2.Key(
    password,
    salt,
    100000,    // iterations
    32,        // key length
    sha256.New,// PRF
)

// With progress callback
key := pbkdf2.KeyWithProgress(
    password, salt, 100000, 32, sha256.New,
    func(current, total int) {
        fmt.Printf("Progress: %d/%d\n", current, total)
    },
)

HKDF

import "github.com/SovereignWallet-Network/metamui-crypto-go/kdf/hkdf"

// Extract
prk := hkdf.Extract(sha256.New, inputKeyMaterial, salt)

// Expand
okm := make([]byte, 42)
err := hkdf.Expand(sha256.New, prk, info, okm)

// One-shot
reader := hkdf.New(sha256.New, inputKeyMaterial, salt, info)
key := make([]byte, 32)
_, err := io.ReadFull(reader, key)

Context Support

Using context.Context

import (
    "context"
    "time"
)

// Operations with timeout
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

// Argon2 with context (can be cancelled)
hash, err := argon2.HashContext(ctx, password, salt, config)
if err == context.DeadlineExceeded {
    fmt.Println("Operation timed out")
}

// Batch operations with context
results, err := ed25519.BatchVerifyContext(
    ctx, signatures, messages, publicKeys)

// Stream processing with context
func processStream(ctx context.Context, r io.Reader) ([]byte, error) {
    h := blake3.New()
    buf := make([]byte, 4096)
    
    for {
        select {
        case <-ctx.Done():
            return nil, ctx.Err()
        default:
            n, err := r.Read(buf)
            if err == io.EOF {
                return h.Sum(nil), nil
            }
            if err != nil {
                return nil, err
            }
            h.Write(buf[:n])
        }
    }
}

Performance

Buffer Reuse

import "sync"

// Buffer pool for encryption
var bufferPool = sync.Pool{
    New: func() interface{} {
        return make([]byte, 4096)
    },
}

func encryptData(cipher *chacha20poly1305.Cipher, data []byte) []byte {
    // Get buffer from pool
    buf := bufferPool.Get().([]byte)
    defer bufferPool.Put(buf)
    
    // Use buffer for encryption
    nonce := buf[:12]
    rand.Read(nonce)
    
    return cipher.Seal(data[:0], nonce, data, nil)
}

Zero-Allocation APIs

// In-place operations
func xorInPlace(dst, src []byte) {
    for i := range dst {
        dst[i] ^= src[i]
    }
}

// Reuse output buffer
output := make([]byte, 0, len(input)+16)
output = cipher.Seal(output, nonce, input, nil)

// Stack allocation for small buffers
var key [32]byte
rand.Read(key[:])

Parallel Processing

import "golang.org/x/sync/errgroup"

// Parallel file hashing
func hashFiles(files []string) ([][]byte, error) {
    g := new(errgroup.Group)
    hashes := make([][]byte, len(files))
    
    for i, file := range files {
        i, file := i, file // capture loop variables
        g.Go(func() error {
            data, err := os.ReadFile(file)
            if err != nil {
                return err
            }
            hashes[i] = blake3.Sum256(data)
            return nil
        })
    }
    
    if err := g.Wait(); err != nil {
        return nil, err
    }
    return hashes, nil
}

Build Constraints and Tags

Platform-Specific Code

// +build amd64,!noasm

package blake3

// Assembly-optimized implementation for AMD64

// +build !amd64 noasm

package blake3

// Pure Go implementation

Feature Flags

# Build with pure Go implementations
go build -tags noasm

# Build with CGO disabled
CGO_ENABLED=0 go build

# Build with specific features
go build -tags "argon2 blake3 pqc"

CGO Integration

Using C Libraries

// #cgo LDFLAGS: -lcrypto
// #include <openssl/evp.h>
import "C"

func hashWithOpenSSL(data []byte) []byte {
    ctx := C.EVP_MD_CTX_new()
    defer C.EVP_MD_CTX_free(ctx)
    
    C.EVP_DigestInit_ex(ctx, C.EVP_sha256(), nil)
    C.EVP_DigestUpdate(ctx, unsafe.Pointer(&data[0]), C.size_t(len(data)))
    
    hash := make([]byte, 32)
    var size C.uint
    C.EVP_DigestFinal_ex(ctx, (*C.uchar)(&hash[0]), &size)
    
    return hash
}

Utility Functions

Secure Random

import "github.com/SovereignWallet-Network/metamui-crypto-go/random"

// Generate random bytes
randomBytes := random.Bytes(32)

// Generate random integer
randomInt := random.Int()
randomIntN := random.Intn(100) // 0-99

// Fill existing buffer
buffer := make([]byte, 64)
random.Read(buffer)

// Cryptographically secure random reader
reader := random.Reader
io.ReadFull(reader, buffer)

Constant-Time Operations

import "github.com/SovereignWallet-Network/metamui-crypto-go/subtle"

// Constant-time comparison
equal := subtle.ConstantTimeCompare(a, b) == 1

// Constant-time selection
subtle.ConstantTimeSelect(1, x, y) // returns x
subtle.ConstantTimeSelect(0, x, y) // returns y

// Constant-time copy
subtle.ConstantTimeCopy(1, dst, src) // copies src to dst
subtle.ConstantTimeCopy(0, dst, src) // doesn't copy

// Clear sensitive data
subtle.SecureZero(sensitiveData)

Encoding

import "github.com/SovereignWallet-Network/metamui-crypto-go/encoding"

// Hex encoding
hexStr := encoding.HexEncode(data)
decoded, err := encoding.HexDecode(hexStr)

// Base64
b64Str := encoding.Base64Encode(data)
decoded, err := encoding.Base64Decode(b64Str)

// Base64 URL-safe
b64url := encoding.Base64URLEncode(data)
decoded, err := encoding.Base64URLDecode(b64url)

// Base32
b32Str := encoding.Base32Encode(data)
decoded, err := encoding.Base32Decode(b32Str)

Security Best Practices

Secure Memory Handling

import (
    "runtime"
    "github.com/SovereignWallet-Network/metamui-crypto-go/secure"
)

// Lock memory to prevent swapping
func lockMemory(data []byte) {
    secure.Mlock(data)
    defer secure.Munlock(data)
    
    // Use data...
}

// Clear sensitive data
func clearSensitive(data []byte) {
    defer secure.Zero(data)
    // Use data...
}

// Prevent compiler optimizations
func useVolatile(data []byte) {
    runtime.KeepAlive(data)
}

Timing Attack Prevention

// DON'T: Variable-time comparison
if bytes.Equal(computed, expected) { // BAD!
    // ...
}

// DO: Constant-time comparison
if subtle.ConstantTimeCompare(computed, expected) == 1 { // GOOD!
    // ...
}

// DON'T: Early return on mismatch
for i := range computed {
    if computed[i] != expected[i] { // BAD!
        return false
    }
}

// DO: Always check all bytes
equal := 1
for i := range computed {
    equal &= subtle.ConstantTimeByteEq(computed[i], expected[i])
}
return equal == 1

Examples

Encrypted Communication Protocol

package main

import (
    "github.com/SovereignWallet-Network/metamui-crypto-go/pqc/mlkem"
    "github.com/SovereignWallet-Network/metamui-crypto-go/signature/ed25519"
    "github.com/SovereignWallet-Network/metamui-crypto-go/encryption/chacha20poly1305"
    "github.com/SovereignWallet-Network/metamui-crypto-go/kdf/hkdf"
)

type SecureChannel struct {
    sessionKey []byte
    cipher     *chacha20poly1305.Cipher
    nonce      uint64
}

func EstablishChannel(
    ourIdentity *ed25519.Keypair,
    theirPublicKey *ed25519.PublicKey,
    theirKEMKey []byte,
) (*SecureChannel, error) {
    // Generate ephemeral KEM key
    ciphertext, sharedSecret, err := mlkem.Encapsulate768(theirKEMKey)
    if err != nil {
        return nil, err
    }
    
    // Sign the ciphertext
    signature, err := ourIdentity.Sign(ciphertext)
    if err != nil {
        return nil, err
    }
    
    // Send ciphertext and signature to peer...
    // Receive their response...
    
    // Derive session key
    reader := hkdf.New(sha256.New, sharedSecret, nil, []byte("session"))
    sessionKey := make([]byte, 32)
    io.ReadFull(reader, sessionKey)
    
    // Create cipher
    cipher, err := chacha20poly1305.New(sessionKey)
    if err != nil {
        return nil, err
    }
    
    return &SecureChannel{
        sessionKey: sessionKey,
        cipher:     cipher,
    }, nil
}

File Encryption Tool

package main

import (
    "io"
    "os"
    "github.com/SovereignWallet-Network/metamui-crypto-go/encryption/chacha20poly1305"
    "github.com/SovereignWallet-Network/metamui-crypto-go/kdf/argon2"
    "github.com/SovereignWallet-Network/metamui-crypto-go/random"
)

func EncryptFile(inputPath, outputPath, password string) error {
    // Generate salt
    salt := random.Bytes(16)
    
    // Derive key from password
    key := argon2.IDKey(
        []byte(password), salt,
        3, 64*1024, 4, 32,
    )
    
    // Create cipher
    cipher, err := chacha20poly1305.NewX(key)
    if err != nil {
        return err
    }
    
    // Open files
    input, err := os.Open(inputPath)
    if err != nil {
        return err
    }
    defer input.Close()
    
    output, err := os.Create(outputPath)
    if err != nil {
        return err
    }
    defer output.Close()
    
    // Write salt
    output.Write(salt)
    
    // Generate nonce
    nonce := random.Bytes(24)
    output.Write(nonce)
    
    // Encrypt file in chunks
    buffer := make([]byte, 64*1024)
    for {
        n, err := input.Read(buffer)
        if err == io.EOF {
            break
        }
        if err != nil {
            return err
        }
        
        encrypted := cipher.Seal(nil, nonce, buffer[:n], nil)
        output.Write(encrypted)
        
        // Increment nonce
        incrementNonce(nonce)
    }
    
    return nil
}

JWT Token Handling

package jwt

import (
    "encoding/json"
    "time"
    "github.com/SovereignWallet-Network/metamui-crypto-go/signature/ed25519"
    "github.com/SovereignWallet-Network/metamui-crypto-go/encoding"
)

type Claims map[string]interface{}

func CreateToken(claims Claims, key *ed25519.PrivateKey) (string, error) {
    // Add standard claims
    claims["iat"] = time.Now().Unix()
    claims["exp"] = time.Now().Add(time.Hour).Unix()
    
    // Create header
    header := map[string]string{
        "alg": "EdDSA",
        "typ": "JWT",
    }
    
    // Encode header and payload
    headerJSON, _ := json.Marshal(header)
    headerB64 := encoding.Base64URLEncode(headerJSON)
    
    payloadJSON, _ := json.Marshal(claims)
    payloadB64 := encoding.Base64URLEncode(payloadJSON)
    
    // Create signature
    message := headerB64 + "." + payloadB64
    signature, err := key.Sign([]byte(message))
    if err != nil {
        return "", err
    }
    
    // Return complete JWT
    return message + "." + encoding.Base64URLEncode(signature), nil
}

func VerifyToken(token string, key *ed25519.PublicKey) (Claims, error) {
    // Split token
    parts := strings.Split(token, ".")
    if len(parts) != 3 {
        return nil, errors.New("invalid token format")
    }
    
    // Verify signature
    message := parts[0] + "." + parts[1]
    signature, err := encoding.Base64URLDecode(parts[2])
    if err != nil {
        return nil, err
    }
    
    if !key.Verify([]byte(message), signature) {
        return nil, errors.New("invalid signature")
    }
    
    // Decode claims
    payloadJSON, err := encoding.Base64URLDecode(parts[1])
    if err != nil {
        return nil, err
    }
    
    var claims Claims
    err = json.Unmarshal(payloadJSON, &claims)
    return claims, err
}

Testing

Unit Tests

package crypto_test

import (
    "testing"
    "bytes"
    "github.com/SovereignWallet-Network/metamui-crypto-go/signature/ed25519"
)

func TestEd25519SignVerify(t *testing.T) {
    keypair, err := ed25519.GenerateKeypair()
    if err != nil {
        t.Fatal(err)
    }
    
    message := []byte("test message")
    signature, err := keypair.Sign(message)
    if err != nil {
        t.Fatal(err)
    }
    
    if !keypair.PublicKey.Verify(message, signature) {
        t.Error("signature verification failed")
    }
    
    // Modify message
    message[0] ^= 1
    if keypair.PublicKey.Verify(message, signature) {
        t.Error("modified message verification should fail")
    }
}

func BenchmarkBlake3(b *testing.B) {
    data := make([]byte, 1024)
    b.SetBytes(int64(len(data)))
    b.ResetTimer()
    
    for i := 0; i < b.N; i++ {
        _ = blake3.Sum256(data)
    }
}

Fuzz Testing

// +build gofuzzer

package crypto

import "github.com/SovereignWallet-Network/metamui-crypto-go/encryption/chacha20poly1305"

func Fuzz(data []byte) int {
    if len(data) < 32 {
        return -1
    }
    
    key := data[:32]
    cipher, err := chacha20poly1305.New(key)
    if err != nil {
        return 0
    }
    
    // Try to encrypt/decrypt
    nonce := make([]byte, 12)
    encrypted := cipher.Seal(nil, nonce, data[32:], nil)
    decrypted, err := cipher.Open(nil, nonce, encrypted, nil)
    
    if err != nil {
        return 0
    }
    
    if !bytes.Equal(decrypted, data[32:]) {
        panic("decryption mismatch")
    }
    
    return 1
}

See Also