-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommon.go
More file actions
223 lines (195 loc) · 7.71 KB
/
Copy pathcommon.go
File metadata and controls
223 lines (195 loc) · 7.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
// Package common contains the common types used by the Sonr network.
// This package provides convenient helper methods for simplified usage
// of the ipfs and webauthn modules by external libraries.
package common
import (
"encoding/base64"
"encoding/json"
"fmt"
"github.com/sonr-io/common/ipfs"
"github.com/sonr-io/common/webauthn"
)
// IPFS Helper Functions
// These functions provide simplified interfaces for common IPFS operations.
// NewIPFSClient creates a new IPFS client connected to the local IPFS daemon.
// Returns a detailed error if the connection fails, helping developers
// identify configuration issues quickly.
func NewIPFSClient() (ipfs.IPFSClient, error) {
client, err := ipfs.GetClient()
if err != nil {
return nil, fmt.Errorf("failed to connect to local IPFS daemon: %w (ensure IPFS daemon is running)", err)
}
return client, nil
}
// MustGetIPFSClient creates a new IPFS client or panics if it fails.
// This is useful for applications where IPFS connectivity is critical
// and should cause immediate failure during initialization.
func MustGetIPFSClient() ipfs.IPFSClient {
client, err := NewIPFSClient()
if err != nil {
panic(err)
}
return client
}
// StoreData stores raw byte data in IPFS and returns the CID.
// This is a convenience wrapper that handles client creation and data storage.
func StoreData(data []byte) (cid string, err error) {
client, err := NewIPFSClient()
if err != nil {
return "", err
}
return client.Add(data)
}
// RetrieveData retrieves content from IPFS using the provided CID.
// This is a convenience wrapper that handles client creation and data retrieval.
func RetrieveData(cid string) ([]byte, error) {
client, err := NewIPFSClient()
if err != nil {
return nil, err
}
return client.Get(cid)
}
// IsIPFSDaemonRunning checks if the local IPFS daemon is running and accessible.
// Returns true if the daemon is available, false otherwise.
func IsIPFSDaemonRunning() bool {
client, err := ipfs.GetClient()
if err != nil {
return false
}
// Try to get node status as a connectivity check
_, err = client.NodeStatus()
return err == nil
}
// StoreFile stores a file with metadata in IPFS and returns the CID.
// This helper creates an ipfs.File from the provided name and data,
// then stores it in IPFS.
func StoreFile(name string, data []byte) (cid string, err error) {
client, err := NewIPFSClient()
if err != nil {
return "", err
}
file := ipfs.NewFile(name, data)
return client.AddFile(file)
}
// StoreFolder stores multiple files as a folder in IPFS and returns the root CID.
// The files map should contain filename -> file data pairs.
func StoreFolder(files map[string][]byte) (cid string, err error) {
client, err := NewIPFSClient()
if err != nil {
return "", err
}
// Convert map to File slice
ipfsFiles := make([]ipfs.File, 0, len(files))
for name, data := range files {
ipfsFiles = append(ipfsFiles, ipfs.NewFile(name, data))
}
folder := ipfs.NewFolder(ipfsFiles...)
return client.AddFolder(folder)
}
// WebAuthn Helper Functions
// These functions provide simplified interfaces for common WebAuthn operations.
// NewChallenge generates a new cryptographic challenge for WebAuthn ceremonies.
// The challenge is 32 bytes of random data, URL-safe base64 encoded.
// Returns the challenge as a string that can be sent to clients.
func NewChallenge() (string, error) {
challenge, err := webauthn.CreateChallenge()
if err != nil {
return "", fmt.Errorf("failed to create WebAuthn challenge: %w", err)
}
return challenge.String(), nil
}
// VerifyOrigin checks if the provided origin matches any of the allowed origins.
// This is a simplified wrapper around the webauthn origin verification logic.
// Origins should be fully qualified (e.g., "https://example.com").
func VerifyOrigin(origin string, allowedOrigins []string) error {
fqOrigin, err := webauthn.FullyQualifiedOrigin(origin)
if err != nil {
return fmt.Errorf("invalid origin format: %w", err)
}
for _, allowed := range allowedOrigins {
if fqOrigin == allowed {
return nil
}
}
return fmt.Errorf("origin %s is not in the allowed origins list", fqOrigin)
}
// EncodeBase64URL encodes data to URL-safe base64 format (without padding).
// This is the encoding format required by WebAuthn specifications.
func EncodeBase64URL(data []byte) string {
return base64.RawURLEncoding.EncodeToString(data)
}
// DecodeBase64URL decodes URL-safe base64 data (with or without padding).
// This handles the base64 format used in WebAuthn responses.
func DecodeBase64URL(encoded string) ([]byte, error) {
decoded, err := base64.RawURLEncoding.DecodeString(encoded)
if err != nil {
return nil, fmt.Errorf("failed to decode base64 URL: %w", err)
}
return decoded, nil
}
// ChallengeLength returns the standard challenge length used for WebAuthn.
// This can be useful for validation and testing.
func ChallengeLength() int {
return webauthn.ChallengeLength
}
// UnmarshalCredentialCreation unmarshals JSON data into a CredentialCreationResponse.
// This is used when receiving a credential creation response from the client during registration.
func UnmarshalCredentialCreation(data []byte) (*webauthn.CredentialCreationResponse, error) {
var ccr webauthn.CredentialCreationResponse
if err := decodeJSON(data, &ccr); err != nil {
return nil, fmt.Errorf("failed to unmarshal credential creation response: %w", err)
}
return &ccr, nil
}
// MarshalCredentialCreation marshals a CredentialCreationResponse into JSON data.
// This can be used for storing or transmitting credential creation responses.
func MarshalCredentialCreation(ccr *webauthn.CredentialCreationResponse) ([]byte, error) {
data, err := encodeJSON(ccr)
if err != nil {
return nil, fmt.Errorf("failed to marshal credential creation response: %w", err)
}
return data, nil
}
// ParseCredentialCreation parses and validates a credential creation response from JSON bytes.
// Returns a parsed credential that has been validated and is ready for verification.
func ParseCredentialCreation(data []byte) (*webauthn.ParsedCredentialCreationData, error) {
parsed, err := webauthn.ParseCredentialCreationResponseBytes(data)
if err != nil {
return nil, fmt.Errorf("failed to parse credential creation response: %w", err)
}
return parsed, nil
}
// UnmarshalCredentialAssertion unmarshals JSON data into a CredentialAssertionResponse.
// This is used when receiving an assertion response from the client during authentication.
func UnmarshalCredentialAssertion(data []byte) (*webauthn.CredentialAssertionResponse, error) {
var car webauthn.CredentialAssertionResponse
if err := decodeJSON(data, &car); err != nil {
return nil, fmt.Errorf("failed to unmarshal credential assertion response: %w", err)
}
return &car, nil
}
// MarshalCredentialAssertion marshals a CredentialAssertionResponse into JSON data.
// This can be used for storing or transmitting credential assertion responses.
func MarshalCredentialAssertion(car *webauthn.CredentialAssertionResponse) ([]byte, error) {
data, err := encodeJSON(car)
if err != nil {
return nil, fmt.Errorf("failed to marshal credential assertion response: %w", err)
}
return data, nil
}
// ParseCredentialAssertion parses and validates a credential assertion response from JSON bytes.
// Returns a parsed assertion that has been validated and is ready for verification.
func ParseCredentialAssertion(data []byte) (*webauthn.ParsedCredentialAssertionData, error) {
parsed, err := webauthn.ParseCredentialRequestResponseBytes(data)
if err != nil {
return nil, fmt.Errorf("failed to parse credential assertion response: %w", err)
}
return parsed, nil
}
// Helper functions for JSON encoding/decoding
func decodeJSON(data []byte, v interface{}) error {
return json.Unmarshal(data, v)
}
func encodeJSON(v interface{}) ([]byte, error) {
return json.Marshal(v)
}