// Package crypto provides quantum-resistant cryptographic primitives for the Synor blockchain. package crypto import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "time" ) // SynorCrypto is the main client for the Crypto SDK type SynorCrypto struct { config Config client *http.Client closed bool Mnemonic *MnemonicClient Keypairs *KeypairClient Signing *SigningClient Falcon *FalconClient Sphincs *SphincsClient KDF *KDFClient Hash *HashClient Negotiation *NegotiationClient } // New creates a new SynorCrypto client func New(config Config) *SynorCrypto { if config.Endpoint == "" { config.Endpoint = DefaultEndpoint } if config.Timeout == 0 { config.Timeout = 30000 } if config.Retries == 0 { config.Retries = 3 } if config.DefaultNetwork == "" { config.DefaultNetwork = NetworkMainnet } c := &SynorCrypto{ config: config, client: &http.Client{ Timeout: time.Duration(config.Timeout) * time.Millisecond, }, } c.Mnemonic = &MnemonicClient{crypto: c} c.Keypairs = &KeypairClient{crypto: c} c.Signing = &SigningClient{crypto: c} c.Falcon = &FalconClient{crypto: c} c.Sphincs = &SphincsClient{crypto: c} c.KDF = &KDFClient{crypto: c} c.Hash = &HashClient{crypto: c} c.Negotiation = &NegotiationClient{crypto: c} return c } // DefaultNetwork returns the default network func (c *SynorCrypto) DefaultNetwork() Network { return c.config.DefaultNetwork } // HealthCheck checks if the service is healthy func (c *SynorCrypto) HealthCheck(ctx context.Context) (bool, error) { var result map[string]interface{} if err := c.get(ctx, "/health", &result); err != nil { return false, nil } status, _ := result["status"].(string) return status == "healthy", nil } // GetInfo returns service information func (c *SynorCrypto) GetInfo(ctx context.Context) (map[string]interface{}, error) { var result map[string]interface{} err := c.get(ctx, "/info", &result) return result, err } // Close closes the client func (c *SynorCrypto) Close() { c.closed = true } // IsClosed returns true if the client is closed func (c *SynorCrypto) IsClosed() bool { return c.closed } func (c *SynorCrypto) get(ctx context.Context, path string, result interface{}) error { if c.closed { return NewCryptoError("Client has been closed", "CLIENT_CLOSED") } req, err := http.NewRequestWithContext(ctx, "GET", c.config.Endpoint+path, nil) if err != nil { return err } c.setHeaders(req) resp, err := c.client.Do(req) if err != nil { return err } defer resp.Body.Close() return c.handleResponse(resp, result) } func (c *SynorCrypto) post(ctx context.Context, path string, body interface{}, result interface{}) error { if c.closed { return NewCryptoError("Client has been closed", "CLIENT_CLOSED") } var reqBody io.Reader if body != nil { jsonBody, err := json.Marshal(body) if err != nil { return err } reqBody = bytes.NewBuffer(jsonBody) } req, err := http.NewRequestWithContext(ctx, "POST", c.config.Endpoint+path, reqBody) if err != nil { return err } c.setHeaders(req) resp, err := c.client.Do(req) if err != nil { return err } defer resp.Body.Close() return c.handleResponse(resp, result) } func (c *SynorCrypto) setHeaders(req *http.Request) { req.Header.Set("Authorization", "Bearer "+c.config.APIKey) req.Header.Set("Content-Type", "application/json") req.Header.Set("X-SDK-Version", "go/0.1.0") } func (c *SynorCrypto) handleResponse(resp *http.Response, result interface{}) error { body, err := io.ReadAll(resp.Body) if err != nil { return err } if resp.StatusCode >= 400 { var errResp map[string]interface{} json.Unmarshal(body, &errResp) msg := fmt.Sprintf("HTTP %d", resp.StatusCode) code := "" if m, ok := errResp["message"].(string); ok { msg = m } if c, ok := errResp["code"].(string); ok { code = c } return NewCryptoError(msg, code) } return json.Unmarshal(body, result) } // ============================================================================ // Mnemonic Client // ============================================================================ // MnemonicClient handles mnemonic operations type MnemonicClient struct { crypto *SynorCrypto } // Generate creates a new random mnemonic func (c *MnemonicClient) Generate(ctx context.Context, wordCount int) (*Mnemonic, error) { var result mnemonicResponse err := c.crypto.post(ctx, "/mnemonic/generate", map[string]int{"word_count": wordCount}, &result) if err != nil { return nil, err } return result.toMnemonic() } // FromPhrase creates a mnemonic from a phrase func (c *MnemonicClient) FromPhrase(ctx context.Context, phrase string) (*Mnemonic, error) { var result mnemonicResponse err := c.crypto.post(ctx, "/mnemonic/from-phrase", map[string]string{"phrase": phrase}, &result) if err != nil { return nil, err } return result.toMnemonic() } // FromEntropy creates a mnemonic from entropy func (c *MnemonicClient) FromEntropy(ctx context.Context, entropy []byte) (*Mnemonic, error) { var result mnemonicResponse err := c.crypto.post(ctx, "/mnemonic/from-entropy", map[string]string{ "entropy": EncodeBase64(entropy), }, &result) if err != nil { return nil, err } return result.toMnemonic() } // Validate checks if a phrase is valid func (c *MnemonicClient) Validate(ctx context.Context, phrase string) (*MnemonicValidation, error) { var result MnemonicValidation err := c.crypto.post(ctx, "/mnemonic/validate", map[string]string{"phrase": phrase}, &result) return &result, err } // ToSeed derives a seed from a mnemonic func (c *MnemonicClient) ToSeed(ctx context.Context, phrase string, passphrase string) ([]byte, error) { var result struct { Seed string `json:"seed"` } err := c.crypto.post(ctx, "/mnemonic/to-seed", map[string]string{ "phrase": phrase, "passphrase": passphrase, }, &result) if err != nil { return nil, err } return DecodeBase64(result.Seed) } // SuggestWords suggests completions for a partial word func (c *MnemonicClient) SuggestWords(ctx context.Context, partial string, limit int) ([]string, error) { var result struct { Suggestions []string `json:"suggestions"` } err := c.crypto.post(ctx, "/mnemonic/suggest", map[string]interface{}{ "partial": partial, "limit": limit, }, &result) return result.Suggestions, err } type mnemonicResponse struct { Phrase string `json:"phrase"` Words []string `json:"words"` WordCount int `json:"word_count"` Entropy string `json:"entropy"` } func (r *mnemonicResponse) toMnemonic() (*Mnemonic, error) { entropy, _ := DecodeBase64(r.Entropy) return &Mnemonic{ Phrase: r.Phrase, Words: r.Words, WordCount: r.WordCount, Entropy: entropy, }, nil } // ============================================================================ // Keypair Client // ============================================================================ // KeypairClient handles keypair operations type KeypairClient struct { crypto *SynorCrypto } // Generate creates a new random keypair func (c *KeypairClient) Generate(ctx context.Context) (*HybridKeypair, error) { var result keypairResponse err := c.crypto.post(ctx, "/keypair/generate", nil, &result) if err != nil { return nil, err } return result.toKeypair() } // FromMnemonic creates a keypair from a mnemonic func (c *KeypairClient) FromMnemonic(ctx context.Context, phrase string, passphrase string) (*HybridKeypair, error) { var result keypairResponse err := c.crypto.post(ctx, "/keypair/from-mnemonic", map[string]string{ "phrase": phrase, "passphrase": passphrase, }, &result) if err != nil { return nil, err } return result.toKeypair() } // FromSeed creates a keypair from a seed func (c *KeypairClient) FromSeed(ctx context.Context, seed []byte) (*HybridKeypair, error) { var result keypairResponse err := c.crypto.post(ctx, "/keypair/from-seed", map[string]string{ "seed": EncodeBase64(seed), }, &result) if err != nil { return nil, err } return result.toKeypair() } // GetAddress gets the address for a public key func (c *KeypairClient) GetAddress(ctx context.Context, pk *HybridPublicKey, network Network) (*Address, error) { var result Address err := c.crypto.post(ctx, "/keypair/address", map[string]interface{}{ "public_key": map[string]string{ "ed25519": EncodeBase64(pk.Ed25519), "dilithium": EncodeBase64(pk.Dilithium), }, "network": network, }, &result) return &result, err } type keypairResponse struct { PublicKey struct { Ed25519 string `json:"ed25519"` Dilithium string `json:"dilithium"` } `json:"public_key"` SecretKey struct { Ed25519Seed string `json:"ed25519_seed"` MasterSeed string `json:"master_seed"` } `json:"secret_key"` Addresses map[string]string `json:"addresses"` } func (r *keypairResponse) toKeypair() (*HybridKeypair, error) { ed25519, _ := DecodeBase64(r.PublicKey.Ed25519) dilithium, _ := DecodeBase64(r.PublicKey.Dilithium) ed25519Seed, _ := DecodeBase64(r.SecretKey.Ed25519Seed) masterSeed, _ := DecodeBase64(r.SecretKey.MasterSeed) addresses := make(map[Network]string) for k, v := range r.Addresses { addresses[Network(k)] = v } return &HybridKeypair{ PublicKey: &HybridPublicKey{ Ed25519: ed25519, Dilithium: dilithium, }, SecretKey: &SecretKey{ Ed25519Seed: ed25519Seed, MasterSeed: masterSeed, }, addresses: addresses, }, nil } // ============================================================================ // Signing Client // ============================================================================ // SigningClient handles signing operations type SigningClient struct { crypto *SynorCrypto } // Sign signs a message with a hybrid keypair func (c *SigningClient) Sign(ctx context.Context, kp *HybridKeypair, message []byte) (*HybridSignature, error) { var result struct { Ed25519 string `json:"ed25519"` Dilithium string `json:"dilithium"` } err := c.crypto.post(ctx, "/sign/hybrid", map[string]interface{}{ "secret_key": map[string]string{ "ed25519_seed": EncodeBase64(kp.SecretKey.Ed25519Seed), "master_seed": EncodeBase64(kp.SecretKey.MasterSeed), }, "message": EncodeBase64(message), }, &result) if err != nil { return nil, err } ed25519, _ := DecodeBase64(result.Ed25519) dilithium, _ := DecodeBase64(result.Dilithium) return &HybridSignature{ Ed25519: ed25519, Dilithium: dilithium, }, nil } // Verify verifies a hybrid signature func (c *SigningClient) Verify(ctx context.Context, pk *HybridPublicKey, message []byte, sig *HybridSignature) (bool, error) { var result struct { Valid bool `json:"valid"` } err := c.crypto.post(ctx, "/sign/verify", map[string]interface{}{ "public_key": map[string]string{ "ed25519": EncodeBase64(pk.Ed25519), "dilithium": EncodeBase64(pk.Dilithium), }, "message": EncodeBase64(message), "signature": map[string]string{ "ed25519": EncodeBase64(sig.Ed25519), "dilithium": EncodeBase64(sig.Dilithium), }, }, &result) return result.Valid, err } // SignEd25519 signs with Ed25519 only func (c *SigningClient) SignEd25519(ctx context.Context, secretKey []byte, message []byte) ([]byte, error) { var result struct { Signature string `json:"signature"` } err := c.crypto.post(ctx, "/sign/ed25519", map[string]string{ "secret_key": EncodeBase64(secretKey), "message": EncodeBase64(message), }, &result) if err != nil { return nil, err } return DecodeBase64(result.Signature) } // ============================================================================ // Falcon Client // ============================================================================ // FalconClient handles Falcon operations type FalconClient struct { crypto *SynorCrypto } // Generate creates a Falcon keypair func (c *FalconClient) Generate(ctx context.Context, variant FalconVariant) (*FalconKeypair, error) { var result map[string]interface{} err := c.crypto.post(ctx, "/falcon/generate", map[string]string{"variant": string(variant)}, &result) if err != nil { return nil, err } // Parse response into FalconKeypair return parseFalconKeypair(result, variant) } // Sign signs with Falcon func (c *FalconClient) Sign(ctx context.Context, kp *FalconKeypair, message []byte) (*FalconSignature, error) { var result struct { Signature string `json:"signature"` Variant string `json:"variant"` } err := c.crypto.post(ctx, "/falcon/sign", map[string]string{ "variant": string(kp.Variant), "secret_key": EncodeBase64(kp.SecretKey.Bytes), "message": EncodeBase64(message), }, &result) if err != nil { return nil, err } sigBytes, _ := DecodeBase64(result.Signature) return &FalconSignature{ Variant: FalconVariant(result.Variant), Bytes: sigBytes, }, nil } // Verify verifies a Falcon signature func (c *FalconClient) Verify(ctx context.Context, publicKey []byte, message []byte, sig *FalconSignature) (bool, error) { var result struct { Valid bool `json:"valid"` } err := c.crypto.post(ctx, "/falcon/verify", map[string]interface{}{ "variant": sig.Variant, "public_key": EncodeBase64(publicKey), "message": EncodeBase64(message), "signature": EncodeBase64(sig.Bytes), }, &result) return result.Valid, err } func parseFalconKeypair(data map[string]interface{}, variant FalconVariant) (*FalconKeypair, error) { pk := data["public_key"].(map[string]interface{}) sk := data["secret_key"].(map[string]interface{}) pkBytes, _ := DecodeBase64(pk["bytes"].(string)) skBytes, _ := DecodeBase64(sk["bytes"].(string)) return &FalconKeypair{ Variant: variant, PublicKey: &FalconPublicKey{Variant: variant, Bytes: pkBytes}, SecretKey: &FalconSecretKey{Variant: variant, Bytes: skBytes}, }, nil } // ============================================================================ // SPHINCS+ Client // ============================================================================ // SphincsClient handles SPHINCS+ operations type SphincsClient struct { crypto *SynorCrypto } // Generate creates a SPHINCS+ keypair func (c *SphincsClient) Generate(ctx context.Context, variant SphincsVariant) (*SphincsKeypair, error) { var result map[string]interface{} err := c.crypto.post(ctx, "/sphincs/generate", map[string]string{"variant": string(variant)}, &result) if err != nil { return nil, err } return parseSphincsKeypair(result, variant) } // Sign signs with SPHINCS+ func (c *SphincsClient) Sign(ctx context.Context, kp *SphincsKeypair, message []byte) (*SphincsSignature, error) { var result struct { Signature string `json:"signature"` Variant string `json:"variant"` } err := c.crypto.post(ctx, "/sphincs/sign", map[string]string{ "variant": string(kp.Variant), "secret_key": EncodeBase64(kp.SecretKey.Bytes), "message": EncodeBase64(message), }, &result) if err != nil { return nil, err } sigBytes, _ := DecodeBase64(result.Signature) return &SphincsSignature{ Variant: SphincsVariant(result.Variant), Bytes: sigBytes, }, nil } // Verify verifies a SPHINCS+ signature func (c *SphincsClient) Verify(ctx context.Context, publicKey []byte, message []byte, sig *SphincsSignature) (bool, error) { var result struct { Valid bool `json:"valid"` } err := c.crypto.post(ctx, "/sphincs/verify", map[string]interface{}{ "variant": sig.Variant, "public_key": EncodeBase64(publicKey), "message": EncodeBase64(message), "signature": EncodeBase64(sig.Bytes), }, &result) return result.Valid, err } func parseSphincsKeypair(data map[string]interface{}, variant SphincsVariant) (*SphincsKeypair, error) { pk := data["public_key"].(map[string]interface{}) sk := data["secret_key"].(map[string]interface{}) pkBytes, _ := DecodeBase64(pk["bytes"].(string)) skBytes, _ := DecodeBase64(sk["bytes"].(string)) return &SphincsKeypair{ Variant: variant, PublicKey: &SphincsPublicKey{Variant: variant, Bytes: pkBytes}, SecretKey: &SphincsSecretKey{Variant: variant, Bytes: skBytes}, }, nil } // ============================================================================ // KDF Client // ============================================================================ // KDFClient handles key derivation type KDFClient struct { crypto *SynorCrypto } // DeriveKey derives a key using HKDF func (c *KDFClient) DeriveKey(ctx context.Context, seed []byte, config *DerivationConfig) ([]byte, error) { body := map[string]interface{}{ "seed": EncodeBase64(seed), "output_length": config.OutputLength, } if config.Salt != nil { body["salt"] = EncodeBase64(config.Salt) } if config.Info != nil { body["info"] = EncodeBase64(config.Info) } var result struct { Key string `json:"key"` } err := c.crypto.post(ctx, "/kdf/hkdf", body, &result) if err != nil { return nil, err } return DecodeBase64(result.Key) } // DeriveFromPassword derives a key from a password func (c *KDFClient) DeriveFromPassword(ctx context.Context, password []byte, config *PasswordDerivationConfig) ([]byte, error) { var result struct { Key string `json:"key"` } err := c.crypto.post(ctx, "/kdf/pbkdf2", map[string]interface{}{ "password": EncodeBase64(password), "salt": EncodeBase64(config.Salt), "iterations": config.Iterations, "output_length": config.OutputLength, }, &result) if err != nil { return nil, err } return DecodeBase64(result.Key) } // DeriveChildKey derives a child key func (c *KDFClient) DeriveChildKey(ctx context.Context, parentKey, chainCode []byte, index int) ([]byte, []byte, error) { var result struct { Key string `json:"key"` ChainCode string `json:"chain_code"` } err := c.crypto.post(ctx, "/kdf/child", map[string]interface{}{ "parent_key": EncodeBase64(parentKey), "chain_code": EncodeBase64(chainCode), "index": index, }, &result) if err != nil { return nil, nil, err } key, _ := DecodeBase64(result.Key) cc, _ := DecodeBase64(result.ChainCode) return key, cc, nil } // ============================================================================ // Hash Client // ============================================================================ // HashClient handles hashing operations type HashClient struct { crypto *SynorCrypto } // SHA3_256 computes SHA3-256 hash func (c *HashClient) SHA3_256(ctx context.Context, data []byte) (*Hash256, error) { var result struct { Hash string `json:"hash"` } err := c.crypto.post(ctx, "/hash/sha3-256", map[string]string{ "data": EncodeBase64(data), }, &result) if err != nil { return nil, err } hashBytes, _ := DecodeBase64(result.Hash) return &Hash256{Bytes: hashBytes, Hex: result.Hash}, nil } // Blake3 computes BLAKE3 hash func (c *HashClient) Blake3(ctx context.Context, data []byte) (*Hash256, error) { var result struct { Hash string `json:"hash"` } err := c.crypto.post(ctx, "/hash/blake3", map[string]string{ "data": EncodeBase64(data), }, &result) if err != nil { return nil, err } hashBytes, _ := DecodeBase64(result.Hash) return &Hash256{Bytes: hashBytes, Hex: result.Hash}, nil } // ============================================================================ // Negotiation Client // ============================================================================ // NegotiationClient handles algorithm negotiation type NegotiationClient struct { crypto *SynorCrypto } // GetCapabilities returns local capabilities func (c *NegotiationClient) GetCapabilities(ctx context.Context) (*AlgorithmCapabilities, error) { var result AlgorithmCapabilities err := c.crypto.get(ctx, "/negotiation/capabilities", &result) return &result, err } // Negotiate negotiates with a peer func (c *NegotiationClient) Negotiate(ctx context.Context, peerCaps *AlgorithmCapabilities, policy *NegotiationPolicy) (*NegotiationResult, error) { var result NegotiationResult err := c.crypto.post(ctx, "/negotiation/negotiate", map[string]interface{}{ "peer_capabilities": peerCaps, "policy": policy, }, &result) return &result, err }