mirror of
https://github.com/sonr-io/sonr.git
synced 2026-08-02 17:31:39 +00:00
Feat/1285 es ucan formatting (#1302)
* feat: Add Enclave Usage Examples * feat(es/ucan): Add comprehensive integration tests - Create integration.test.ts with full UCAN token lifecycle testing - Cover end-to-end token creation, parsing, and validation - Test capability attenuation and delegation chains - Validate multi-algorithm support and timestamp scenarios - Implement error recovery and performance test scenarios 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com> * No commit suggestions generated * No commit suggestions generated * chore: Remove migrated components and add migration documentation Removed all code and references for components that have been moved to separate repositories: **Moved to sonr-io/hway:** - bridge/ - HTTP service with OAuth2/OIDC/WebAuthn handlers - cmd/hway/ - Highway service binary - internal/migrations/ - PostgreSQL schema migrations **Moved to sonr-io/motr:** - cmd/motr/ - Motor worker service (WASM vault operations) - cmd/vault/ - Vault CLI tool - crypto/ - Comprehensive cryptographic library - packages/ - TypeScript SDK packages (es, sdk, ui, com, pkl) - web/auth/ - Authentication web application - web/dash/ - Dashboard web application **Updated Configuration:** - Makefile: Removed build/test/release targets for moved components - CLAUDE.md: Simplified to focus on core blockchain components - devbox.json: Removed scripts for moved services - docker-compose.yml: Removed hway, postgres, redis, auth, dash services - .github/scopes.yml: Removed CI scopes for migrated components - .goreleaser.yml: Updated release configuration **Added Migration Documentation:** - MIGRATE_HWAY.md: Comprehensive Highway service architecture and migration guide - MIGRATE_MOTR.md: Comprehensive Motor/Worker/Vault architecture and migration guide These migration documents provide complete context for setting up the new repositories including architecture diagrams, component breakdowns, API documentation, and migration checklists. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * No commit suggestions generated * chore: Remove contracts references and documentation Removed all references to the contracts directory that was migrated to a separate repository. **Changes:** - .gitignore: Removed contract-specific ignore patterns for DAO and wSNR contracts - .gitignore: Removed hway and motr binary references (already migrated) - .rgignore: Removed contracts, chains, and crypto directory references - docs/reference/contracts/: Removed DAO.mdx and wSNR.mdx documentation files This completes the cleanup of migrated components from the repository. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * docs: add crypto library migration documentation Added comprehensive migration documentation for the crypto library that was moved to sonr-io/crypto repository. This documentation provides complete context for understanding the cryptographic primitives and protocols used throughout the Sonr ecosystem. ## Key Documentation Added ### MIGRATE_CRYPTO.md Complete documentation of the crypto library covering: **Core Cryptographic Primitives** - Elliptic curve implementations (Ed25519, Secp256k1, P-256, BLS12-381, Pallas/Vesta) - Native curve arithmetic with optimized field operations - Pairing-friendly curves for BLS signatures **Multi-Party Computation (MPC)** - MPC enclave for vault key generation and management - Threshold cryptography (TECDSA, TED25519 with FROST protocol) - Distributed Key Generation (DKG) via Gennaro and FROST protocols - Secret sharing schemes (Shamir, Feldman VSS, Pedersen VSS) **Digital Signature Schemes** - BLS signatures with aggregation support - BBS+ signatures for selective disclosure - Schnorr signatures (standard and Mina/NEM variants) - ECDSA with deterministic nonce generation **Zero-Knowledge Proofs** - Bulletproofs for range proofs - Inner Product Arguments (IPA) - Batch verification support **Advanced Cryptographic Protocols** - Cryptographic accumulators for set membership proofs - Paillier homomorphic encryption - Oblivious Transfer (OT) protocols - Verifiable Random Functions (VRF) **Key Management & Identity** - DID key management with multi-chain support - Multi-algorithm public key handling - Wallet address derivation (Bitcoin, Ethereum, Cosmos, Solana, etc.) **UCAN Integration** - User-Controlled Authorization Networks - Capability delegation and attenuation - JWT-based capability tokens - MPC-enabled UCAN signing **Security Utilities** - AEAD encryption (AES-GCM, AES-SIV) - Argon2 key derivation - ECIES encryption - Secure memory handling ### MIGRATE_MOTR.md Updates Updated Motor migration documentation to clarify that the crypto library is now a separate external dependency at github.com/sonr-io/crypto v1.0.1 ## Repository Context The crypto library has been successfully migrated to its own repository and is published as a Go module. It serves as the foundational cryptographic layer for: - Sonr blockchain (snrd) - DID signatures, vault operations - Highway service (hway) - UCAN token signing, WebAuthn - Motor/Worker (motr) - MPC vault operations, threshold signatures ## Integration Impact All Sonr ecosystem components now depend on the external crypto library: ```go require github.com/sonr-io/crypto v1.0.1 ``` The migration enables independent versioning and maintenance of cryptographic primitives while maintaining security and compatibility across the ecosystem. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * No commit suggestions generated * No commit suggestions generated * No commit suggestions generated --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,6 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
webauthnutils "github.com/sonr-io/sonr/types/webauthn"
|
||||
"github.com/sonr-io/sonr/x/did/client/server"
|
||||
"github.com/sonr-io/sonr/x/did/types"
|
||||
)
|
||||
@@ -525,10 +524,18 @@ func broadcastWebAuthnCredential(
|
||||
}
|
||||
|
||||
// generateAddressFromWebAuthn generates a deterministic address from WebAuthn credential
|
||||
// using the centralized utility function from types/webauthn
|
||||
func generateAddressFromWebAuthn(credential *server.WebAuthnCredential) sdk.AccAddress {
|
||||
// Use the centralized address generation to ensure consistency
|
||||
return webauthnutils.GenerateAddressFromCredential(credential.CredentialID)
|
||||
// Use the local types package for address generation
|
||||
// It returns a hex string with 0x prefix
|
||||
addrHex := types.GenerateAddressFromCredential(credential.CredentialID)
|
||||
// Remove 0x prefix
|
||||
addrHex = strings.TrimPrefix(addrHex, "0x")
|
||||
// Decode hex to bytes
|
||||
addrBytes := make([]byte, 20)
|
||||
for i := 0; i < 20; i++ {
|
||||
fmt.Sscanf(addrHex[i*2:i*2+2], "%02x", &addrBytes[i])
|
||||
}
|
||||
return sdk.AccAddress(addrBytes)
|
||||
}
|
||||
|
||||
// promptForUsername prompts the user for a username using standard input
|
||||
|
||||
@@ -12,8 +12,9 @@ import (
|
||||
|
||||
"cosmossdk.io/log"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/sonr-io/sonr/types/webauthn"
|
||||
"github.com/sonr-io/sonr/types/webauthn/webauthncbor"
|
||||
"github.com/sonr-io/common/webauthn"
|
||||
"github.com/sonr-io/common/webauthn/webauthncbor"
|
||||
didtypes "github.com/sonr-io/sonr/x/did/types"
|
||||
)
|
||||
|
||||
var logger = log.NewLogger(os.Stderr)
|
||||
@@ -544,8 +545,8 @@ func generateChallenge() (string, error) {
|
||||
|
||||
// verifyClientData verifies the client data JSON and challenge using centralized WebAuthn validation
|
||||
func verifyClientData(clientDataJSON, expectedChallenge string) error {
|
||||
// Parse client data using the centralized WebAuthn protocol parser
|
||||
clientData, err := webauthn.ValidateClientDataJSONFormat(clientDataJSON)
|
||||
// Parse client data using the local types validation
|
||||
clientData, err := didtypes.ValidateClientDataJSONFormat(clientDataJSON)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse client data: %w", err)
|
||||
}
|
||||
@@ -581,8 +582,8 @@ func verifyClientData(clientDataJSON, expectedChallenge string) error {
|
||||
|
||||
// verifyClientDataForAuthentication verifies the client data JSON and challenge for authentication
|
||||
func verifyClientDataForAuthentication(clientDataJSON, expectedChallenge string) error {
|
||||
// Parse client data using the centralized WebAuthn protocol parser
|
||||
clientData, err := webauthn.ValidateClientDataJSONFormat(clientDataJSON)
|
||||
// Parse client data using the local types validation
|
||||
clientData, err := didtypes.ValidateClientDataJSONFormat(clientDataJSON)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse client data: %w", err)
|
||||
}
|
||||
@@ -673,8 +674,8 @@ func processWebAuthnRegistration(credential *WebAuthnCredential) error {
|
||||
|
||||
// extractOriginFromClientData extracts the origin from client data JSON using centralized WebAuthn parsing
|
||||
func extractOriginFromClientData(clientDataJSON string) (string, error) {
|
||||
// Use the centralized WebAuthn client data parser
|
||||
clientData, err := webauthn.ValidateClientDataJSONFormat(clientDataJSON)
|
||||
// Use the local types validation
|
||||
clientData, err := didtypes.ValidateClientDataJSONFormat(clientDataJSON)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to parse client data: %w", err)
|
||||
}
|
||||
@@ -688,8 +689,8 @@ func extractOriginFromClientData(clientDataJSON string) (string, error) {
|
||||
|
||||
// extractPublicKeyFromAttestation extracts public key and algorithm from attestation object using centralized WebAuthn parsing
|
||||
func extractPublicKeyFromAttestation(attestationObject string) ([]byte, int32, error) {
|
||||
// Use the centralized WebAuthn attestation validation first
|
||||
if err := webauthn.ValidateAttestationObjectFormat(attestationObject); err != nil {
|
||||
// Use the local types validation first
|
||||
if err := didtypes.ValidateAttestationObjectFormat(attestationObject); err != nil {
|
||||
return nil, 0, fmt.Errorf("invalid attestation object format: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,9 @@ import (
|
||||
"golang.org/x/crypto/sha3"
|
||||
|
||||
apiv1 "github.com/sonr-io/sonr/api/did/v1"
|
||||
"github.com/sonr-io/sonr/crypto/mpc"
|
||||
"github.com/sonr-io/sonr/types/webauthn"
|
||||
"github.com/sonr-io/sonr/types/webauthn/webauthncose"
|
||||
"github.com/sonr-io/crypto/mpc"
|
||||
"github.com/sonr-io/common/webauthn"
|
||||
"github.com/sonr-io/common/webauthn/webauthncose"
|
||||
"github.com/sonr-io/sonr/x/did/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/sonr-io/sonr/crypto/keys"
|
||||
"github.com/sonr-io/sonr/crypto/ucan"
|
||||
"github.com/sonr-io/crypto/keys"
|
||||
"github.com/sonr-io/crypto/ucan"
|
||||
"github.com/sonr-io/sonr/x/did/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"lukechampine.com/blake3"
|
||||
|
||||
apiv1 "github.com/sonr-io/sonr/api/did/v1"
|
||||
"github.com/sonr-io/sonr/types/webauthn"
|
||||
"github.com/sonr-io/common/webauthn"
|
||||
"github.com/sonr-io/sonr/x/did/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/sonr-io/sonr/crypto/ucan"
|
||||
"github.com/sonr-io/crypto/ucan"
|
||||
"github.com/sonr-io/sonr/x/did/types"
|
||||
)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/sonr-io/sonr/types/webauthn"
|
||||
"github.com/sonr-io/common/webauthn"
|
||||
"github.com/sonr-io/sonr/x/did/types"
|
||||
)
|
||||
|
||||
@@ -160,7 +160,7 @@ func (v *WebAuthnControllerVerifier) verifyWebAuthnAssertion(
|
||||
// Additional Sonr-specific validations
|
||||
|
||||
// Verify the credential origin matches what's stored
|
||||
clientData, err := webauthn.ValidateClientDataJSONFormat(assertion.ClientDataJSON)
|
||||
clientData, err := types.ValidateClientDataJSONFormat(assertion.ClientDataJSON)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to validate client data JSON: %w", err)
|
||||
}
|
||||
@@ -174,7 +174,7 @@ func (v *WebAuthnControllerVerifier) verifyWebAuthnAssertion(
|
||||
}
|
||||
|
||||
// Verify the algorithm is supported
|
||||
if err := webauthn.ValidateAlgorithmSupport(credential.Algorithm); err != nil {
|
||||
if err := types.ValidateAlgorithmSupport(credential.Algorithm); err != nil {
|
||||
return fmt.Errorf("algorithm validation failed: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
webauthn "github.com/sonr-io/sonr/types/webauthn"
|
||||
"github.com/sonr-io/sonr/types/webauthn/webauthncbor"
|
||||
webauthn "github.com/sonr-io/common/webauthn"
|
||||
"github.com/sonr-io/common/webauthn/webauthncbor"
|
||||
"github.com/sonr-io/sonr/x/did/types"
|
||||
)
|
||||
|
||||
@@ -51,8 +51,8 @@ func (k Keeper) ProcessWebAuthnRegistration(
|
||||
CreatedAt: sdkCtx.BlockTime().Unix(),
|
||||
}
|
||||
|
||||
// Validate the WebAuthn credential using centralized validation
|
||||
if err := webauthn.ValidateStructure(webAuthnCredential); err != nil {
|
||||
// Validate the WebAuthn credential using local types validation
|
||||
if err := types.ValidateStructure(webAuthnCredential); err != nil {
|
||||
return nil, fmt.Errorf("WebAuthn credential validation failed: %w", err)
|
||||
}
|
||||
|
||||
@@ -218,8 +218,8 @@ func (k Keeper) isValidLocalhost(origin string) bool {
|
||||
// extractPublicKeyFromAttestation extracts the public key from WebAuthn attestation object
|
||||
// Now leverages the full WebAuthn protocol implementation for proper CBOR parsing
|
||||
func (k Keeper) extractPublicKeyFromAttestation(attestationObject string) ([]byte, int32, error) {
|
||||
// Use the centralized WebAuthn protocol validation to extract public key
|
||||
if err := webauthn.ValidateAttestationObjectFormat(attestationObject); err != nil {
|
||||
// Use the local types validation to extract public key
|
||||
if err := types.ValidateAttestationObjectFormat(attestationObject); err != nil {
|
||||
return nil, 0, fmt.Errorf("invalid attestation object format: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/sonr-io/sonr/types/webauthn"
|
||||
"github.com/sonr-io/sonr/types/webauthn/webauthncbor"
|
||||
"github.com/sonr-io/sonr/types/webauthn/webauthncose"
|
||||
"github.com/sonr-io/common/webauthn"
|
||||
"github.com/sonr-io/common/webauthn/webauthncbor"
|
||||
"github.com/sonr-io/common/webauthn/webauthncose"
|
||||
"github.com/sonr-io/sonr/x/did/keeper"
|
||||
"github.com/sonr-io/sonr/x/did/types"
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/sonr-io/sonr/crypto/mpc"
|
||||
"github.com/sonr-io/crypto/mpc"
|
||||
)
|
||||
|
||||
// AccountKeeper defines the expected account keeper interface
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/sonr-io/sonr/crypto/ucan"
|
||||
"github.com/sonr-io/crypto/ucan"
|
||||
)
|
||||
|
||||
// UCAN Action Constants for DID operations
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/sonr-io/common/webauthn"
|
||||
"github.com/sonr-io/common/webauthn/webauthncbor"
|
||||
)
|
||||
|
||||
// ClientData represents the client data for WebAuthn ceremonies
|
||||
// This is a simplified version for backward compatibility
|
||||
type ClientData struct {
|
||||
Type string `json:"type"`
|
||||
Challenge string `json:"challenge"`
|
||||
Origin string `json:"origin"`
|
||||
}
|
||||
|
||||
// ValidateStructure validates a WebAuthn credential structure
|
||||
func ValidateStructure(cred *WebAuthnCredential) error {
|
||||
if cred == nil {
|
||||
return fmt.Errorf("credential is nil")
|
||||
}
|
||||
|
||||
if cred.CredentialId == "" {
|
||||
return fmt.Errorf("credential ID is required")
|
||||
}
|
||||
|
||||
if len(cred.PublicKey) == 0 {
|
||||
return fmt.Errorf("public key is required")
|
||||
}
|
||||
|
||||
if cred.AttestationType == "" {
|
||||
return fmt.Errorf("attestation type is required")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateAttestation performs security validation of WebAuthn credential data
|
||||
func ValidateAttestation(cred *WebAuthnCredential, challenge, expectedOrigin string) error {
|
||||
// Validate structure first
|
||||
if err := ValidateStructure(cred); err != nil {
|
||||
return fmt.Errorf("structure validation failed: %w", err)
|
||||
}
|
||||
|
||||
// Parse and validate client data JSON
|
||||
clientData, err := ValidateClientDataJSONFormat(cred.ClientDataJson)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid client data JSON: %w", err)
|
||||
}
|
||||
|
||||
// Verify challenge
|
||||
if clientData.Challenge != challenge {
|
||||
return fmt.Errorf("challenge mismatch: expected %s, got %s", challenge, clientData.Challenge)
|
||||
}
|
||||
|
||||
// Verify origin
|
||||
if expectedOrigin != "" && !strings.HasPrefix(clientData.Origin, expectedOrigin) {
|
||||
return fmt.Errorf("origin mismatch: expected %s, got %s", expectedOrigin, clientData.Origin)
|
||||
}
|
||||
|
||||
// Verify ceremony type
|
||||
if clientData.Type != "webauthn.create" {
|
||||
return fmt.Errorf("invalid ceremony type: expected webauthn.create, got %s", clientData.Type)
|
||||
}
|
||||
|
||||
// Validate attestation object format if present
|
||||
if cred.AttestationObject != "" {
|
||||
if err := ValidateAttestationObjectFormat(cred.AttestationObject); err != nil {
|
||||
return fmt.Errorf("invalid attestation object: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateForGaslessRegistration performs comprehensive validation for gasless WebAuthn registration
|
||||
func ValidateForGaslessRegistration(cred *WebAuthnCredential, challenge, expectedOrigin string) error {
|
||||
// Perform standard attestation validation
|
||||
if err := ValidateAttestation(cred, challenge, expectedOrigin); err != nil {
|
||||
return fmt.Errorf("attestation validation failed: %w", err)
|
||||
}
|
||||
|
||||
// Additional gasless-specific validations
|
||||
// User verification is recommended but not strictly required for gasless registration
|
||||
// The WebAuthn protocol itself provides sufficient security guarantees
|
||||
|
||||
// Verify algorithm support for gasless transactions
|
||||
if err := ValidateAlgorithmSupport(cred.Algorithm); err != nil {
|
||||
return fmt.Errorf("unsupported algorithm for gasless registration: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateCredentialUniqueness validates that a WebAuthn credential is unique
|
||||
func ValidateCredentialUniqueness(credentialID string, existingCredentials []string) error {
|
||||
if credentialID == "" {
|
||||
return fmt.Errorf("credential ID cannot be empty")
|
||||
}
|
||||
|
||||
for _, existing := range existingCredentials {
|
||||
if existing == credentialID {
|
||||
return fmt.Errorf("credential ID already exists: %s", credentialID)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateAlgorithmSupport validates that the specified algorithm is supported
|
||||
func ValidateAlgorithmSupport(algorithm int32) error {
|
||||
// Supported algorithms for Sonr
|
||||
// -7: ES256 (ECDSA with SHA-256)
|
||||
// -257: RS256 (RSA with SHA-256)
|
||||
// -8: EdDSA
|
||||
supportedAlgs := map[int32]string{
|
||||
-7: "ES256",
|
||||
-257: "RS256",
|
||||
-8: "EdDSA",
|
||||
}
|
||||
|
||||
if _, ok := supportedAlgs[algorithm]; !ok {
|
||||
return fmt.Errorf("unsupported algorithm: %d (supported: ES256=-7, RS256=-257, EdDSA=-8)", algorithm)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateAttestationObjectFormat validates the attestation object format
|
||||
func ValidateAttestationObjectFormat(attestationObject string) error {
|
||||
if attestationObject == "" {
|
||||
return fmt.Errorf("attestation object is empty")
|
||||
}
|
||||
|
||||
// Decode base64url
|
||||
attestationBytes, err := base64.RawURLEncoding.DecodeString(attestationObject)
|
||||
if err != nil {
|
||||
// Try standard base64 as fallback
|
||||
attestationBytes, err = base64.StdEncoding.DecodeString(attestationObject)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to decode attestation object: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Parse as CBOR
|
||||
var attestationObj webauthn.AttestationObject
|
||||
if err := webauthncbor.Unmarshal(attestationBytes, &attestationObj); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal attestation object: %w", err)
|
||||
}
|
||||
|
||||
// Validate that it has authenticator data
|
||||
if len(attestationObj.RawAuthData) == 0 {
|
||||
return fmt.Errorf("attestation object missing authenticator data")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateClientDataJSONFormat validates the client data JSON format
|
||||
func ValidateClientDataJSONFormat(clientDataJSON string) (*ClientData, error) {
|
||||
if clientDataJSON == "" {
|
||||
return nil, fmt.Errorf("client data JSON is empty")
|
||||
}
|
||||
|
||||
// Decode base64url
|
||||
clientDataBytes, err := base64.RawURLEncoding.DecodeString(clientDataJSON)
|
||||
if err != nil {
|
||||
// Try standard base64 as fallback
|
||||
clientDataBytes, err = base64.StdEncoding.DecodeString(clientDataJSON)
|
||||
if err != nil {
|
||||
// Try parsing as plain JSON
|
||||
clientDataBytes = []byte(clientDataJSON)
|
||||
}
|
||||
}
|
||||
|
||||
// Parse as JSON
|
||||
var clientData ClientData
|
||||
if err := json.Unmarshal(clientDataBytes, &clientData); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal client data JSON: %w", err)
|
||||
}
|
||||
|
||||
// Validate required fields
|
||||
if clientData.Type == "" {
|
||||
return nil, fmt.Errorf("client data missing 'type' field")
|
||||
}
|
||||
|
||||
if clientData.Challenge == "" {
|
||||
return nil, fmt.Errorf("client data missing 'challenge' field")
|
||||
}
|
||||
|
||||
if clientData.Origin == "" {
|
||||
return nil, fmt.Errorf("client data missing 'origin' field")
|
||||
}
|
||||
|
||||
return &clientData, nil
|
||||
}
|
||||
|
||||
// GenerateAddressFromCredential generates a deterministic address from a WebAuthn credential ID
|
||||
func GenerateAddressFromCredential(credentialID string) string {
|
||||
if credentialID == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Create a SHA-256 hash of the credential ID
|
||||
hash := sha256.Sum256([]byte(credentialID))
|
||||
|
||||
// Take first 20 bytes and encode as hex (Ethereum-style address)
|
||||
address := hex.EncodeToString(hash[:20])
|
||||
|
||||
// Return with 0x prefix
|
||||
return "0x" + address
|
||||
}
|
||||
|
||||
// GenerateDIDFromCredential generates a deterministic DID from a WebAuthn credential
|
||||
func GenerateDIDFromCredential(credentialID, username string) string {
|
||||
if credentialID == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Create a hash of credential ID + username for uniqueness
|
||||
data := credentialID
|
||||
if username != "" {
|
||||
data = credentialID + ":" + username
|
||||
}
|
||||
|
||||
hash := sha256.Sum256([]byte(data))
|
||||
|
||||
// Encode as base58-like string (using hex for simplicity)
|
||||
identifier := hex.EncodeToString(hash[:16])
|
||||
|
||||
// Return DID in did:sonr format
|
||||
return fmt.Sprintf("did:sonr:%s", identifier)
|
||||
}
|
||||
+8
-80
@@ -1,95 +1,23 @@
|
||||
// Package types provides x/did module types that delegate WebAuthn validation
|
||||
// to the centralized types/webauthn package to eliminate circular dependencies.
|
||||
//
|
||||
// All WebAuthn validation logic has been moved to types/webauthn/sonr_validation.go
|
||||
// to leverage the full WebAuthn protocol stack while maintaining API compatibility.
|
||||
// Package types provides x/did module types with WebAuthn validation
|
||||
// All WebAuthn validation logic is now in validation.go in this package.
|
||||
package types
|
||||
|
||||
import (
|
||||
webauthnvalidation "github.com/sonr-io/sonr/types/webauthn"
|
||||
)
|
||||
|
||||
// WebAuthnCredential automatically implements the WebAuthnCredential interface
|
||||
// through the getter methods generated by protobuf (GetCredentialId, GetPublicKey, etc.)
|
||||
// This provides compatibility with the centralized validation functions in types/webauthn
|
||||
|
||||
// ValidateStructure validates a WebAuthn credential for gasless transaction processing.
|
||||
// This method delegates to the centralized validation logic in types/webauthn package.
|
||||
//
|
||||
// DEPRECATED: This method delegates to webauthnvalidation.ValidateStructure.
|
||||
// New code should import types/webauthn and use ValidateStructure directly.
|
||||
// This method uses the local validation logic in this package.
|
||||
func (c *WebAuthnCredential) ValidateStructure() error {
|
||||
return webauthnvalidation.ValidateStructure(c)
|
||||
return ValidateStructure(c)
|
||||
}
|
||||
|
||||
// ValidateAttestation performs security validation of WebAuthn credential data.
|
||||
// This method delegates to the centralized validation logic in types/webauthn package.
|
||||
//
|
||||
// DEPRECATED: This method delegates to webauthnvalidation.ValidateAttestation.
|
||||
// New code should import types/webauthn and use ValidateAttestation directly.
|
||||
// This method uses the local validation logic in this package.
|
||||
func (c *WebAuthnCredential) ValidateAttestation(challenge, expectedOrigin string) error {
|
||||
return webauthnvalidation.ValidateAttestation(c, challenge, expectedOrigin)
|
||||
return ValidateAttestation(c, challenge, expectedOrigin)
|
||||
}
|
||||
|
||||
// ValidateForGaslessRegistration performs comprehensive validation for gasless WebAuthn registration.
|
||||
// This method delegates to the centralized validation logic in types/webauthn package.
|
||||
//
|
||||
// DEPRECATED: This method delegates to webauthnvalidation.ValidateForGaslessRegistration.
|
||||
// New code should import types/webauthn and use ValidateForGaslessRegistration directly.
|
||||
// This method uses the local validation logic in this package.
|
||||
func (c *WebAuthnCredential) ValidateForGaslessRegistration(
|
||||
challenge, expectedOrigin string,
|
||||
) error {
|
||||
return webauthnvalidation.ValidateForGaslessRegistration(c, challenge, expectedOrigin)
|
||||
}
|
||||
|
||||
// Utility functions that delegate to types/webauthn for enhanced functionality
|
||||
|
||||
// ValidateCredentialUniqueness validates that a WebAuthn credential is unique across the system.
|
||||
func ValidateCredentialUniqueness(credentialID string, existingCredentials []string) error {
|
||||
return webauthnvalidation.ValidateCredentialUniqueness(credentialID, existingCredentials)
|
||||
}
|
||||
|
||||
// ValidateAlgorithmSupport validates that the specified algorithm is supported.
|
||||
func ValidateAlgorithmSupport(algorithm int32) error {
|
||||
return webauthnvalidation.ValidateAlgorithmSupport(algorithm)
|
||||
}
|
||||
|
||||
// ValidateAttestationObjectFormat validates the attestation object format using full WebAuthn protocol.
|
||||
func ValidateAttestationObjectFormat(attestationObject string) error {
|
||||
return webauthnvalidation.ValidateAttestationObjectFormat(attestationObject)
|
||||
}
|
||||
|
||||
// ValidateClientDataJSONFormat validates the client data JSON format using WebAuthn protocol structures.
|
||||
func ValidateClientDataJSONFormat(clientDataJSON string) (*webauthnvalidation.ClientData, error) {
|
||||
return webauthnvalidation.ValidateClientDataJSONFormat(clientDataJSON)
|
||||
}
|
||||
|
||||
// ValidateWithProtocol has been moved to types/webauthn package
|
||||
// Use webauthnvalidation.ValidateWithProtocol directly with centralized WebAuthn credentials
|
||||
|
||||
// Service binding validation functions have been moved to types/webauthn package
|
||||
// Use webauthnvalidation.ValidateServiceBinding and webauthnvalidation.ValidateCredentialForDomain directly
|
||||
|
||||
// Legacy ClientData type for backward compatibility
|
||||
// DEPRECATED: Use webauthnvalidation.ClientData instead
|
||||
type ClientData struct {
|
||||
Type string `json:"type"`
|
||||
Challenge string `json:"challenge"`
|
||||
Origin string `json:"origin"`
|
||||
}
|
||||
|
||||
// parseClientDataJSON functionality has been moved to types/webauthn package
|
||||
// Use webauthnvalidation.ValidateClientDataJSONFormat instead
|
||||
|
||||
// Helper functions that maintain API compatibility while delegating to types/webauthn
|
||||
|
||||
// GenerateAddressFromCredential generates a deterministic address from a WebAuthn credential ID.
|
||||
func GenerateAddressFromCredential(credentialID string) string {
|
||||
// Import the utility package for address generation
|
||||
return webauthnvalidation.GenerateAddressFromCredential(credentialID).String()
|
||||
}
|
||||
|
||||
// GenerateDIDFromCredential generates a deterministic DID from a WebAuthn credential.
|
||||
func GenerateDIDFromCredential(credentialID string, username string) string {
|
||||
return webauthnvalidation.GenerateDIDFromCredential(credentialID, username)
|
||||
return ValidateForGaslessRegistration(c, challenge, expectedOrigin)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user