From 429565562d764e3837ef67fac8063bfa0b4273ec Mon Sep 17 00:00:00 2001 From: Derrick Hammer Date: Fri, 1 Mar 2024 01:24:20 -0500 Subject: [PATCH] fix: need to implement MetadataTypeProof support --- go.mod | 2 + go.sum | 4 ++ metadata/media_metadata.go | 96 +++++++++++++++++++++++++++++++++++++- metadata/parent_link.go | 18 ++++++- types/meta.go | 12 +++++ 5 files changed, 129 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d6e1c52..23a7fa4 100644 --- a/go.mod +++ b/go.mod @@ -17,11 +17,13 @@ require ( go.sia.tech/jape v0.11.1 go.uber.org/fx v1.20.1 go.uber.org/zap v1.26.0 + lukechampine.com/blake3 v1.2.1 nhooyr.io/websocket v1.7.1 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/mr-tron/base58 v1.1.0 // indirect github.com/multiformats/go-base32 v0.0.3 // indirect github.com/multiformats/go-base36 v0.1.0 // indirect diff --git a/go.sum b/go.sum index 5f19d99..6da4f7c 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -107,5 +109,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= +lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= nhooyr.io/websocket v1.7.1 h1:W8X03PI0a2fiKb3Srck2gpmWr8UwJqDGndXw8bb93yM= nhooyr.io/websocket v1.7.1/go.mod h1:FyTYp9aYEPchTiPpXj2mOOnHJ49S35YStWZCjotwizg= diff --git a/metadata/media_metadata.go b/metadata/media_metadata.go index 80d0a69..143ea94 100644 --- a/metadata/media_metadata.go +++ b/metadata/media_metadata.go @@ -1,10 +1,17 @@ package metadata import ( + "bytes" + "crypto/ed25519" "errors" + "git.lumeweb.com/LumeWeb/libs5-go/encoding" "git.lumeweb.com/LumeWeb/libs5-go/serialize" "git.lumeweb.com/LumeWeb/libs5-go/types" + "git.lumeweb.com/LumeWeb/libs5-go/utils" "github.com/vmihailenco/msgpack/v5" + "io" + "lukechampine.com/blake3" + _ "lukechampine.com/blake3" ) var ( @@ -23,9 +30,14 @@ type MediaMetadata struct { Details MediaMetadataDetails Links *MediaMetadataLinks ExtraMetadata ExtraMetadata + provenPubKeys []*encoding.Multihash BaseMetadata } +func (m *MediaMetadata) ProvenPubKeys() []*encoding.Multihash { + return m.provenPubKeys +} + func NewMediaMetadata(name string, details MediaMetadataDetails, parents []MetadataParentLink, mediaTypes map[string][]MediaFormat, links *MediaMetadataLinks, extraMetadata ExtraMetadata) *MediaMetadata { return &MediaMetadata{ Name: name, @@ -61,7 +73,78 @@ func (m *MediaMetadata) DecodeMsgpack(dec *msgpack.Decoder) error { } func (m *MediaMetadata) decodeProof(dec *msgpack.Decoder) error { - return errors.New("Not implemented") + all, err := io.ReadAll(dec.Buffered()) + if err != nil { + return err + } + + proofSectionLength := utils.DecodeEndian(all[0:2]) + + bodyBytes := all[2+proofSectionLength:] + + if proofSectionLength == 0 { + return nil + } + + childDec := msgpack.NewDecoder(bytes.NewReader(all[2 : proofSectionLength+4])) + + b3hash := blake3.Sum256(bodyBytes) + + arrayLen, err := childDec.DecodeArrayLen() + if err != nil { + return err + } + + provenPubKeys := make([]*encoding.Multihash, 0) + + for i := 0; i < arrayLen; i++ { + proofData, err := childDec.DecodeSlice() + if err != nil { + return err + } + + for j := 0; j < len(proofData); j++ { + var mhashType int + var pubkey []byte + var signature []byte + + switch j { + case 0: + sigType := proofData[j].(int) + if types.MetadataProofType(sigType) != types.MetadataProofTypeSignature { + return errors.New("Invalid proof type") + } + case 1: + mhashType = proofData[j].(int) + if types.HashType(mhashType) != types.HashTypeBlake3 { + return errors.New("Invalid hash type") + } + + case 2: + pubkey = proofData[j].([]byte) + if types.HashType(mhashType) != types.HashTypeEd25519 { + return errors.New("Invalid public key type") + } + + if len(pubkey) != 33 { + return errors.New("Invalid public key length") + } + + case 3: + signature = proofData[j].([]byte) + + if valid := ed25519.Verify(pubkey, b3hash[:], signature); !valid { + return errors.New("Invalid signature") + } + + provenPubKeys = append(provenPubKeys, encoding.NewMultihash(pubkey)) + } + } + } + + m.provenPubKeys = provenPubKeys + + return m.decodeMedia(msgpack.NewDecoder(bytes.NewReader(bodyBytes))) } func (m *MediaMetadata) decodeMedia(dec *msgpack.Decoder) error { @@ -80,11 +163,20 @@ func (m *MediaMetadata) decodeMedia(dec *msgpack.Decoder) error { return err } - err = dec.Decode(&m.Parents) + arrLen, err := dec.DecodeArrayLen() if err != nil { return err } + parents := make([]MetadataParentLink, arrLen) + for i := 0; i < arrLen; i++ { + parents[i].SetParent(m) + err = dec.Decode(&parents[i]) + if err != nil { + return err + } + } + err = dec.Decode(&m.MediaTypes) if err != nil { return err diff --git a/metadata/parent_link.go b/metadata/parent_link.go index 344a999..a6f55af 100644 --- a/metadata/parent_link.go +++ b/metadata/parent_link.go @@ -18,6 +18,11 @@ type MetadataParentLink struct { Type types.ParentLinkType Role string Signed bool + parent *MediaMetadata +} + +func (m *MetadataParentLink) SetParent(parent *MediaMetadata) { + m.parent = parent } func (m *MetadataParentLink) EncodeMsgpack(enc *msgpack.Encoder) error { @@ -31,6 +36,8 @@ func (m *MetadataParentLink) DecodeMsgpack(dec *msgpack.Decoder) error { return err } + cid := &encoding.CID{} + for i := 0; i < mapLen; i++ { key, err := dec.DecodeInt8() if err != nil { @@ -45,7 +52,7 @@ func (m *MetadataParentLink) DecodeMsgpack(dec *msgpack.Decoder) error { case 0: m.Type = types.ParentLinkType(value.(int)) case 1: - cid, err := encoding.CIDFromBytes(value.([]byte)) + cid, err = encoding.CIDFromBytes(value.([]byte)) if err != nil { return err } @@ -60,6 +67,15 @@ func (m *MetadataParentLink) DecodeMsgpack(dec *msgpack.Decoder) error { m.Signed = false + if m.parent != nil { + for _, key := range m.parent.ProvenPubKeys() { + if cid.Hash.Equals(key) { + m.Signed = true + break + } + } + } + return nil } diff --git a/types/meta.go b/types/meta.go index 767a485..36b5698 100644 --- a/types/meta.go +++ b/types/meta.go @@ -57,3 +57,15 @@ var MetadataTypeMap = map[string]MetadataType{ "Proof": MetadataTypeProof, "UserIdentity": MetadataTypeUserIdentity, } + +type MetadataProofType uint8 + +const ( + MetadataProofTypeSignature MetadataProofType = 0x01 + MetadataProofTypeTimestamp MetadataProofType = 0x02 +) + +var MetadataProofTypeMap = map[string]MetadataProofType{ + "Signature": MetadataProofTypeSignature, + "Timestamp": MetadataProofTypeTimestamp, +}