github.com/holochain/holochain-proto@v0.1.0-alpha-26.0.20200915073418-5c83169c9b5b/warrant.go (about) 1 // Copyright (C) 2013-2017, The MetaCurrency Project (Eric Harris-Braun, Arthur Brock, et. al.) 2 // Use of this source code is governed by GPLv3 found in the LICENSE file 3 //---------------------------------------------------------------------------------------- 4 5 // warrant an interface for signed claims that can be cryptographically verified and implementation of various warrants 6 7 package holochain 8 9 import ( 10 "errors" 11 . "github.com/holochain/holochain-proto/hash" 12 ic "github.com/libp2p/go-libp2p-crypto" 13 peer "github.com/libp2p/go-libp2p-peer" 14 ) 15 16 const ( 17 SelfRevocationType = iota 18 ) 19 20 // Warrant abstracts the notion of a multi-party cryptographically verifiable signed claim 21 // the meaning of the warrant is understood by the warrant name an/or by properties contained in it 22 type Warrant interface { 23 24 // Int returns the warrant type 25 Type() int 26 27 // Parties returns the hashes of the public keys of the signers of the warrant 28 Parties() ([]Hash, error) 29 30 // Verify confirms that the content of a warrant is valid and has been signed by the 31 // the parties in it. Requires a Holochain object for context, returns nil if it 32 // verfies or an error 33 Verify(h *Holochain) error 34 35 // Property returns a value of a property attested to by the warrant 36 // returns a WarrantPropertyNotFoundErr if the warrant doesn't have that property 37 Property(key string) (value interface{}, err error) 38 39 // Encode marshals the warrant into bytes for sending over the wire 40 Encode() (data []byte, err error) 41 42 // Decode unmarshals a warrant from bytes 43 Decode(data []byte) (err error) 44 } 45 46 var WarrantPropertyNotFoundErr = errors.New("warrant property not found") 47 var UnknownWarrantTypeErr = errors.New("unknown warrant type") 48 49 // SelfRevocationWarrant warrants that the first party revoked its own key in favor of the second 50 type SelfRevocationWarrant struct { 51 Revocation SelfRevocation 52 } 53 54 func NewSelfRevocationWarrant(revocation *SelfRevocation) (wP *SelfRevocationWarrant, err error) { 55 w := SelfRevocationWarrant{Revocation: *revocation} 56 wP = &w 57 return 58 } 59 60 func DecodeWarrant(warrantType int, data []byte) (w Warrant, err error) { 61 switch warrantType { 62 case SelfRevocationType: 63 w = &SelfRevocationWarrant{} 64 err = w.Decode(data) 65 default: 66 err = UnknownWarrantTypeErr 67 } 68 return 69 } 70 71 func (w *SelfRevocationWarrant) Type() int { 72 return SelfRevocationType 73 } 74 75 func (w *SelfRevocationWarrant) Parties() (parties []Hash, err error) { 76 var oldPubKey, newPubKey ic.PubKey 77 oldPubKey, err = w.Revocation.getOldKey() 78 if err != nil { 79 return 80 } 81 newPubKey, err = w.Revocation.getNewKey() 82 if err != nil { 83 return 84 } 85 var ID peer.ID 86 ID, err = peer.IDFromPublicKey(oldPubKey) 87 if err != nil { 88 return 89 } 90 var oldH, newH Hash 91 oldH, err = NewHash(peer.IDB58Encode(ID)) 92 if err != nil { 93 return 94 } 95 ID, err = peer.IDFromPublicKey(newPubKey) 96 if err != nil { 97 return 98 } 99 newH, err = NewHash(peer.IDB58Encode(ID)) 100 if err != nil { 101 return 102 } 103 parties = append(parties, oldH, newH) 104 105 return 106 } 107 108 func (w *SelfRevocationWarrant) Verify(h *Holochain) (err error) { 109 // check that the revocation itself verifies 110 err = w.Revocation.Verify() 111 if err != nil { 112 return 113 } 114 // also check that old and new keys appear as they should in the DHT 115 116 var parties []Hash 117 parties, err = w.Parties() 118 if err != nil { 119 return 120 } 121 122 var data []byte 123 data, _, _, _, err = h.dht.Get(parties[0], StatusDefault, GetMaskDefault) 124 if err != ErrHashModified { 125 err = errors.New("expected old key to be modified on DHT") 126 return 127 } else { 128 err = nil 129 } 130 if string(data) != parties[1].String() { 131 err = errors.New("expected old key to point to new key on DHT") 132 } 133 134 return 135 } 136 137 func (w *SelfRevocationWarrant) Property(key string) (value interface{}, err error) { 138 data := w.Revocation.Data 139 if key == "payload" { 140 l := int(data[0]) 141 value = data[l*2+1 : len(data)] 142 return 143 } 144 err = WarrantPropertyNotFoundErr 145 return 146 } 147 148 func (w *SelfRevocationWarrant) Encode() (data []byte, err error) { 149 var rev string 150 rev, err = w.Revocation.Marshal() 151 if err == nil { 152 data = []byte(rev) 153 } 154 return 155 } 156 157 func (w *SelfRevocationWarrant) Decode(data []byte) (err error) { 158 err = w.Revocation.Unmarshal(string(data)) 159 return 160 }