github.com/holochain/holochain-proto@v0.1.0-alpha-26.0.20200915073418-5c83169c9b5b/revocation.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  // interface for revoking keys
     6  
     7  package holochain
     8  
     9  import (
    10  	"encoding/json"
    11  	"errors"
    12  	ic "github.com/libp2p/go-libp2p-crypto"
    13  )
    14  
    15  type Revocation interface {
    16  	Verify() error
    17  	Marshal() (string, error)
    18  	Unmarshal(string) error
    19  }
    20  
    21  var SelfRevocationDoesNotVerify = errors.New("self revocation does not verify")
    22  
    23  // SelfRevocation holds the old key being revoked and the new key, other revocation data and
    24  // the two cryptographic signatures of that data by the two keys to confirm the revocation
    25  type SelfRevocation struct {
    26  	Data   []byte // concatination of key length, two marshaled keys, and revocation properties
    27  	OldSig []byte // signature of oldnew by old key
    28  	NewSig []byte // signature by oldnew new key
    29  }
    30  
    31  func NewSelfRevocation(old, new ic.PrivKey, payload []byte) (rP *SelfRevocation, err error) {
    32  	oldPub := old.GetPublic()
    33  	newPub := new.GetPublic()
    34  	var oldPubBytes, newPubBytes, oldSig, newSig []byte
    35  	oldPubBytes, err = ic.MarshalPublicKey(oldPub)
    36  	if err != nil {
    37  		return
    38  	}
    39  	newPubBytes, _ = ic.MarshalPublicKey(newPub)
    40  	if err != nil {
    41  		return
    42  	}
    43  	data := []byte{byte(len(oldPubBytes))}
    44  
    45  	data = append(data, oldPubBytes...)
    46  	data = append(data, newPubBytes...)
    47  	data = append(data, payload...)
    48  
    49  	oldSig, err = old.Sign(data)
    50  	newSig, err = new.Sign(data)
    51  
    52  	revocation := SelfRevocation{
    53  		Data:   data,
    54  		OldSig: oldSig,
    55  		NewSig: newSig,
    56  	}
    57  	rP = &revocation
    58  	return
    59  }
    60  
    61  func (r *SelfRevocation) getOldKey() (key ic.PubKey, err error) {
    62  	l := int(r.Data[0])
    63  	bytes := r.Data[1 : l+1]
    64  	key, err = ic.UnmarshalPublicKey(bytes)
    65  	return
    66  
    67  }
    68  
    69  func (r *SelfRevocation) getNewKey() (key ic.PubKey, err error) {
    70  	l := int(r.Data[0])
    71  	bytes := r.Data[l+1 : l*2+1]
    72  	key, err = ic.UnmarshalPublicKey(bytes)
    73  	return
    74  }
    75  
    76  func (r *SelfRevocation) Marshal() (data string, err error) {
    77  	var j []byte
    78  	j, err = json.Marshal(r)
    79  	if err == nil {
    80  		data = string(j)
    81  	}
    82  	return
    83  }
    84  
    85  func (r *SelfRevocation) Unmarshal(data string) (err error) {
    86  	err = json.Unmarshal([]byte(data), r)
    87  	return
    88  }
    89  
    90  // Verify confirms that a self-revocation is properly signed
    91  func (r *SelfRevocation) Verify() (err error) {
    92  	var oldPubKey, newPubKey ic.PubKey
    93  	oldPubKey, err = r.getOldKey()
    94  	if err != nil {
    95  		return
    96  	}
    97  	var matches bool
    98  	matches, err = oldPubKey.Verify(r.Data, r.OldSig)
    99  	if err != nil {
   100  		return err
   101  	}
   102  	if !matches {
   103  		return SelfRevocationDoesNotVerify
   104  	}
   105  	newPubKey, err = r.getNewKey()
   106  
   107  	if err != nil {
   108  		return
   109  	}
   110  	matches, err = newPubKey.Verify(r.Data, r.NewSig)
   111  	if err != nil {
   112  		return err
   113  	}
   114  	if !matches {
   115  		return SelfRevocationDoesNotVerify
   116  	}
   117  	return
   118  }