import * as crypto from "@node-lightning/crypto" ; import { ILogger } from "@node-lightning/logger" ; import { bufRightShift } from "./bufRightShift" ; import { generateCipherStream } from "./generateCipherStream" ; import { generateFiller } from "./generateFiller" ; import { generateKey } from "./generateKey" ; import { KeyType } from "./KeyType" ; import { SharedSecretGenerator } from "./SharedSecretGenerator" ; export class OnionPacket { public routingInfo : Buffer ; public headerMac : Buffer ; public hmacs : Buffer [ ] ; constructor ( readonly version = 0x00 , hopPayloads , readonly associatedData , readonly ss , logger ? ) { const numHops = hopPayloads . length ; const hopDataSize = 65 ; const hmacSize = 32 ; const routingInfoSize = 1300 ; const numStreamBytes = routingInfoSize * 2 ; logger ?. trace ( "numHops" , numHops ) ; logger ?. trace ( "hopDataSize" , hopDataSize ) ; logger ?. trace ( "hmacSize" , hmacSize ) ; logger ?. trace ( "routinInfoSize" , routingInfoSize ) ; logger ?. trace ( "numStreamBytes" , numStreamBytes ) ; const filler = generateFiller ( KeyType . rho , numHops , hopDataSize , ss . sharedSecrets ) ; logger ?. trace ( "filler" , filler ) ; const paddingKey = generateKey ( KeyType . pad , ss . sessionKey ) ; logger ?. trace ( "paddingKey" , paddingKey ) ; const paddingBytes = generateCipherStream ( paddingKey , routingInfoSize ) ; logger ?. trace ( "paddingBytes" , paddingBytes ) ; let mixHeader = Buffer . alloc ( routingInfoSize , paddingBytes ) ; logger ?. trace ( "initial mixHeader" , mixHeader ) ; let nextHmac = Buffer . alloc ( hmacSize ) ; logger ?. trace ( "initial nextHmac" , nextHmac ) ; this . hmacs = [ ] ; for ( let i = numHops - 1 ; i >= 0 ; i -- ) { logger ?. trace ( "hop" , i ) ; const rhoKey = generateKey ( KeyType . rho , ss . sharedSecrets [ i ] ) ; logger ?. trace ( "rhoKey" , rhoKey ) ; const muKey = generateKey ( KeyType . mu , ss . sharedSecrets [ i ] ) ; logger ?. trace ( "muKey" , muKey ) ; const streamBytes = generateCipherStream ( rhoKey , numStreamBytes ) ; logger ?. trace ( "streamBytes" , streamBytes ) ; mixHeader = bufRightShift ( mixHeader , hopDataSize ) ; logger ?. trace ( "rightShifted" , mixHeader ) ; const hopData = Buffer . concat ( [ Buffer . alloc ( 1 ) , hopPayloads [ i ] , nextHmac ] ) ; logger ?. trace ( "hopData" , hopData ) ; hopData . copy ( mixHeader ) ; logger ?. trace ( "pre-xor" , mixHeader ) ; mixHeader = crypto . xor ( mixHeader , streamBytes ) ; logger ?. trace ( "post-xor" , mixHeader ) ; if ( i === numHops - 1 ) { filler . copy ( mixHeader , mixHeader . length - filler . length ) ; } const packet = Buffer . concat ( [ mixHeader , associatedData ] ) ; logger ?. trace ( "pre-hmac" , packet ) ; nextHmac = crypto . hmac ( muKey , packet ) ; logger ?. trace ( "hmac" , nextHmac ) ; this . hmacs . unshift ( nextHmac ) ; } this . headerMac = nextHmac ; this . routingInfo = mixHeader ; } public toBuffer ( ) { return Buffer . concat ( [ Buffer . from ( [ this . version ] ) , this . ss . sessionPubKey , this . routingInfo , this . headerMac , ] ) ; } }