Files
did-it/verifiers/_methods/multikey/multikey.go

113 lines
2.7 KiB
Go
Raw Normal View History

package multikey
import (
"encoding/json"
"errors"
"fmt"
"github.com/ucan-wg/go-did-it"
"github.com/ucan-wg/go-did-it/crypto"
allkeys "github.com/ucan-wg/go-did-it/crypto/_allkeys"
)
// Specification: https://www.w3.org/TR/cid-1.0/#Multikey
const (
// This is apparently the right context despite the spec above saying otherwise.
JsonLdContext = "https://w3id.org/security/multikey/v1"
Type = "Multikey"
)
var _ did.VerificationMethodSignature = &MultiKey{}
var _ did.VerificationMethodKeyAgreement = &MultiKey{}
type MultiKey struct {
id string
pubkey crypto.PublicKey
controller string
}
func NewMultiKey(id string, pubkey crypto.PublicKey, controller did.DID) *MultiKey {
return &MultiKey{
id: id,
pubkey: pubkey,
controller: controller.String(),
}
}
func (m MultiKey) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
ID string `json:"id"`
Type string `json:"type"`
Controller string `json:"controller"`
PublicKeyMultibase string `json:"publicKeyMultibase"`
}{
ID: m.ID(),
Type: m.Type(),
Controller: m.Controller(),
PublicKeyMultibase: m.pubkey.ToPublicKeyMultibase(),
})
}
func (m *MultiKey) UnmarshalJSON(bytes []byte) error {
aux := struct {
ID string `json:"id"`
Type string `json:"type"`
Controller string `json:"controller"`
PublicKeyMultibase string `json:"publicKeyMultibase"`
}{}
err := json.Unmarshal(bytes, &aux)
if err != nil {
return err
}
if aux.Type != m.Type() {
return errors.New("invalid type")
}
m.id = aux.ID
if len(m.id) == 0 {
return errors.New("invalid id")
}
2025-06-25 10:51:13 +02:00
m.controller = aux.Controller
if !did.HasValidDIDSyntax(m.controller) {
return errors.New("invalid controller")
}
2025-06-25 15:53:29 +02:00
m.pubkey, err = allkeys.PublicKeyFromPublicKeyMultibase(aux.PublicKeyMultibase)
if err != nil {
return fmt.Errorf("invalid publicKeyMultibase: %w", err)
}
return nil
}
func (m MultiKey) ID() string {
return m.id
}
func (m MultiKey) Type() string {
return Type
}
func (m MultiKey) Controller() string {
return m.controller
}
func (m MultiKey) JsonLdContext() string {
return JsonLdContext
}
func (m MultiKey) Verify(data []byte, sig []byte) (bool, error) {
2025-07-09 17:58:09 +02:00
if pub, ok := m.pubkey.(crypto.PublicKeySigningBytes); ok {
return pub.VerifyBytes(data, sig), nil
}
return false, errors.New("not a signing public key")
}
2025-07-03 15:55:58 +02:00
func (m MultiKey) PrivateKeyIsCompatible(local crypto.PrivateKeyKeyExchange) bool {
return local.PublicKeyIsCompatible(m.pubkey)
}
2025-07-03 15:55:58 +02:00
func (m MultiKey) KeyExchange(local crypto.PrivateKeyKeyExchange) ([]byte, error) {
return local.KeyExchange(m.pubkey)
}