mirror of
https://github.com/muun/recovery.git
synced 2025-02-23 11:32:33 -05:00
62 lines
2.2 KiB
Go
62 lines
2.2 KiB
Go
|
package sphinx
|
||
|
|
||
|
import (
|
||
|
"crypto/rand"
|
||
|
|
||
|
"github.com/aead/chacha20"
|
||
|
"github.com/btcsuite/btcd/btcec"
|
||
|
)
|
||
|
|
||
|
// PacketFiller is a function type to be specified by the caller to provide a
|
||
|
// stream of random bytes derived from a CSPRNG to fill out the starting packet
|
||
|
// in order to ensure we don't leak information on the true route length to the
|
||
|
// receiver. The packet filler may also use the session key to generate a set
|
||
|
// of filler bytes if it wishes to be deterministic.
|
||
|
type PacketFiller func(*btcec.PrivateKey, *[routingInfoSize]byte) error
|
||
|
|
||
|
// RandPacketFiller is a packet filler that reads a set of random bytes from a
|
||
|
// CSPRNG.
|
||
|
func RandPacketFiller(_ *btcec.PrivateKey, mixHeader *[routingInfoSize]byte) error {
|
||
|
// Read out random bytes to fill out the rest of the starting packet
|
||
|
// after the hop payload for the final node. This mitigates a privacy
|
||
|
// leak that may reveal a lower bound on the true path length to the
|
||
|
// receiver.
|
||
|
if _, err := rand.Read(mixHeader[:]); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// BlankPacketFiller is a packet filler that doesn't attempt to fill out the
|
||
|
// packet at all. It should ONLY be used for generating test vectors or other
|
||
|
// instances that required deterministic packet generation.
|
||
|
func BlankPacketFiller(_ *btcec.PrivateKey, _ *[routingInfoSize]byte) error {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// DeterministicPacketFiller is a packet filler that generates a deterministic
|
||
|
// set of filler bytes by using chacha20 with a key derived from the session
|
||
|
// key.
|
||
|
func DeterministicPacketFiller(sessionKey *btcec.PrivateKey,
|
||
|
mixHeader *[routingInfoSize]byte) error {
|
||
|
|
||
|
// First, we'll generate a new key that'll be used to generate some
|
||
|
// random bytes for our padding purposes. To derive this new key, we
|
||
|
// essentially calculate: HMAC("pad", sessionKey).
|
||
|
var sessionKeyBytes Hash256
|
||
|
copy(sessionKeyBytes[:], sessionKey.Serialize())
|
||
|
paddingKey := generateKey("pad", &sessionKeyBytes)
|
||
|
|
||
|
// Now that we have our target key, we'll use chacha20 to generate a
|
||
|
// series of random bytes directly into the passed mixHeader packet.
|
||
|
var nonce [8]byte
|
||
|
padCipher, err := chacha20.NewCipher(nonce[:], paddingKey[:])
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
padCipher.XORKeyStream(mixHeader[:], mixHeader[:])
|
||
|
|
||
|
return nil
|
||
|
}
|