Added bip38 decryption files, tested out register and activate on new DB, and added profile conversion code (v1 to v2)

This commit is contained in:
Muneeb Ali
2014-06-28 17:56:21 -07:00
parent 629a502800
commit 1a824f06e6
6 changed files with 176 additions and 60 deletions

View File

@@ -5,7 +5,7 @@ import json
import requests
from time import sleep
from coinrpc.coinrpc import namecoind_blocks, namecoind_firstupdate
from coinrpc.namecoin.namecoind_wrapper import namecoind_blocks, namecoind_firstupdate
blocks = namecoind_blocks()
@@ -74,7 +74,6 @@ def do_name_firstupdate():
output = namecoind_firstupdate(entry['key'],entry['rand'],update_value,entry['longhex'])
#output = namecoind_firstupdate(entry['key'], entry['rand'], update_value, entry['longhex'])
print "Transaction ID ", output
if 'message' in output and output['message'] == "this name is already active":
@@ -90,7 +89,7 @@ def do_name_firstupdate():
#sleep(1)
else:
pass
print "wait: " + str(entry['wait_till_block'] - current_blocks) + " blocks"
#-----------------------------------
if __name__ == '__main__':

View File

@@ -1,28 +1,34 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
SLEEP_INTERVAL = 1
#-----------------------
# Copyright 2014 Halfmoon Labs, Inc.
# All Rights Reserved
#-----------------------
#520 is the real limit
VALUE_MAX_LIMIT = 512
from time import sleep
import requests
import json
from coinrpc.coinrpc import namecoind_blocks, namecoind_name_new, check_registration
from coinrpc.coinrpc import namecoind_name_update, namecoind_name_show
from coinrpc.namecoin.namecoind_wrapper import namecoind_blocks, namecoind_name_new, check_registration
from coinrpc.namecoin.namecoind_wrapper import namecoind_name_update, namecoind_name_show
from config import LOAD_BALANCER
#-----------------------------------
from pymongo import MongoClient
db = MongoClient['namecoin']
queue = db.queue
codes = db.codes
client = MongoClient()
from config import MONGODB_URI, HEROKU_APP
local_db = client['namecoin']
queue = local_db.queue
codes = local_db.codes
from config import MONGODB_URI
remote_client = MongoClient(MONGODB_URI)
users = remote_client[HEROKU_APP].user
remote_db = remote_client.get_default_database()
users = remote_db.user
registrations = remote_db.user_registration
#-----------------------------------
def utf8len(s):
@@ -132,7 +138,6 @@ def register_name(key,value):
print reply
print '---'
sleep(SLEEP_INTERVAL)
#-----------------------------------
def update_name(key,value):
@@ -157,7 +162,6 @@ def update_name(key,value):
print reply
print info
print '---'
sleep(SLEEP_INTERVAL)
#----------------------------------
def get_old_keys(username):
@@ -191,7 +195,7 @@ def get_old_keys(username):
return old_keys
#-----------------------------------
def process_user(username,profile,accesscode=None):
def process_user(username,profile):
old_keys = get_old_keys(username)
@@ -206,28 +210,8 @@ def process_user(username,profile,accesscode=None):
if check_registration(key1):
#if name is registered
check_profile = namecoind_name_show(key1)
try:
check_profile = check_profile['value']
#if name is reserved, check code
if 'status' in check_profile and check_profile['status'] == 'reserved':
print "name reserved: " + key1
code = codes.find_one({'username':key1})
if code['accesscode'] == accesscode:
print "code match"
update_name(key1,value1)
else:
#if registered but not reserved
print "name update: " + key1
update_name(key1,value1)
except Exception as e:
#if registered but not reserved
print "name update: " + key1
update_name(key1,value1)
print "name update: " + key1
update_name(key1,value1)
else:
#if not registered
@@ -290,31 +274,23 @@ def set_backend_server(DISTRIBUTE=True):
print "sending " + i['username'] + " to backend_server " + str(selected_server)
#-----------------------------------
def check_new_registrations(IS_LIVE=False):
def check_new_registrations(LIVE=True):
registered_counter = 0
unregistered_counter = 0
print '-' * 5
print "Checking for new users"
for user in users.find():
for user in registrations.find():
if 'dispatched' in user and user['dispatched'] is False:
if not IS_LIVE:
print user['username']
print user['email']
print '-' * 5
unregistered_counter += 1
accesscode = None
if 'accesscode' in user:
accesscode = user['accesscode']
if ('backend_server' in user) and (user['backend_server'] == int(LOAD_BALANCER)):
if IS_LIVE:
if LIVE:
try:
process_user(user['username'],json.loads(user['profile']),accesscode)
process_user(user['username'],json.loads(user['profile']))
print user['backend_server']
except Exception as e:
print e
@@ -326,7 +302,7 @@ def check_new_registrations(IS_LIVE=False):
local = queue.find_one({'key':username})
if local is not None:
print "in local DB"
if IS_LIVE:
if LIVE:
user['dispatched'] = True
user['accepted'] = True
users.save(user)
@@ -342,7 +318,7 @@ def check_new_registrations(IS_LIVE=False):
#-----------------------------------
if __name__ == '__main__':
IS_LIVE = True
LIVE = True
DISTRIBUTE = False
set_backend_server(DISTRIBUTE)
check_new_registrations(IS_LIVE)
check_new_registrations(LIVE)

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#-----------------------
# Copyright 2014 Halfmoon Labs, Inc.
# All Rights Reserved
@@ -17,7 +18,7 @@ except:
DEBUG = True
#--------------------------------------------------
NAMECOIND_READONLY = True
NAMECOIND_READONLY = False
NAMECOIND_USE_HTTPS = True
@@ -29,8 +30,4 @@ except:
#--------------------------------------------------
MONGODB_URI = os.environ['MONGODB_URI']
HEROKU_APP = os.environ['HEROKU_APP']
LOAD_BALANCER = os.environ['LOAD_BALANCER']
LOAD_BALANCER = os.environ['LOAD_BALANCER']

