Skip to content

Commit

Permalink
Add support for custom initial fillers
Browse files Browse the repository at this point in the history
All-zero initial packets should only be used for generating
test vectors or other instances that requires deterministic
packet generation also according to bolt #4,
The packet is initialized with 1300 random bytes derived
from a CSPRNG (ChaCha20). The pad key is used to extract
additional random bytes from a ChaCha20  stream, using it as
a CSPRNG for this purpose. Once the paddingKey has been obtained,
ChaCha20 is used with an all zero nonce, to generate 1300 random
bytes. Those random bytes are then used as the starting state of
the mix-header to be created.

See more
(https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md#packet-construction)
  • Loading branch information
aarani committed Jun 11, 2021
1 parent b2f17bc commit 42876d9
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 5 deletions.
17 changes: 15 additions & 2 deletions src/DotNetLightning.Core/Crypto/Sphinx.fs
Original file line number Diff line number Diff line change
Expand Up @@ -194,22 +194,35 @@ module Sphinx =
HMAC = nextHmac }
nextPacket

module PacketFiller =
// DeterministicPacketFiller is a packet filler that generates a deterministic
// set of filler bytes by using chacha20 with a key derived from the session
// key.
let DeterministicPacketFiller (sessionKey: Key) =
generateStream(generateKey("pad",sessionKey.ToBytes()), 1300)

// 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.
let BlankPacketFiller _=
Array.zeroCreate 1300

type PacketAndSecrets = {
Packet: OnionPacket
/// Shared secrets (one per node in the route). Known (and needed) only if you're creating the
/// packet. Empty if you're just forwarding the packet to the next node
SharedSecrets: (Key * PubKey) list
}
with
static member Create (sessionKey: Key, pubKeys: PubKey list, payloads: byte[] list, ad: byte[]) =
static member Create (sessionKey: Key, pubKeys: PubKey list, payloads: byte[] list, ad: byte[], initialPacketFiller: Key -> byte[]) =
let (ephemeralPubKeys, sharedSecrets) = computeEphemeralPublicKeysAndSharedSecrets (sessionKey) (pubKeys)
let filler = generateFiller "rho" payloads sharedSecrets

let lastPacket = makeNextPacket(payloads |> List.last,
ad,
ephemeralPubKeys |> List.last,
(sharedSecrets |> List.last |> fun ss -> ss.ToBytes()),
OnionPacket.LastPacket,
{OnionPacket.LastPacket with HopData = initialPacketFiller(sessionKey)},
Some(filler))
let rec loop (hopPayloads: byte[] list, ephKeys: PubKey list, ss: Key list, packet: OnionPacket) =
if (hopPayloads.IsEmpty) then
Expand Down
6 changes: 3 additions & 3 deletions tests/DotNetLightning.Core.Tests/SphinxTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ let bolt4Tests1 =

