Skip to content

Commit

Permalink
add fat error encryption and decryption
Browse files Browse the repository at this point in the history
  • Loading branch information
joostjager committed Apr 24, 2023
1 parent 568d591 commit c0682ea
Show file tree
Hide file tree
Showing 7 changed files with 933 additions and 0 deletions.
124 changes: 124 additions & 0 deletions attributable_error_crypto.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package sphinx

import (
"crypto/hmac"
"crypto/sha256"
"io"
)

type payloadSource byte

const (
// payloadIntermediateNode is a marker to signal that this attributable
// error payload is originating from a node between the payer and the error
// source.
payloadIntermediateNode payloadSource = 0

// payloadErrorNode is a marker to signal that this attributable error
// payload is originating from the error source.
payloadErrorNode payloadSource = 1
)

type AttributableErrorStructure struct {
HopCount int
FixedPayloadLen int
}

type attributableErrorBase struct {
maxHops int
totalHmacs int
allHmacsLen int
hmacsAndPayloadsLen int
allPayloadsLen int
payloadLen int
payloadDataLen int
}

func newAttributableErrorBase(
structure *AttributableErrorStructure) attributableErrorBase {

var (
payloadDataLen = structure.FixedPayloadLen

// payloadLen is the size of the per-node payload. It consists of a
// 1-byte payload type followed by the payload data.
payloadLen = 1 + payloadDataLen

totalHmacs = (structure.HopCount *
(structure.HopCount + 1)) / 2

allHmacsLen = totalHmacs * sha256.Size
allPayloadsLen = payloadLen * structure.HopCount
hmacsAndPayloadsLen = allHmacsLen + allPayloadsLen
)

return attributableErrorBase{
totalHmacs: totalHmacs,
allHmacsLen: allHmacsLen,
hmacsAndPayloadsLen: hmacsAndPayloadsLen,
allPayloadsLen: allPayloadsLen,
maxHops: structure.HopCount,
payloadLen: payloadLen,
payloadDataLen: payloadDataLen,
}
}

// getMsgComponents splits a complete failure message into its components
// without re-allocating memory.
func (o *attributableErrorBase) getMsgComponents(data []byte) ([]byte, []byte,
[]byte) {

payloads := data[len(data)-o.hmacsAndPayloadsLen : len(data)-o.allHmacsLen]
hmacs := data[len(data)-o.allHmacsLen:]
message := data[:len(data)-o.hmacsAndPayloadsLen]

return message, payloads, hmacs
}

// calculateHmac calculates an hmac given a shared secret and a presumed
// position in the path. Position is expressed as the distance to the error
// source. The error source itself is at position 0.
func (o *attributableErrorBase) calculateHmac(sharedSecret Hash256,
position int, message, payloads, hmacs []byte) []byte {

umKey := generateKey("um", &sharedSecret)
hash := hmac.New(sha256.New, umKey[:])

// Include message.
_, _ = hash.Write(message)

// Include payloads including our own.
_, _ = hash.Write(payloads[:(o.maxHops-position)*o.payloadLen])

// Include downstream hmacs.
writeDownstreamHmacs(position, o.maxHops, hmacs, hash)

return hash.Sum(nil)
}

// writeDownstreamHmacs writes the hmacs of downstream nodes that are relevant
// for the given position to a writer instance.
func writeDownstreamHmacs(position, maxHops int, hmacs []byte, w io.Writer) {
// Track the index of the next hmac to write in a variable. The first
// maxHops slots are reserved for the hmacs of the current hop and can
// therefore be skipped. The first hmac to write is part of the block of
// hmacs that was written by the first downstream node. Which hmac exactly
// is determined by the assumed position of the current node.
var hmacIdx = maxHops + position

// Iterate over all downstream nodes.
for j := 0; j < maxHops-position-1; j++ {
_, _ = w.Write(
hmacs[hmacIdx*sha256.Size : (hmacIdx+1)*sha256.Size],
)

// Calculate the total number of hmacs in the block of the current
// downstream node.
blockSize := maxHops - j - 1

// Skip to the next block. The new hmac index will point to the hmac
// that corresponds to the next downstream node which is one step closer
// to the assumed error source.
hmacIdx += blockSize
}
}
Loading

0 comments on commit c0682ea

Please sign in to comment.