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  }