@@ -56,17 +56,33 @@ type Store interface {
5656 DecryptMessage (cipher []byte , peerID string ) ([]byte , error )
5757}
5858
59+ // SignatureAlgorithm represents supported signature algorithms
60+ type SignatureAlgorithm string
61+
62+ const (
63+ AlgorithmEd25519 SignatureAlgorithm = "ed25519"
64+ AlgorithmP256 SignatureAlgorithm = "p256"
65+ )
66+
5967// AuthorizerInfo represents a single authorizer with their public key and algorithm
6068type AuthorizerInfo struct {
61- PublicKey string `json:"public_key"`
62- Algorithm string `json:"algorithm"` // "ed25519" or "secp256k1"
69+ PublicKey string `json:"public_key"`
70+ Algorithm SignatureAlgorithm `json:"algorithm"`
6371}
6472
6573// AuthorizationConfig holds the cached authorization configuration
6674type AuthorizationConfig struct {
67- Enabled bool
68- RequiredAuthorizers int
69- AuthorizerPublicKeys map [string ]AuthorizerInfo // key is authorizer ID
75+ Enabled bool `mapstructure:"enabled"`
76+ RequiredAuthorizers int `mapstructure:"required_authorizers"`
77+ AuthorizerPublicKeys map [string ]AuthorizerInfo `mapstructure:"authorizer_public_keys"`
78+ Authorizers map [string ]AuthorizerInfo `mapstructure:"authorizers"` // backward compatibility
79+ }
80+
81+ // AuthorizerConfigEntry represents the raw configuration for an authorizer
82+ type AuthorizerConfigEntry struct {
83+ PublicKey string `mapstructure:"public_key"`
84+ Algorithm string `mapstructure:"algorithm"`
85+ Pubkey string `mapstructure:"pubkey"` // backward compatibility
7086}
7187
7288// fileStore implements the Store interface using the filesystem
@@ -170,70 +186,87 @@ func NewFileStore(identityDir, nodeName string, decrypt bool) (*fileStore, error
170186 }
171187
172188 // Load authorization configuration
173- store .authzConfig = AuthorizationConfig {
189+ if err := store .loadAuthorizationConfig (); err != nil {
190+ return nil , fmt .Errorf ("failed to load authorization config: %w" , err )
191+ }
192+
193+ return store , nil
194+ }
195+
196+ // loadAuthorizationConfig loads and caches the authorization configuration
197+ func (s * fileStore ) loadAuthorizationConfig () error {
198+ // Load base configuration
199+ s .authzConfig = AuthorizationConfig {
174200 Enabled : viper .GetBool ("authorization.enabled" ),
175201 RequiredAuthorizers : viper .GetInt ("authorization.required_authorizers" ),
176202 AuthorizerPublicKeys : make (map [string ]AuthorizerInfo ),
203+ Authorizers : make (map [string ]AuthorizerInfo ),
177204 }
178205
179- // Load authorizer public keys
180- authKeys := viper .GetStringMap ("authorization.authorizer_public_keys" )
181- for authID , authData := range authKeys {
182- if authInfo , ok := authData .(map [string ]interface {}); ok {
183- info := AuthorizerInfo {
184- Algorithm : "ed25519" , // default algorithm
185- }
186-
187- if pubKey , ok := authInfo ["public_key" ].(string ); ok && pubKey != "" {
188- info .PublicKey = pubKey
189- }
190-
191- if algo , ok := authInfo ["algorithm" ].(string ); ok && algo != "" {
192- info .Algorithm = algo
193- }
194-
195- if info .PublicKey != "" {
196- store .authzConfig .AuthorizerPublicKeys [authID ] = info
197- store .authorizerInfo [authID ] = info
198- }
206+ // Load authorizer public keys (new format)
207+ authKeysConfig := viper .GetStringMap ("authorization.authorizer_public_keys" )
208+ for authID , authData := range authKeysConfig {
209+ info , err := parseAuthorizerConfig (authData , true )
210+ if err != nil {
211+ logger .Warn ("Failed to parse authorizer config" , "authorizerID" , authID , "error" , err )
212+ continue
213+ }
214+ if info .PublicKey != "" {
215+ s .authzConfig .AuthorizerPublicKeys [authID ] = info
216+ s .authorizerInfo [authID ] = info
199217 }
200218 }
201219
202220 // Load global authorizer configuration (backward compatibility)
203- authzAuthorizers := viper .GetStringMap ("authorization.authorizers" )
204- for id , v := range authzAuthorizers {
205- // Skip if already loaded from operation-specific config
206- if _ , exists := store .authorizerInfo [id ]; exists {
221+ authorizersConfig := viper .GetStringMap ("authorization.authorizers" )
222+ for authID , authData := range authorizersConfig {
223+ // Skip if already loaded from new format
224+ if _ , exists := s .authorizerInfo [authID ]; exists {
207225 continue
208226 }
209227
210- // v is expected to be a map with key "pubkey" and optional "algorithm"
211- if entry , ok := v .(map [string ]interface {}); ok {
212- info := AuthorizerInfo {
213- Algorithm : "ed25519" , // default algorithm
214- }
228+ info , err := parseAuthorizerConfig (authData , false )
229+ if err != nil {
230+ logger .Warn ("Failed to parse legacy authorizer config" , "authorizerID" , authID , "error" , err )
231+ continue
232+ }
233+ if info .PublicKey != "" {
234+ s .authzConfig .Authorizers [authID ] = info
235+ s .authorizerInfo [authID ] = info
236+ }
237+ }
215238
216- if pubHexRaw , ok := entry ["pubkey" ]; ok {
217- if pubHex , ok := pubHexRaw .(string ); ok && pubHex != "" {
218- info .PublicKey = pubHex
219- }
220- }
239+ return nil
240+ }
221241
222- if algoRaw , ok := entry [ "algorithm" ]; ok {
223- if algo , ok := algoRaw .( string ); ok && algo != "" {
224- info . Algorithm = algo
225- }
226- }
242+ // parseAuthorizerConfig parses authorizer configuration from interface{} to AuthorizerInfo
243+ func parseAuthorizerConfig ( authData interface {}, isNewFormat bool ) ( AuthorizerInfo , error ) {
244+ info := AuthorizerInfo {
245+ Algorithm : AlgorithmEd25519 , // default algorithm
246+ }
227247
228- if info .PublicKey != "" {
229- store .authorizerInfo [id ] = info
230- } else {
231- logger .Warn ("Invalid or empty pubkey for authorizer" , "authorizerID" , id )
232- }
248+ authMap , ok := authData .(map [string ]interface {})
249+ if ! ok {
250+ return info , fmt .Errorf ("invalid authorizer config format" )
251+ }
252+
253+ // Parse public key (handle both new and legacy formats)
254+ if isNewFormat {
255+ if pubKey , ok := authMap ["public_key" ].(string ); ok && pubKey != "" {
256+ info .PublicKey = pubKey
257+ }
258+ } else {
259+ if pubKey , ok := authMap ["pubkey" ].(string ); ok && pubKey != "" {
260+ info .PublicKey = pubKey
233261 }
234262 }
235263
236- return store , nil
264+ // Parse algorithm
265+ if algo , ok := authMap ["algorithm" ].(string ); ok && algo != "" {
266+ info .Algorithm = SignatureAlgorithm (algo )
267+ }
268+
269+ return info , nil
237270}
238271
239272// loadPrivateKey loads the private key from file, decrypting if necessary
@@ -551,9 +584,9 @@ func (s *fileStore) AuthorizeInitiatorMessage(operation string, msg types.Initia
551584}
552585
553586// verifySignatureByAlgorithm verifies a signature using the specified algorithm
554- func verifySignatureByAlgorithm (publicKeyHex , algorithm string , message , signature []byte ) (bool , error ) {
587+ func verifySignatureByAlgorithm (publicKeyHex string , algorithm SignatureAlgorithm , message , signature []byte ) (bool , error ) {
555588 switch algorithm {
556- case "ed25519" :
589+ case AlgorithmEd25519 :
557590 pubKeyBytes , err := hex .DecodeString (publicKeyHex )
558591 if err != nil {
559592 return false , fmt .Errorf ("invalid ed25519 public key hex: %w" , err )
@@ -563,21 +596,14 @@ func verifySignatureByAlgorithm(publicKeyHex, algorithm string, message, signatu
563596 }
564597 return ed25519 .Verify (pubKeyBytes , message , signature ), nil
565598
566- case "secp256k1" , "p256" :
599+ case AlgorithmP256 :
567600 pubKeyBytes , err := hex .DecodeString (publicKeyHex )
568601 if err != nil {
569602 return false , fmt .Errorf ("invalid ecdsa public key hex: %w" , err )
570603 }
571604
572605 // Parse the public key
573- var curve elliptic.Curve
574- if algorithm == "secp256k1" {
575- // For secp256k1, we'd need to import a secp256k1 library
576- // For now, we'll use P256 as a placeholder
577- curve = elliptic .P256 ()
578- } else {
579- curve = elliptic .P256 ()
580- }
606+ curve := elliptic .P256 ()
581607
582608 // Assume uncompressed point format (0x04 + 32 bytes x + 32 bytes y)
583609 if len (pubKeyBytes ) == 65 && pubKeyBytes [0 ] == 0x04 {
0 commit comments