testCase "Create packet (reference test vector)" <| fun _ ->
let (onion, _ss) =
let p = PacketAndSecrets.Create (sessionKey, pubKeys, payloads, associatedData)
let p = PacketAndSecrets.Create (sessionKey, pubKeys, payloads, associatedData, PacketFiller.BlankPacketFiller)
(p.Packet, p.SharedSecrets)
let expectedPacket =
"0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619e5f14350c2a76fc232b5e46d421e9615471ab9e0bc887beff8c95fdb878f7b3a716a996c7845c93d90e4ecbb9bde4ece2f69425c99e4bc820e44485455f135edc0d10f7d61ab590531cf08000179a333a347f8b4072f216400406bdf3bf038659793d4a1fd7b246979e3150a0a4cb052c9ec69acf0f48c3d39cd55675fe717cb7d80ce721caad69320c3a469a202f1e468c67eaf7a7cd8226d0fd32f7b48084dca885d56047694762b67021713ca673929c163ec36e04e40ca8e1c6d17569419d3039d9a1ec866abe044a9ad635778b961fc0776dc832b3a451bd5d35072d2269cf9b040f6b7a7dad84fb114ed413b1426cb96ceaf83825665ed5a1d002c1687f92465b49ed4c7f0218ff8c6c7dd7221d589c65b3b9aaa71a41484b122846c7c7b57e02e679ea8469b70e14fe4f70fee4d87b910cf144be6fe48eef24da475c0b0bcc6565ae82cd3f4e3b24c76eaa5616c6111343306ab35c1fe5ca4a77c0e314ed7dba39d6f1e0de791719c241a939cc493bea2bae1c1e932679ea94d29084278513c77b899cc98059d06a27d171b0dbdf6bee13ddc4fc17a0c4d2827d488436b57baa167544138ca2e64a11b43ac8a06cd0c2fba2d4d900ed2d9205305e2d7383cc98dacb078133de5f6fb6bed2ef26ba92cea28aafc3b9948dd9ae5559e8bd6920b8cea462aa445ca6a95e0e7ba52961b181c79e73bd581821df2b10173727a810c92b83b5ba4a0403eb710d2ca10689a35bec6c3a708e9e92f7d78ff3c5d9989574b00c6736f84c199256e76e19e78f0c98a9d580b4a658c84fc8f2096c2fbea8f5f8c59d0fdacb3be2802ef802abbecb3aba4acaac69a0e965abd8981e9896b1f6ef9d60f7a164b371af869fd0e48073742825e9434fc54da837e120266d53302954843538ea7c6c3dbfb4ff3b2fdbe244437f2a153ccf7bdb4c92aa08102d4f3cff2ae5ef86fab4653595e6a5837fa2f3e29f27a9cde5966843fb847a4a61f1e76c281fe8bb2b0a181d096100db5a1a5ce7a910238251a43ca556712eaadea167fb4d7d75825e440f3ecd782036d7574df8bceacb397abefc5f5254d2722215c53ff54af8299aaaad642c6d72a14d27882d9bbd539e1cc7a527526ba89b8c037ad09120e98ab042d3e8652b31ae0e478516bfaf88efca9f3676ffe99d2819dcaeb7610a626695f53117665d267d3f7abebd6bbd6733f645c72c389f03855bdf1e4b8075b516569b118233a0f0971d24b83113c0b096f5216a207ca99a7cddc81c130923fe3d91e7508c9ac5f2e914ff5dccab9e558566fa14efb34ac98d878580814b94b73acbfde9072f30b881f7f0fff42d4045d1ace6322d86a97d164aa84d93a60498065cc7c20e636f5862dc81531a88c60305a2e59a985be327a6902e4bed986dbf4a0b50c217af0ea7fdf9ab37f9ea1a1aaa72f54cf40154ea9b269f1a7c09f9f43245109431a175d50e2db0132337baa0ef97eed0fcf20489da36b79a1172faccc2f7ded7c60e00694282d93359c4682135642bc81f433574aa8ef0c97b4ade7ca372c5ffc23c7eddd839bab4e0f14d6df15c9dbeab176bec8b5701cf054eb3072f6dadc98f88819042bf10c407516ee58bce33fbe3b3d86a54255e577db4598e30a135361528c101683a5fcde7e8ba53f3456254be8f45fe3a56120ae96ea3773631fcb3873aa3abd91bcff00bd38bd43697a2e789e00da6077482e7b1b1a677b5afae4c54e6cbdf7377b694eb7d7a5b913476a5be923322d3de06060fd5e819635232a2cf4f0731da13b8546d1d6d4f8d75b9fce6c2341a71b0ea6f780df54bfdb0dd5cd9855179f602f9172307c7268724c3618e6817abd793adc214a0dc0bc616816632f27ea336fb56dfd"
Expand Down Expand Up @@ -108,7 +108,7 @@ let bolt4Tests1 =

testCase "last node replies with an error message" <| fun _ ->
let (onion, ss) =
let p = PacketAndSecrets.Create (sessionKey, pubKeys, payloads, associatedData)
let p = PacketAndSecrets.Create (sessionKey, pubKeys, payloads, associatedData, PacketFiller.BlankPacketFiller)
(p.Packet, p.SharedSecrets)
let { NextPacket = packet1; SharedSecret = ss0 }: ParsedPacket =
Sphinx.parsePacket (privKeys.[0]) (associatedData) (onion.ToBytes())
Expand Down Expand Up @@ -166,7 +166,7 @@ let bolt4Tests1 =

testCase "Intermediate node replies with an error message" <| fun _ ->
let { Packet = packet; SharedSecrets = ss } =
Sphinx.PacketAndSecrets.Create(sessionKey, pubKeys, payloads, associatedData)
Sphinx.PacketAndSecrets.Create(sessionKey, pubKeys, payloads, associatedData, PacketFiller.BlankPacketFiller)
let { NextPacket = packet1; SharedSecret = ss0 } =
Sphinx.parsePacket(privKeys.[0]) (associatedData) (packet.ToBytes())
|> Result.defaultWith(fun _ -> failwith "Fail: bolt4 intrm node replies with err msg defaultClosure0")
Expand Down

0 comments on commit 42876d9

Please sign in to comment.