View File

@@ -0,0 +1,83 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#-----------------------
# Copyright 2014 Halfmoon Labs, Inc.
# All Rights Reserved
#-----------------------
"""
BIP 0038
~~~~~
:copyright: (c) 2014 by Halfmoon Labs
:license: MIT, see LICENSE for more details.
"""
import re, os, random, struct, hashlib, binascii, scrypt
from hashlib import sha256
from coinkit import BitcoinKeypair, b58check_encode, b58check_decode
from Crypto.Cipher import AES
def bip38_encrypt(private_key, passphrase, n=16384, r=8, p=8, compressed=False):
# determine the flagbyte
if compressed:
flagbyte = '\xe0'
else:
flagbyte = '\xc0'
# get the private key's address and equivalent in hex format and wif format
k = BitcoinKeypair(private_key)
address = k.address()
hex_private_key = k.private_key()
wif_private_key = k.wif_pk()
# calculate the address's checksum
address_checksum = sha256(sha256(address).digest()).digest()[0:4]
# calculate the scrypt hash and split it in half
scrypt_derived_key = scrypt.hash(passphrase, address_checksum, n, r, p)
derived_half_1 = scrypt_derived_key[0:32]
derived_half_2 = scrypt_derived_key[32:64]
# combine parts of the private key and scrypt hash and AES encrypt them
aes = AES.new(derived_half_2)
encrypted_half_1 = aes.encrypt(
binascii.unhexlify(
'%0.32x' % (long(hex_private_key[0:32], 16) ^ long(binascii.hexlify(derived_half_1[0:16]), 16))
)
)
encrypted_half_2 = aes.encrypt(
binascii.unhexlify(
'%0.32x' % (long(hex_private_key[32:64], 16) ^ long(binascii.hexlify(derived_half_1[16:32]), 16))
)
)
# build the encrypted private key from the checksum and encrypted parts
encrypted_private_key = ('\x42' + flagbyte + address_checksum + encrypted_half_1 + encrypted_half_2)
# base 58 encode the encrypted private key
b58check_encrypted_private_key = b58check_encode(encrypted_private_key, version_byte=1)
# return the encrypted private key
return b58check_encrypted_private_key
def bip38_decrypt(b58check_encrypted_private_key, passphrase, n=16384, r=8, p=8):
# decode private key from base 58 check to binary
encrypted_private_key = b58check_decode(b58check_encrypted_private_key)
# parse the encrypted key different byte sections
bip38_key_identification_byte = encrypted_private_key[0:1]
flagbyte = encrypted_private_key[1:2]
address_checksum = encrypted_private_key[2:6]
encrypted_half_1 = encrypted_private_key[6:6+16]
encrypted_half_2 = encrypted_private_key[6+16:6+32]
# derive a unique key from the passphrase and the address checksum
scrypt_derived_key = scrypt.hash(passphrase, address_checksum, n, r, p)
derived_half_1 = scrypt_derived_key[0:32]
derived_half_2 = scrypt_derived_key[32:64]
# decrypt the encrypted halves
aes = AES.new(derived_half_2)
decrypted_half_1 = aes.decrypt(encrypted_half_1)
decrypted_half_2 = aes.decrypt(encrypted_half_2)
# get the original private key from the encrypted halves + the derived half
decrypted_private_key = '%064x' % (long(binascii.hexlify(decrypted_half_1 + decrypted_half_2), 16) ^ long(binascii.hexlify(derived_half_1), 16))
# get the address corresponding to the private key
k = BitcoinKeypair(decrypted_private_key)
address = k.address()
# make sure the address matches the checksum in the original encrypted key
if address_checksum != sha256(sha256(address).digest()).digest()[0:4]:
raise ValueError('Invalid private key and password combo.')
# return the decrypted private key
return k.private_key()

View File

@@ -0,0 +1,61 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#-----------------------
# Copyright 2014 Halfmoon Labs, Inc.
# All Rights Reserved
#-----------------------
#-----------------------------------
def convert_v1_to_v2(profile):
new_profile = {}
if 'v' in profile:
new_profile['v'] = '0.2'
if 'website' in profile:
new_profile['website'] = profile['website']
if 'bio' in profile:
new_profile['bio'] = profile['bio']
if 'github' in profile:
new_profile['github'] = profile['github']
if 'instagram' in profile:
new_profile['instagram'] = {"username":profile['instagram']}
if 'twitter' in profile:
new_profile['twitter'] = {"username":profile['twitter']}
if 'cover' in profile:
new_profile['cover'] = {"url":profile['cover']}
if 'avatar' in profile:
new_profile['avatar'] = {"url":profile['avatar']}
if 'bitcoin' in profile:
new_profile['bitcoin'] = {"address":profile['bitcoin']}
if 'linkedin' in profile:
new_profile['linkedin'] = {"url":profile['linkedin']}
if 'name' in profile:
new_profile['name'] = {"formatted":profile['name']}
if 'facebook' in profile:
new_profile['facebook'] = {"username":profile['facebook']}
if 'location' in profile:
new_profile['location'] = {"formatted":profile['location']}
if 'angellist' in profile:
new_profile['angellist'] = {"username":profile['angellist']}
if 'bitmessage' in profile:
new_profile['bitmessage'] = {"address":profile['bitmessage']}
if 'pgp' in profile:
new_profile['pgp'] = profile['pgp']
return new_profile