Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
james-choncholas committed Sep 14, 2020
0 parents commit d92d6f4
Show file tree
Hide file tree
Showing 34 changed files with 4,122 additions and 0 deletions.
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
**.o
**.a
!**/lib/*.a
**.d
**Session.vim
**/tags
**/build
**/node_modules
**/geth


alice/to-sign.dat
bob/ECDSA_signature_1.dat
bob/to-sign.dat
verify/sig.bin
verify/sig.hex
verify/to-ver.dat
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "blockchain-crypto-mpc"]
path = blockchain-crypto-mpc
url = ../blockchain-crypto-mpc.git
39 changes: 39 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Use the target `make help` for more information.

##----------------------------------------------------------------------------
## Meta build setup
SHELL := /bin/bash
BASEDIR :=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))

VERBOSE ?= 0
ifeq ($(VERBOSE), 0)
QUIET=@
else
QUIET=
endif

## ----------------------------------------------------------------------------
## Additional Libs
MPC_DIR = $(BASEDIR)/blockchain-crypto-mpc
MPC_LIB = $(MPC_DIR)/libmpc_crypto.so


.PHONY: all help deps

all: help

deps: ## Install blockchain-crypto-mpc dependancies. Requires sudo privileges.
$(QUIET)echo installing blockchain-crypto-mpc library dependancies
$(QUIET)#sudo apt install openjdk-8-jdk make make-guile gcc g++ openssl libssl-dev
$(QUIET)sudo apt install openjdk-8-jdk make gcc g++ openssl libssl-dev
$(QUIET)$(MAKE) JAVA_HOME=$(JAVA_HOME) -C $(MPC_DIR)
$(QUIET)echo installing ethereum dependancies
$(QUIET)sudo add-apt-repository -y ppa:ethereum/ethereum
$(QUIET)sudo apt update
$(QUIET)sudo apt install ethereum


help: ## Show this help.
@echo -e "$$(grep -hE '^\S+:.*##' $(MAKEFILE_LIST) | sed -e 's/:.*##\s*/:/' -e 's/^\(.\+\):\(.*\)/\\x1b[36m\1\\x1b[m:\2/' | column -c2 -t -s :)"


62 changes: 62 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Interview Challange
See [challenge.md](challenge.md) for problem definition.

The solution presented here can be broken into four pieces.
First, the devchain/ directory contains the configuration and setup
to run a private, local blockchain with three participating nodes.
Next a smart contract resides in store-contract/ as a truffle project.
This contract is deployed to the local chain.
Lindell's blockchain-crypto-mpc library is used to run EDDSA
signatures via MPC for two parties.
This process is managed by coordinator.sh in coordinator/.
Finally, the coordinator will upload the signature to the deployed
contract via the web3 client in the chain-bridge/ directory.

# Environment
The following build instructions are for Ubuntu 18.04LTS but will likely work
with little modification on other debian-based operating systems.

# First Run Setup
0) Ensure submodules have been pulled.
```
git submodule init
```

1) Install crypto library dependencies and build.
```
make deps
```

2) Follow the instructions in devchain/README.md.

3) Deploy the truffle contract.
```
cd store-contract
truffle deploy --network devchain
```

4) Install node packages for chain-bridge
```
cd chain-bridge
npm install
```

# Run
```
./devchain/start.sh
./alice/alice.sh pay carol $5
./bob/bob.sh pay carol $5
```
Note to stop the devchain run `./devchain/stop.sh`

Note: both alice and bob have the ability to fake a signature using an incorrect key shard.
Passing the `-f` flag to the script enables this behavior.
Unfortunately the blockchain-crypto-mpc library crashes when doing this.

# Verify Signature
```
./verify/verify.sh pay carol $5
```

The verify script will pull the signature from the chain and verify with the message passed
in as an argument.
65 changes: 65 additions & 0 deletions alice/alice.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/bin/bash

scriptpath="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
libdir=$scriptpath/../blockchain-crypto-mpc
export LD_LIBRARY_PATH=$libdir
fakesig=false

usage() {
echo "alice <OPTION> [message to sign]"
echo "OPTIONS"
echo " -h Print this message"
echo " -f Fake the signature"
echo
echo "example: alice -f pay carol $5"
}

OPTS=`getopt -l help fh "$@"`

if [ $? != 0 ] ; then echo "Failed parsing options." >&2 ; exit 1 ; fi

eval set -- "$OPTS"

while [ "$1" != -- ]
do
case $1 in
-h|--help)
shift
usage
exit 0
;;
-f)
shift
fakesig=true
;;
esac
done

shift # removing '--' from arg list

message=$@

# crypto-lib wants 32 digit hex value - assuming md5
cksum <<< $message | cut -f 1 -d ' ' > $scriptpath/to-sign.dat

