Skip to content

Commit e6b9314

Browse files
committed
add fat error encryption and decryption
1 parent 371dfed commit e6b9314

8 files changed

+789
-0
lines changed

crypto.go

+4
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ type DecryptedError struct {
9292

9393
// Message is the decrypted error message.
9494
Message []byte
95+
96+
// Payloads is an array of data blocks reported by each node on the (error)
97+
// path.
98+
Payloads [][]byte
9599
}
96100

97101
// zeroHMAC is the special HMAC value that allows the final node to determine

fat_error_crypto.go

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package sphinx
2+
3+
import (
4+
"crypto/hmac"
5+
"crypto/sha256"
6+
"encoding/binary"
7+
)
8+
9+
var byteOrder = binary.BigEndian
10+
11+
type FatErrorStructure struct {
12+
MaxHops int
13+
MaxPayloadSize int
14+
}
15+
16+
type fatErrorBase struct {
17+
maxHops int
18+
totalHmacs int
19+
allHmacsLen int
20+
hmacsAndPayloadsLen int
21+
allPayloadsLen int
22+
payloadLen int
23+
payloadDataLen int
24+
}
25+
26+
func newFatErrorBase(structure *FatErrorStructure) fatErrorBase {
27+
var (
28+
payloadDataLen = structure.MaxPayloadSize
29+
30+
// payloadLen is the size of the per-node payload. It consists of a 1-byte
31+
// payload type followed by the payload data.
32+
payloadLen = 1 + payloadDataLen
33+
34+
totalHmacs = (structure.MaxHops * (structure.MaxHops + 1)) / 2
35+
allHmacsLen = totalHmacs * sha256.Size
36+
allPayloadsLen = payloadLen * structure.MaxHops
37+
hmacsAndPayloadsLen = allHmacsLen + allPayloadsLen
38+
)
39+
40+
return fatErrorBase{
41+
totalHmacs: totalHmacs,
42+
allHmacsLen: allHmacsLen,
43+
hmacsAndPayloadsLen: hmacsAndPayloadsLen,
44+
allPayloadsLen: allPayloadsLen,
45+
maxHops: structure.MaxHops,
46+
payloadLen: payloadLen,
47+
payloadDataLen: payloadDataLen,
48+
}
49+
}
50+
51+
// getMsgComponents splits a complete failure message into its components
52+
// without re-allocating memory.
53+
func (o *fatErrorBase) getMsgComponents(data []byte) ([]byte, []byte, []byte) {
54+
payloads := data[len(data)-o.hmacsAndPayloadsLen : len(data)-o.allHmacsLen]
55+
hmacs := data[len(data)-o.allHmacsLen:]
56+
message := data[:len(data)-o.hmacsAndPayloadsLen]
57+
58+
return message, payloads, hmacs
59+
}
60+
61+
// calculateHmac calculates an hmac given a shared secret and a presumed
62+
// position in the path. Position is expressed as the distance to the error
63+
// source. The error source itself is at position 0.
64+
func (o *fatErrorBase) calculateHmac(sharedSecret Hash256, position int,
65+
message, payloads, hmacs []byte) []byte {
66+
67+
umKey := generateKey("um", &sharedSecret)
68+
hash := hmac.New(sha256.New, umKey[:])
69+
70+
// Include message.
71+
_, _ = hash.Write(message)
72+
73+
// Include payloads including our own.
74+
_, _ = hash.Write(payloads[:(o.maxHops-position)*o.payloadLen])
75+
76+
// Include downstream hmacs.
77+
var hmacsIdx = position + o.maxHops
78+
for j := 0; j < o.maxHops-position-1; j++ {
79+
_, _ = hash.Write(
80+
hmacs[hmacsIdx*sha256.Size : (hmacsIdx+1)*sha256.Size],
81+
)
82+
83+
hmacsIdx += o.maxHops - j - 1
84+
}
85+
86+
return hash.Sum(nil)
87+
}

0 commit comments

Comments
 (0)