Skip to content

Instantly share code, notes, and snippets.

@jpopesculian
Last active September 4, 2019 09:34
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save jpopesculian/bcbe046cd77064085b5b27e2ddfc6a03 to your computer and use it in GitHub Desktop.
Zen Example
import hashlib
import base58
import base64
import json
from zenroom_minimal import Zenroom
from cryptoconditions import read_zencode
from cryptoconditions import ZenroomSha256
from datetime import datetime
from bigchaindb_driver.crypto import generate_keypair
from bigchaindb_driver import BigchainDB
BDB_URL = 'http://localhost:9984/'
VERSION = '2.0'
def gen_keyring():
zenroom = Zenroom(read_zencode)
zenroom.load("""
Scenario 'signing': "Generate a new keyring"
Given a blank keyring
Then generate a new key pair
And serialize my keyring
And return 'serialized keyring'
""")
return json.loads(zenroom.eval())["serialized_keyring"]
def sign(message, keyring):
zenroom = Zenroom(read_zencode)
zenroom.load("""
Scenario 'signing': "Sign a message"
Given that I am 'alice'
And a blank keyring
And the input 'message'
Then load my serialized private key
And decode base64 'message'
And sign 'message'
And encode base64 'signature'
And return 'signature'
""")
zenroom.load_data("{ message = '%s' }" % message)
zenroom.load_keys("{ alice = '%s' }" % json.dumps(keyring))
return json.loads(zenroom.eval())["signature"]
def verify(message, signature, keyring):
zenroom = Zenroom(read_zencode)
zenroom.load("""
Scenario 'signing': "Verify a message"
Given that I am 'alice'
And a blank keyring
And the input 'message'
And the input 'signature'
Then load my serialized public key
And decode base64 'message'
And decode base64 'signature'
And verify the signature for 'message'
And assert 'verified'
""")
zenroom.load_data("{ message = '%s', signature = '%s' }" %(message, signature))
zenroom.load_keys("{ alice = '%s' }" % json.dumps(keyring))
return json.loads(zenroom.eval())
def build_tx(owner1, owner2, fulfillment):
tx_input = {
'fulfillment': None,
'fulfills': None,
'owners_before': (owner1.public_key,)
}
tx_output = {
'amount': '10',
'condition': {
'details': {
'type': fulfillment.TYPE_NAME,
'script': base58.b58encode(fulfillment.script).decode()
},
'uri': fulfillment.condition.serialize_uri()
},
'public_keys': (owner2.public_key,),
}
return {
'id': None,
'operation': 'CREATE',
'version': VERSION,
'asset': { 'data': { 'nonce': str(datetime.now()) } },
'metadata': None,
'inputs': (tx_input,),
'outputs': (tx_output,)
}
def encode_tx(tx):
return json.dumps(
tx,
sort_keys=True,
separators=(',', ':'),
ensure_ascii=False
).encode()
def hash_tx(tx):
return hashlib.sha3_256(encode_tx(tx)).digest()
def create_id(tx):
return hashlib.sha3_256(encode_tx(tx)).hexdigest()
def sign_tx(tx, fulfillment, keyring):
message = base64.urlsafe_b64encode(hash_tx(tx))[0:-1].decode('utf-8')
signature = sign(message, keyring)
fulfillment.data = signature
tx['inputs'][0]['fulfillment'] = fulfillment.serialize_uri()
tx['id'] = create_id(tx)
return tx
owner1, owner2 = generate_keypair(), generate_keypair()
keyring = gen_keyring()
print("🔑 Keys generated")
script = """
Scenario 'signing': "Verify a message"
Given the constant 'public key' is '%s'
And a blank keyring
And the input 'message'
And the input 'signature'
Then load serialized public key from 'public key'
And decode base64 'message'
And decode base64 'signature'
And verify the signature for 'message'
And assert 'verified'
""" % keyring["public"]
fulfillment = ZenroomSha256(script=script)
tx = build_tx(owner1, owner2, fulfillment)
print("🔨 Transaction built")
tx = sign_tx(tx, fulfillment, keyring)
print("🔏 Transaction signed")
returned_tx = BigchainDB(BDB_URL).transactions.send_async(tx)
print("👍 Transaction created")
print("")
print(returned_tx)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment