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