Skip to content

Commit

Permalink
initial commit for ex1 and ex2
Browse files Browse the repository at this point in the history
  • Loading branch information
bmancini55 committed Aug 16, 2021
0 parents commit 4e4119e
Show file tree
Hide file tree
Showing 12 changed files with 1,949 additions and 0 deletions.
64 changes: 64 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Typescript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# MacOS
.DS_Store

wallet.dat
*.key
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
This project has several examples of onion packets. Each example builds off prior examples to improve security and privacy.

## Getting Started

1. Install dependencies
```
npm install
```

2. Run example
```
npm start ex1
npm start ex2
```
10 changes: 10 additions & 0 deletions lib/OnionPacket.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { OnionPayload } from "./OnionPayload";

export class OnionPacket {
constructor(
readonly version: number,
readonly payload: OnionPayload,
readonly ephemeralPoint?: Buffer,
readonly hmac?: Buffer
) {}
}
3 changes: 3 additions & 0 deletions lib/OnionPayload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export class OnionPayload {
constructor(readonly data?: Buffer, readonly nextPayload?: Buffer, readonly nextHmac?: Buffer) {}
}
8 changes: 8 additions & 0 deletions lib/encryptData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as crypto from "@node-lightning/crypto";

export function encryptData(key: Buffer, data: Buffer): Buffer {
const iv = Buffer.alloc(16);
const zeros = Buffer.alloc(data.length);
const stream = crypto.chachaEncrypt(key, iv, zeros);
return crypto.xor(data, stream);
}
33 changes: 33 additions & 0 deletions lib/ex1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Stupid Example

This is an example construction that provides zero confidentiality,
integrity, or privacy.

The onion construction simply "wraps" the prior data by prepending the
new data to it.

There is no confidentiality as no obfuscation of data is used.
There is no integrity as no MACs are used.
There is no privacy because you can see how many hops exist in the path.

## Building

If you have data parts that are each 4-bytes: `11111111` and `22222222`
for hops 1 and 2 respectively...

Inner onion: `0422222222`
Outer onion: `0411111111` + `0422222222`

## Reading

To read is quite simple. Each hop strips and reads the length byte and
associated data from the front of the packet. It then forwards the
remainder of the data.

Hop1 input: `04111111110422222222`
Hop1 extracts: `0411111111`
Hop1 forwards: `0422222222`

Hop2 input: `0422222222`
Hop2 extracts: `0422222222`
Hop2 forwards: N/A
116 changes: 116 additions & 0 deletions lib/ex1/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { BufferReader, BufferWriter } from "@node-lightning/bufio";
import { OnionPacket } from "../OnionPacket";
import { OnionPayload } from "../OnionPayload";

/**
* Reads info from the packet. No verification of information is
* performed. This code simply reads from the front of the packet,
* removes its information and then forwards on the remainder of the
* packet.
*
* Any node could tamper with information along the way. And since there
* is no decryption, anyone can see the information (no confidentiality).
*
* @param packet
*/
export function read(packet: Buffer): Buffer {
// Read the packet which usually is constructed as:
// version|eph_key|payload|hmac

const packetReader = new BufferReader(packet);
console.log("read packet: ", packet.toString("hex"));

// read version
const version = packetReader.readUInt8(); // expect version 1
console.log("version: ", version);

// NO ephemeral key

// read payload
const payload = packetReader.readBytes();
console.log("payload: ", payload.toString("hex"));

// NO HMAC

// Next we read the payload which is constructed as:
// len|data|next_data|next_hmac
const payloadReader = new BufferReader(payload);

// read len
const len = payloadReader.readUInt8();
console.log("payload len: ", len);

// read data
const data = payloadReader.readBytes(len);
console.log("payload data:", data.toString("hex"));

// read next payload
const nextPayload = payloadReader.eof ? Buffer.alloc(0) : payloadReader.readBytes();
console.log("next payload:", nextPayload.toString("hex"));

// NO NEXT HMAC
console.log("");

// Abort when we don't have any more data
if (!nextPayload.length) {
return;
}

// Return the next packet
const nextPacket = new BufferWriter();
nextPacket.writeUInt8(version);
// nextPacket.writeBytes(ephemeralPoint); - no ephemeral point
nextPacket.writeBytes(nextPayload);
// nextPacket.writeBytes(nextHmac); - no hmac
return nextPacket.toBuffer();
}

/**
* This example is really stupid but it acts as the foundation for
* building cryptographic onions that actually protect information. This
* construction simply takes the data and builds a linear ordering of
* the data. There is no MAC, no shared secrets, nothing.
*
* As a result, any observer can see the data. Any observer can see
* how many hops there are. Any hop can tamper with the data. So we
* completely lack anonymity, confidentiality, and integrity.
*
* @param data - data to wrap in onion for each hop
*/
export function build(version: number, data: Buffer[]): Buffer {
let lastHopData: Buffer = Buffer.alloc(0);

// Iterate in reverse order to construct our onion from the center
// to the outside. This is not required for this implementation since
// there is no cryptographic wrapping, however we can use a similar
// construct in future implementations that improve on how things work.
while (data.length) {
// Extract the currrent hop information
const currentHopData = data.pop();

// Prepend the current hop information to the existing information
const w = new BufferWriter();

// write length
w.writeBigSize(currentHopData.length);
console.log("data size:", currentHopData.length);

// write data
w.writeBytes(currentHopData);
console.log("data: ", currentHopData.toString("hex"));

// write prior data
w.writeBytes(lastHopData);
console.log("last data:", lastHopData.toString("hex"));

lastHopData = w.toBuffer();
console.log("onion: ", lastHopData.toString("hex"));
console.log("");
}

// Return the outer layer of the onion
const packet = new BufferWriter();
packet.writeUInt8(version);
packet.writeBytes(lastHopData);
return packet.toBuffer();
}
Loading

0 comments on commit 4e4119e

Please sign in to comment.