aboutsummaryrefslogtreecommitdiff
path: root/src/gnunet/service/gns/block.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/gnunet/service/gns/block.go')
-rw-r--r--src/gnunet/service/gns/block.go185
1 files changed, 185 insertions, 0 deletions
diff --git a/src/gnunet/service/gns/block.go b/src/gnunet/service/gns/block.go
new file mode 100644
index 0000000..9d83f99
--- /dev/null
+++ b/src/gnunet/service/gns/block.go
@@ -0,0 +1,185 @@
1package gns
2
3import (
4 "fmt"
5
6 "gnunet/crypto"
7 "gnunet/enums"
8 "gnunet/message"
9 "gnunet/util"
10
11 "github.com/bfix/gospel/crypto/ed25519"
12 "github.com/bfix/gospel/data"
13)
14
15var (
16 ErrBlockNotDecrypted = fmt.Errorf("GNS block not decrypted")
17)
18
19//======================================================================
20// GNS block: An encrypted and signed container for GNS resource records
21// that represents the "atomic" data structure associated with a GNS
22// label in a given zone.
23//======================================================================
24
25// SignedBlockData: signed and encrypted list of resource records stored
26// in a GNSRecordSet
27type SignedBlockData struct {
28 Purpose *crypto.SignaturePurpose // Size and purpose of signature (8 bytes)
29 Expire util.AbsoluteTime // Expiration time of the block.
30 EncData []byte `size:"*"` // encrypted GNSRecordSet
31
32 // transient data (not serialized)
33 data []byte // unencrypted GNSRecord set
34}
35
36// GNSBlock is the result of GNS lookups for a given label in a zone.
37type GNSBlock struct {
38 Signature []byte `size:"64"` // Signature of the block.
39 DerivedKey []byte `size:"32"` // Derived key used for signing
40 Block *SignedBlockData
41
42 // transient data (not serialized)
43 checked bool // block integrity checked
44 verified bool // block signature verified (internal)
45 decrypted bool // block data decrypted (internal)
46}
47
48// String returns the human-readable representation of a GNSBlock
49func (b *GNSBlock) String() string {
50 return fmt.Sprintf("GNSBlock{Verified=%v,Decrypted=%v,data=[%d]}",
51 b.verified, b.decrypted, len(b.Block.EncData))
52}
53
54// Records returns the list of resource records in a block.
55func (b *GNSBlock) Records() ([]*message.GNSResourceRecord, error) {
56 // check if block is decrypted
57 if !b.decrypted {
58 return nil, ErrBlockNotDecrypted
59 }
60 // parse block data into record set
61 rs := NewGNSRecordSet()
62 if err := data.Unmarshal(rs, b.Block.data); err != nil {
63 return nil, err
64 }
65 return rs.Records, nil
66}
67
68// Verify the integrity of the block data from a signature.
69func (b *GNSBlock) Verify(zoneKey *ed25519.PublicKey, label string) (err error) {
70 // Integrity check performed
71 b.checked = true
72
73 // verify derived key
74 dkey := ed25519.NewPublicKeyFromBytes(b.DerivedKey)
75 dkey2 := crypto.DerivePublicKey(zoneKey, label, "gns")
76 if !dkey.Q.Equals(dkey2.Q) {
77 return fmt.Errorf("Invalid signature key for GNS Block")
78 }
79 // verify signature
80 var (
81 sig *ed25519.EcSignature
82 buf []byte
83 ok bool
84 )
85 if sig, err = ed25519.NewEcSignatureFromBytes(b.Signature); err != nil {
86 return
87 }
88 if buf, err = data.Marshal(b.Block); err != nil {
89 return
90 }
91 if ok, err = dkey.EcVerify(buf, sig); err == nil && !ok {
92 err = fmt.Errorf("Signature verification failed for GNS block")
93 }
94 b.verified = true
95 return
96}
97
98// Decrypt block data with a key/iv combination derived from (PKEY,label)
99func (b *GNSBlock) Decrypt(zoneKey *ed25519.PublicKey, label string) (err error) {
100 // decrypt payload
101 b.Block.data, err = crypto.DecryptBlock(b.Block.EncData, zoneKey, label)
102 b.decrypted = true
103 return
104}
105
106// NewGNSBlock instantiates an empty GNS block
107func NewGNSBlock() *GNSBlock {
108 return &GNSBlock{
109 Signature: make([]byte, 64),
110 DerivedKey: make([]byte, 32),
111 Block: &SignedBlockData{
112 Purpose: new(crypto.SignaturePurpose),
113 Expire: *new(util.AbsoluteTime),
114 EncData: nil,
115 data: nil,
116 },
117 checked: false,
118 verified: false,
119 decrypted: false,
120 }
121}
122
123//----------------------------------------------------------------------
124// GNSRecordSet
125//----------------------------------------------------------------------
126
127// GNSRecordSet ist the GNUnet data structure for a list of resource records
128// in a GNSBlock. As part of GNUnet messages, the record set is padded so that
129// the binary size of (records||padding) is the smallest power of two.
130type GNSRecordSet struct {
131 Count uint32 `order:"big"` // number of resource records
132 Records []*message.GNSResourceRecord `size:"Count"` // list of resource records
133 Padding []byte `size:"*"` // padding
134}
135
136// NewGNSRecordSet returns an empty resource record set.
137func NewGNSRecordSet() *GNSRecordSet {
138 return &GNSRecordSet{
139 Count: 0,
140 Records: make([]*message.GNSResourceRecord, 0),
141 Padding: make([]byte, 0),
142 }
143}
144
145// AddRecord to append a resource record to the set.
146func (rs *GNSRecordSet) AddRecord(rec *message.GNSResourceRecord) {
147 rs.Count++
148 rs.Records = append(rs.Records, rec)
149}
150
151//======================================================================
152// List of resource records types (for GNS/DNS queries)
153//======================================================================
154
155// RRTypeList is a list of integers representing RR types.
156type RRTypeList []int
157
158// Initialize a new type list with given type values
159func NewRRTypeList(args ...int) (res RRTypeList) {
160 for _, val := range args {
161 // if GNS_TYPE_ANY is encountered, it becomes the sole type
162 if val == enums.GNS_TYPE_ANY {
163 res = make(RRTypeList, 1)
164 res[0] = val
165 return
166 }
167 res = append(res, val)
168 }
169 return
170}
171
172// HasType returns true if the type is included in the list
173func (tl RRTypeList) HasType(t int) bool {
174 // return true if type is GNS_TYPE_ANY
175 if tl[0] == enums.GNS_TYPE_ANY {
176 return true
177 }
178 // check for type in list
179 for _, val := range tl {
180 if val == t {
181 return true
182 }
183 }
184 return false
185}