lib/lightning/onion/sphinx.rb in lightning-onion-0.2.2 vs lib/lightning/onion/sphinx.rb in lightning-onion-0.2.3
- old
+ new
@@ -9,12 +9,11 @@
MAX_HOPS = 20
HOP_LENGTH = PAYLOAD_LENGTH + MAC_LENGTH
MAX_ERROR_PAYLOAD_LENGTH = 256
ERROR_PACKET_LENGTH = MAC_LENGTH + MAX_ERROR_PAYLOAD_LENGTH + 2 + 2
- ZERO_HOP = Lightning::Onion::HopData.parse("\x00" * HOP_LENGTH)
- LAST_PACKET = Lightning::Onion::Packet.new(VERSION, "\x00" * 33, [ZERO_HOP] * MAX_HOPS, "\x00" * MAC_LENGTH)
+ LAST_PACKET = Lightning::Onion::Packet.new(VERSION, "\x00" * 33, '00' * MAX_HOPS * HOP_LENGTH, '00' * MAC_LENGTH)
def self.make_packet(session_key, public_keys, payloads, associated_data)
ephemereal_public_keys, shared_secrets = compute_keys_and_secrets(session_key, public_keys)
filler = generate_filler('rho', shared_secrets[0...-1], HOP_LENGTH, MAX_HOPS)
last_packet = make_next_packet(
@@ -33,34 +32,50 @@
associated_data
)
[packet, shared_secrets.zip(public_keys)]
end
+ # @return payload 33bytes payload of the outermost layer of onions,which including realm
+ # @return packet
+ def self.parse(private_key, raw_packet)
+ packet = Lightning::Onion::Packet.parse(raw_packet)
+ shared_secret = compute_shared_secret(packet.public_key, private_key)
+ rho = generate_key('rho', shared_secret)
+ bin = xor(
+ (packet.routing_info + '00' * HOP_LENGTH).htb.unpack('C*'),
+ generate_cipher_stream(rho, HOP_LENGTH + MAX_HOPS * HOP_LENGTH).unpack('C*')
+ )
+ payload = bin[0...HOP_LENGTH].pack('C*')
+ hmac = bin[PAYLOAD_LENGTH...HOP_LENGTH].pack('C*')
+ next_hops_data = bin[HOP_LENGTH..-1]
+
+ next_public_key = make_blind(packet.public_key, compute_blinding_factor(packet.public_key, shared_secret))
+ routing_info = next_hops_data.pack('C*').bth
+ [Lightning::Onion::HopData.parse(payload), Lightning::Onion::Packet.new(VERSION, next_public_key, routing_info, hmac.bth), shared_secret]
+ end
+
def self.internal_make_packet(hop_payloads, keys, shared_secrets, packet, associated_data)
return packet if hop_payloads.empty?
next_packet = make_next_packet(hop_payloads.last, associated_data, keys.last, shared_secrets.last, packet)
internal_make_packet(hop_payloads[0...-1], keys[0...-1], shared_secrets[0...-1], next_packet, associated_data)
end
def self.make_next_packet(payload, associated_data, ephemereal_public_key, shared_secret, packet, filler = '')
- hops_data1 = payload.htb << packet.hmac << packet.hops_data.map(&:to_payload).join[0...-HOP_LENGTH]
- stream = generate_cipher_stream(generate_key('rho', shared_secret), MAX_HOPS * HOP_LENGTH)
+ hops_data1 = payload.htb << packet.hmac.htb << packet.routing_info.htb[0...-HOP_LENGTH]
+ rho_key = generate_key('rho', shared_secret)
+ stream = generate_cipher_stream(rho_key, MAX_HOPS * HOP_LENGTH)
hops_data2 = xor(hops_data1.unpack('C*'), stream.unpack('C*'))
next_hops_data =
if filler.empty?
hops_data2
else
hops_data2[0...-filler.htb.unpack('C*').size] + filler.htb.unpack('C*')
end
- next_hmac = mac(generate_key('mu', shared_secret), next_hops_data + associated_data.htb.unpack('C*'))
- hops_data = []
- 20.times do |i|
- payload = next_hops_data.pack('C*')[i * HOP_LENGTH...(i + 1) * HOP_LENGTH]
- hops_data << Lightning::Onion::HopData.parse(payload)
- end
-
- Lightning::Onion::Packet.new(VERSION, ephemereal_public_key, hops_data, next_hmac)
+ mu_key = generate_key('mu', shared_secret)
+ next_hmac = mac(mu_key, next_hops_data + associated_data.htb.unpack('C*'))
+ routing_info = next_hops_data.pack('C*').bth
+ Lightning::Onion::Packet.new(VERSION, ephemereal_public_key, routing_info, next_hmac.bth)
end
def self.compute_keys_and_secrets(session_key, public_keys)
point = ECDSA::Group::Secp256k1.generator
generator_pubkey = ECDSA::Format::PointOctetString.encode(point, compression: true)
@@ -153,30 +168,9 @@
a.zip(b).map { |x, y| ((x ^ y) & 0xff) }
end
def self.mac(key, message)
hmac256(key, message.pack('C*'))[0...MAC_LENGTH]
- end
-
- def self.parse(private_key, raw_packet)
- packet = Lightning::Onion::Packet.parse(raw_packet)
- shared_secret = compute_shared_secret(packet.public_key, private_key)
- rho = generate_key('rho', shared_secret)
- bin = xor(
- (packet.hops_data.map(&:to_payload).join + "\x00" * HOP_LENGTH).unpack('C*'),
- generate_cipher_stream(rho, HOP_LENGTH + MAX_HOPS * HOP_LENGTH).unpack('C*')
- )
- payload = bin[0...PAYLOAD_LENGTH].pack('C*')
- hmac = bin[PAYLOAD_LENGTH...HOP_LENGTH].pack('C*')
- next_hops_data = bin[HOP_LENGTH..-1]
-
- next_public_key = make_blind(packet.public_key, compute_blinding_factor(packet.public_key, shared_secret))
- hops_data = []
- 20.times do |i|
- hop_payload = next_hops_data.pack('C*')[i * HOP_LENGTH...(i + 1) * HOP_LENGTH]
- hops_data << Lightning::Onion::HopData.parse(hop_payload)
- end
- [payload, Lightning::Onion::Packet.new(VERSION, next_public_key, hops_data, hmac), shared_secret]
end
def self.make_error_packet(shared_secret, failure)
message = failure.to_payload
um = generate_key('um', shared_secret)