github.com/storacha/go-ucanto@v0.7.2/principal/ed25519/signer/signer.go (about) 1 package signer 2 3 import ( 4 "bytes" 5 "crypto/ed25519" 6 "crypto/rand" 7 "fmt" 8 9 "github.com/multiformats/go-multibase" 10 "github.com/multiformats/go-varint" 11 "github.com/storacha/go-ucanto/did" 12 "github.com/storacha/go-ucanto/principal" 13 "github.com/storacha/go-ucanto/principal/ed25519/verifier" 14 "github.com/storacha/go-ucanto/ucan/crypto/signature" 15 ) 16 17 const Code = 0x1300 18 const Name = verifier.Name 19 20 const SignatureCode = verifier.SignatureCode 21 const SignatureAlgorithm = verifier.SignatureAlgorithm 22 23 var privateTagSize = varint.UvarintSize(Code) 24 var publicTagSize = varint.UvarintSize(verifier.Code) 25 26 const keySize = 32 27 28 var size = privateTagSize + keySize + publicTagSize + keySize 29 var pubKeyOffset = privateTagSize + keySize 30 31 func Generate() (principal.Signer, error) { 32 pub, priv, err := ed25519.GenerateKey(rand.Reader) 33 if err != nil { 34 return nil, fmt.Errorf("generating Ed25519 key: %w", err) 35 } 36 s := make(Ed25519Signer, size) 37 varint.PutUvarint(s, Code) 38 copy(s[privateTagSize:], priv) 39 varint.PutUvarint(s[pubKeyOffset:], verifier.Code) 40 copy(s[pubKeyOffset+publicTagSize:], pub) 41 return s, nil 42 } 43 44 func Parse(str string) (principal.Signer, error) { 45 _, bytes, err := multibase.Decode(str) 46 if err != nil { 47 return nil, fmt.Errorf("decoding multibase string: %w", err) 48 } 49 return Decode(bytes) 50 } 51 52 func Format(signer principal.Signer) (string, error) { 53 return multibase.Encode(multibase.Base64pad, signer.Encode()) 54 } 55 56 func Decode(b []byte) (principal.Signer, error) { 57 if len(b) != size { 58 return nil, fmt.Errorf("invalid length: %d wanted: %d", len(b), size) 59 } 60 61 prc, err := varint.ReadUvarint(bytes.NewReader(b)) 62 if err != nil { 63 return nil, fmt.Errorf("reading private key codec: %w", err) 64 } 65 if prc != Code { 66 return nil, fmt.Errorf("invalid private key codec: %d", prc) 67 } 68 69 puc, err := varint.ReadUvarint(bytes.NewReader(b[pubKeyOffset:])) 70 if err != nil { 71 return nil, fmt.Errorf("reading public key codec: %w", err) 72 } 73 if puc != verifier.Code { 74 return nil, fmt.Errorf("invalid public key codec: %d", puc) 75 } 76 77 _, err = verifier.Decode(b[pubKeyOffset:]) 78 if err != nil { 79 return nil, fmt.Errorf("decoding public key: %w", err) 80 } 81 82 s := make(Ed25519Signer, size) 83 copy(s, b) 84 85 return s, nil 86 } 87 88 // FromRaw takes raw ed25519 private key bytes and tags with the ed25519 signer 89 // and verifier multiformat codes, returning an ed25519 signer. 90 func FromRaw(b []byte) (principal.Signer, error) { 91 if len(b) != ed25519.PrivateKeySize { 92 return nil, fmt.Errorf("invalid length: %d wanted: %d", len(b), ed25519.PrivateKeySize) 93 } 94 s := make(Ed25519Signer, size) 95 varint.PutUvarint(s, Code) 96 copy(s[privateTagSize:privateTagSize+keySize], b[:ed25519.PrivateKeySize-ed25519.PublicKeySize]) 97 varint.PutUvarint(s[pubKeyOffset:], verifier.Code) 98 copy(s[pubKeyOffset+publicTagSize:], b[ed25519.PrivateKeySize-ed25519.PublicKeySize:ed25519.PrivateKeySize]) 99 return s, nil 100 } 101 102 type Ed25519Signer []byte 103 104 func (s Ed25519Signer) Code() uint64 { 105 return Code 106 } 107 108 func (s Ed25519Signer) SignatureCode() uint64 { 109 return SignatureCode 110 } 111 112 func (s Ed25519Signer) SignatureAlgorithm() string { 113 return SignatureAlgorithm 114 } 115 116 func (s Ed25519Signer) Verifier() principal.Verifier { 117 return verifier.Ed25519Verifier(s[pubKeyOffset:]) 118 } 119 120 func (s Ed25519Signer) DID() did.DID { 121 id, _ := did.Decode(s[pubKeyOffset:]) 122 return id 123 } 124 125 func (s Ed25519Signer) Encode() []byte { 126 return s 127 } 128 129 func (s Ed25519Signer) Raw() []byte { 130 pk := make(ed25519.PrivateKey, ed25519.PrivateKeySize) 131 copy(pk[0:ed25519.PublicKeySize], s[privateTagSize:pubKeyOffset]) 132 copy(pk[ed25519.PrivateKeySize-ed25519.PublicKeySize:ed25519.PrivateKeySize], s[pubKeyOffset+publicTagSize:pubKeyOffset+publicTagSize+keySize]) 133 return pk 134 } 135 136 func (s Ed25519Signer) Sign(msg []byte) signature.SignatureView { 137 return signature.NewSignatureView(signature.NewSignature(signature.EdDSA, ed25519.Sign(s.Raw(), msg))) 138 }