# First generate keys
if [ ! -f $scriptpath/key_share_alice.bin ]; then
echo "Generating Alice's ECDSA key shard..."
python $libdir/python/mpc_demo.py --out_file $scriptpath/key_share_alice.bin --server
sleep 1 # wait for alice to die
fi

# Decide if we are faking a signature
if $fakesig ; then
keyfile=$scriptpath/fake-key.bin
else
keyfile=$scriptpath/key_share_alice.bin
fi

# Now sign
cd $scriptpath
echo "Signing..."
python $libdir/python/mpc_demo.py --in_file $keyfile --data_file $scriptpath/to-sign.dat --server
cd -

# Bob (client) uploads for us. This is okay because bob signed and wants the sig visible just as much as us.
Binary file added alice/fake-key.bin
Binary file not shown.
Binary file added alice/key_share_alice.bin
Binary file not shown.
66 changes: 66 additions & 0 deletions bob/bob.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/bin/bash

scriptpath="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
libdir=$scriptpath/../blockchain-crypto-mpc
export LD_LIBRARY_PATH=$libdir
fakesig=false

usage() {
echo "bob <OPTION> [message to sign]"
echo "OPTIONS"
echo " -h Print this message"
echo " -f Fake the signature"
echo
echo "example: bob -f pay carol $5"
}

OPTS=`getopt -l help fh "$@"`

if [ $? != 0 ] ; then echo "Failed parsing options." >&2 ; exit 1 ; fi

eval set -- "$OPTS"

while [ "$1" != -- ]
do
case $1 in
-h|--help)
shift
usage
exit 0
;;
-f)
shift
fakesig=true
;;
esac
done

shift # removing '--' from arg list

message=$@

# crypto-lib wants 32 digit hex value - assuming md5
cksum <<< $message | cut -f 1 -d ' ' > $scriptpath/to-sign.dat

# First generate keys
if [ ! -f $scriptpath/key_share_bob.bin ]; then
echo "Generating Bob's ECDSA key shard..."
python $libdir/python/mpc_demo.py --type ECDSA --command generate --out_file $scriptpath/key_share_bob.bin --host localhost
sleep 5 # wait for alice and bob to die before trying to reconnect
fi

# Decide if we are faking a signature
if $fakesig ; then
keyfile=$scriptpath/fake-key.bin
else
keyfile=$scriptpath/key_share_bob.bin
fi

# Now sign
cd $scriptpath
echo "Signing..."
python $libdir/python/mpc_demo.py --type ECDSA --command sign --in_file $keyfile --data_file $scriptpath/to-sign.dat --host localhost
cd -

# upload to chain
node $scriptpath/../chain-bridge/app.js -s $(xxd -p $scriptpath/ECDSA_signature_1.dat | tr -d '\n')
Binary file added bob/fake-key.bin
Binary file not shown.
Binary file added bob/key_share_bob.bin
Binary file not shown.
1 change: 1 addition & 0 deletions chain-bridge/Store.json
70 changes: 70 additions & 0 deletions chain-bridge/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
const fs = require('fs');
const yargs = require('yargs');
const fetch = require("node-fetch");
const url = 'http://localhost:8501';
const Web3 = require('web3');

const contract = require("@truffle/contract");
const StorageArtifacts = require('./Store.json');

var web3;
var Storage;
var storageInstance;

async function start(get, val) {
console.log('looking for local node...');
await fetch(url).catch(err => {
console.error(err);
throw Error('local node not found');
});

console.log('local node active. connecting to node...');
var provider = new Web3.providers.HttpProvider(url);
web3 = new Web3(provider);
//console.log(await web3.eth.net.getId());

console.log('connected to local node. finding contracts...');

Storage = contract(StorageArtifacts);
Storage.setProvider(provider);
storageInstance = await Storage.deployed();
console.log("storage contract address: " + storageInstance.address);

let owner = (await web3.eth.personal.getAccounts())[0];

if (get == "") {
let s = await storageInstance.set(val, {from: owner})
.catch(function(e) {return e;});
console.log('Storing value: ' + val);
console.log(s);
} else {
let v = await storageInstance.get.call({from: owner})
.catch(function(e) {return e;});
console.log('got value: ' + v);
fs.writeFile(get, v, function (err) {
if (err) return console.log(err);
});
}
}

const argv = yargs
.option('s', {
alias : 'to-store',
describe: 'Value to store on-chain',
type: 'string', /* array | boolean | string */
nargs: 1,
default: "",
})
.option('g', {
alias : 'get',
describe: 'Get the value on chain and write to file',
type: 'string', /* array | boolean | string */
nargs: 1,
default: "",
})
.alias('h', 'help')
.help('help')
.showHelpOnFail(true, "Specify --help for available options")
.argv;

start(argv.g, argv.s);
Loading

0 comments on commit d92d6f4

Please sign in to comment.