Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- #-*- coding: utf-8 -*-
- pywversion="2.1.7"
- never_update=False
- #
- # jackjack's pywallet.py
- # https://github.com/jackjack-jj/pywallet
- # forked from Joric's pywallet.py
- #
- beta_version = ('a' in pywversion.split('-')[0]) or ('b' in pywversion.split('-')[0])
- missing_dep = []
- try:
- from bsddb.db import *
- except:
- missing_dep.append('bsddb')
- import os, sys, time, re
- pyw_filename = os.path.basename(__file__)
- pyw_path = os.path.dirname(os.path.realpath(__file__))
- try:
- for i in os.listdir('/usr/lib/python2.5/site-packages'):
- if 'Twisted' in i:
- sys.path.append('/usr/lib/python2.5/site-packages/'+i)
- except:
- ''
- try:
- import json
- except:
- try:
- import simplejson as json
- except:
- print("Json or simplejson package is needed")
- import logging
- import struct
- import StringIO
- import traceback
- import socket
- import types
- import string
- import exceptions
- import hashlib
- import random
- import urllib
- import math
- try:
- from twisted.internet import reactor
- from twisted.web import server, resource
- from twisted.web.static import File
- from twisted.python import log
- except:
- missing_dep.append('twisted')
- from datetime import datetime
- from subprocess import *
- import os
- import os.path
- import platform
- max_version = 81000
- addrtype = 0
- json_db = {}
- private_keys = []
- private_hex_keys = []
- passphrase = ""
- global_merging_message = ["",""]
- balance_site = 'http://jackjack.alwaysdata.net/balance/index.php?address'
- aversions = {};
- for i in range(256):
- aversions[i] = "version %d" % i;
- aversions[0] = 'Bitcoin';
- aversions[48] = 'Litecoin';
- aversions[52] = 'Namecoin';
- aversions[111] = 'Testnet';
- wallet_dir = ""
- wallet_name = ""
- ko = 1e3
- kio = 1024
- Mo = 1e6
- Mio = 1024 ** 2
- Go = 1e9
- Gio = 1024 ** 3
- To = 1e12
- Tio = 1024 ** 4
- prekeys = ["308201130201010420".decode('hex'), "308201120201010420".decode('hex')]
- postkeys = ["a081a530".decode('hex'), "81a530".decode('hex')]
- def iais(a):
- if a>= 2:
- return 's'
- else:
- return ''
- def systype():
- if platform.system() == "Darwin":
- return 'Mac'
- elif platform.system() == "Windows":
- return 'Win'
- return 'Linux'
- def determine_db_dir():
- if wallet_dir in "":
- if platform.system() == "Darwin":
- return os.path.expanduser("~/Library/Application Support/Bitcoin/")
- elif platform.system() == "Windows":
- return os.path.join(os.environ['APPDATA'], "Bitcoin")
- return os.path.expanduser("~/.bitcoin")
- else:
- return wallet_dir
- def determine_db_name():
- if wallet_name in "":
- return "wallet.dat"
- else:
- return wallet_name
- ########################
- # begin of aes.py code #
- ########################
- # from the SlowAES project, http://code.google.com/p/slowaes (aes.py)
- def append_PKCS7_padding(s):
- """return s padded to a multiple of 16-bytes by PKCS7 padding"""
- numpads = 16 - (len(s)%16)
- return s + numpads*chr(numpads)
- def strip_PKCS7_padding(s):
- """return s stripped of PKCS7 padding"""
- if len(s)%16 or not s:
- raise ValueError("String of len %d can't be PCKS7-padded" % len(s))
- numpads = ord(s[-1])
- if numpads > 16:
- raise ValueError("String ending with %r can't be PCKS7-padded" % s[-1])
- return s[:-numpads]
- class AES(object):
- # valid key sizes
- keySize = dict(SIZE_128=16, SIZE_192=24, SIZE_256=32)
- # Rijndael S-box
- sbox = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67,
- 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59,
- 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7,
- 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1,
- 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05,
- 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83,
- 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29,
- 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
- 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa,
- 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c,
- 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc,
- 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
- 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19,
- 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee,
- 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49,
- 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
- 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4,
- 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6,
- 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70,
- 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9,
- 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e,
- 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1,
- 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0,
- 0x54, 0xbb, 0x16]
- # Rijndael Inverted S-box
- rsbox = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3,
- 0x9e, 0x81, 0xf3, 0xd7, 0xfb , 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f,
- 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb , 0x54,
- 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b,
- 0x42, 0xfa, 0xc3, 0x4e , 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24,
- 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 , 0x72, 0xf8,
- 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d,
- 0x65, 0xb6, 0x92 , 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
- 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 , 0x90, 0xd8, 0xab,
- 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3,
- 0x45, 0x06 , 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1,
- 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b , 0x3a, 0x91, 0x11, 0x41,
- 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6,
- 0x73 , 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9,
- 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e , 0x47, 0xf1, 0x1a, 0x71, 0x1d,
- 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b ,
- 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0,
- 0xfe, 0x78, 0xcd, 0x5a, 0xf4 , 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07,
- 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f , 0x60,
- 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f,
- 0x93, 0xc9, 0x9c, 0xef , 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5,
- 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 , 0x17, 0x2b,
- 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55,
- 0x21, 0x0c, 0x7d]
- def getSBoxValue(self,num):
- """Retrieves a given S-Box Value"""
- return self.sbox[num]
- def getSBoxInvert(self,num):
- """Retrieves a given Inverted S-Box Value"""
- return self.rsbox[num]
- def rotate(self, word):
- """ Rijndael's key schedule rotate operation.
- Rotate a word eight bits to the left: eg, rotate(1d2c3a4f) == 2c3a4f1d
- Word is an char list of size 4 (32 bits overall).
- """
- return word[1:] + word[:1]
- # Rijndael Rcon
- Rcon = [0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
- 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97,
- 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72,
- 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66,
- 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
- 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d,
- 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
- 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61,
- 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
- 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40,
- 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc,
- 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5,
- 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a,
- 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d,
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c,
- 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
- 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4,
- 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
- 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08,
- 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
- 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d,
- 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2,
- 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74,
- 0xe8, 0xcb ]
- def getRconValue(self, num):
- """Retrieves a given Rcon Value"""
- return self.Rcon[num]
- def core(self, word, iteration):
- """Key schedule core."""
- # rotate the 32-bit word 8 bits to the left
- word = self.rotate(word)
- # apply S-Box substitution on all 4 parts of the 32-bit word
- for i in range(4):
- word[i] = self.getSBoxValue(word[i])
- # XOR the output of the rcon operation with i to the first part
- # (leftmost) only
- word[0] = word[0] ^ self.getRconValue(iteration)
- return word
- def expandKey(self, key, size, expandedKeySize):
- """Rijndael's key expansion.
- Expands an 128,192,256 key into an 176,208,240 bytes key
- expandedKey is a char list of large enough size,
- key is the non-expanded key.
- """
- # current expanded keySize, in bytes
- currentSize = 0
- rconIteration = 1
- expandedKey = [0] * expandedKeySize
- # set the 16, 24, 32 bytes of the expanded key to the input key
- for j in range(size):
- expandedKey[j] = key[j]
- currentSize += size
- while currentSize < expandedKeySize:
- # assign the previous 4 bytes to the temporary value t
- t = expandedKey[currentSize-4:currentSize]
- # every 16,24,32 bytes we apply the core schedule to t
- # and increment rconIteration afterwards
- if currentSize % size == 0:
- t = self.core(t, rconIteration)
- rconIteration += 1
- # For 256-bit keys, we add an extra sbox to the calculation
- if size == self.keySize["SIZE_256"] and ((currentSize % size) == 16):
- for l in range(4): t[l] = self.getSBoxValue(t[l])
- # We XOR t with the four-byte block 16,24,32 bytes before the new
- # expanded key. This becomes the next four bytes in the expanded
- # key.
- for m in range(4):
- expandedKey[currentSize] = expandedKey[currentSize - size] ^ \
- t[m]
- currentSize += 1
- return expandedKey
- def addRoundKey(self, state, roundKey):
- """Adds (XORs) the round key to the state."""
- for i in range(16):
- state[i] ^= roundKey[i]
- return state
- def createRoundKey(self, expandedKey, roundKeyPointer):
- """Create a round key.
- Creates a round key from the given expanded key and the
- position within the expanded key.
- """
- roundKey = [0] * 16
- for i in range(4):
- for j in range(4):
- roundKey[j*4+i] = expandedKey[roundKeyPointer + i*4 + j]
- return roundKey
- def galois_multiplication(self, a, b):
- """Galois multiplication of 8 bit characters a and b."""
- p = 0
- for counter in range(8):
- if b & 1: p ^= a
- hi_bit_set = a & 0x80
- a <<= 1
- # keep a 8 bit
- a &= 0xFF
- if hi_bit_set:
- a ^= 0x1b
- b >>= 1
- return p
- #
- # substitute all the values from the state with the value in the SBox
- # using the state value as index for the SBox
- #
- def subBytes(self, state, isInv):
- if isInv: getter = self.getSBoxInvert
- else: getter = self.getSBoxValue
- for i in range(16): state[i] = getter(state[i])
- return state
- # iterate over the 4 rows and call shiftRow() with that row
- def shiftRows(self, state, isInv):
- for i in range(4):
- state = self.shiftRow(state, i*4, i, isInv)
- return state
- # each iteration shifts the row to the left by 1
- def shiftRow(self, state, statePointer, nbr, isInv):
- for i in range(nbr):
- if isInv:
- state[statePointer:statePointer+4] = \
- state[statePointer+3:statePointer+4] + \
- state[statePointer:statePointer+3]
- else:
- state[statePointer:statePointer+4] = \
- state[statePointer+1:statePointer+4] + \
- state[statePointer:statePointer+1]
- return state
- # galois multiplication of the 4x4 matrix
- def mixColumns(self, state, isInv):
- # iterate over the 4 columns
- for i in range(4):
- # construct one column by slicing over the 4 rows
- column = state[i:i+16:4]
- # apply the mixColumn on one column
- column = self.mixColumn(column, isInv)
- # put the values back into the state
- state[i:i+16:4] = column
- return state
- # galois multiplication of 1 column of the 4x4 matrix
- def mixColumn(self, column, isInv):
- if isInv: mult = [14, 9, 13, 11]
- else: mult = [2, 1, 1, 3]
- cpy = list(column)
- g = self.galois_multiplication
- column[0] = g(cpy[0], mult[0]) ^ g(cpy[3], mult[1]) ^ \
- g(cpy[2], mult[2]) ^ g(cpy[1], mult[3])
- column[1] = g(cpy[1], mult[0]) ^ g(cpy[0], mult[1]) ^ \
- g(cpy[3], mult[2]) ^ g(cpy[2], mult[3])
- column[2] = g(cpy[2], mult[0]) ^ g(cpy[1], mult[1]) ^ \
- g(cpy[0], mult[2]) ^ g(cpy[3], mult[3])
- column[3] = g(cpy[3], mult[0]) ^ g(cpy[2], mult[1]) ^ \
- g(cpy[1], mult[2]) ^ g(cpy[0], mult[3])
- return column
- # applies the 4 operations of the forward round in sequence
- def aes_round(self, state, roundKey):
- state = self.subBytes(state, False)
- state = self.shiftRows(state, False)
- state = self.mixColumns(state, False)
- state = self.addRoundKey(state, roundKey)
- return state
- # applies the 4 operations of the inverse round in sequence
- def aes_invRound(self, state, roundKey):
- state = self.shiftRows(state, True)
- state = self.subBytes(state, True)
- state = self.addRoundKey(state, roundKey)
- state = self.mixColumns(state, True)
- return state
- # Perform the initial operations, the standard round, and the final
- # operations of the forward aes, creating a round key for each round
- def aes_main(self, state, expandedKey, nbrRounds):
- state = self.addRoundKey(state, self.createRoundKey(expandedKey, 0))
- i = 1
- while i < nbrRounds:
- state = self.aes_round(state,
- self.createRoundKey(expandedKey, 16*i))
- i += 1
- state = self.subBytes(state, False)
- state = self.shiftRows(state, False)
- state = self.addRoundKey(state,
- self.createRoundKey(expandedKey, 16*nbrRounds))
- return state
- # Perform the initial operations, the standard round, and the final
- # operations of the inverse aes, creating a round key for each round
- def aes_invMain(self, state, expandedKey, nbrRounds):
- state = self.addRoundKey(state,
- self.createRoundKey(expandedKey, 16*nbrRounds))
- i = nbrRounds - 1
- while i > 0:
- state = self.aes_invRound(state,
- self.createRoundKey(expandedKey, 16*i))
- i -= 1
- state = self.shiftRows(state, True)
- state = self.subBytes(state, True)
- state = self.addRoundKey(state, self.createRoundKey(expandedKey, 0))
- return state
- # encrypts a 128 bit input block against the given key of size specified
- def encrypt(self, iput, key, size):
- output = [0] * 16
- # the number of rounds
- nbrRounds = 0
- # the 128 bit block to encode
- block = [0] * 16
- # set the number of rounds
- if size == self.keySize["SIZE_128"]: nbrRounds = 10
- elif size == self.keySize["SIZE_192"]: nbrRounds = 12
- elif size == self.keySize["SIZE_256"]: nbrRounds = 14
- else: return None
- # the expanded keySize
- expandedKeySize = 16*(nbrRounds+1)
- # Set the block values, for the block:
- # a0,0 a0,1 a0,2 a0,3
- # a1,0 a1,1 a1,2 a1,3
- # a2,0 a2,1 a2,2 a2,3
- # a3,0 a3,1 a3,2 a3,3
- # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3
- #
- # iterate over the columns
- for i in range(4):
- # iterate over the rows
- for j in range(4):
- block[(i+(j*4))] = iput[(i*4)+j]
- # expand the key into an 176, 208, 240 bytes key
- # the expanded key
- expandedKey = self.expandKey(key, size, expandedKeySize)
- # encrypt the block using the expandedKey
- block = self.aes_main(block, expandedKey, nbrRounds)
- # unmap the block again into the output
- for k in range(4):
- # iterate over the rows
- for l in range(4):
- output[(k*4)+l] = block[(k+(l*4))]
- return output
- # decrypts a 128 bit input block against the given key of size specified
- def decrypt(self, iput, key, size):
- output = [0] * 16
- # the number of rounds
- nbrRounds = 0
- # the 128 bit block to decode
- block = [0] * 16
- # set the number of rounds
- if size == self.keySize["SIZE_128"]: nbrRounds = 10
- elif size == self.keySize["SIZE_192"]: nbrRounds = 12
- elif size == self.keySize["SIZE_256"]: nbrRounds = 14
- else: return None
- # the expanded keySize
- expandedKeySize = 16*(nbrRounds+1)
- # Set the block values, for the block:
- # a0,0 a0,1 a0,2 a0,3
- # a1,0 a1,1 a1,2 a1,3
- # a2,0 a2,1 a2,2 a2,3
- # a3,0 a3,1 a3,2 a3,3
- # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3
- # iterate over the columns
- for i in range(4):
- # iterate over the rows
- for j in range(4):
- block[(i+(j*4))] = iput[(i*4)+j]
- # expand the key into an 176, 208, 240 bytes key
- expandedKey = self.expandKey(key, size, expandedKeySize)
- # decrypt the block using the expandedKey
- block = self.aes_invMain(block, expandedKey, nbrRounds)
- # unmap the block again into the output
- for k in range(4):
- # iterate over the rows
- for l in range(4):
- output[(k*4)+l] = block[(k+(l*4))]
- return output
- class AESModeOfOperation(object):
- aes = AES()
- # structure of supported modes of operation
- modeOfOperation = dict(OFB=0, CFB=1, CBC=2)
- # converts a 16 character string into a number array
- def convertString(self, string, start, end, mode):
- if end - start > 16: end = start + 16
- if mode == self.modeOfOperation["CBC"]: ar = [0] * 16
- else: ar = []
- i = start
- j = 0
- while len(ar) < end - start:
- ar.append(0)
- while i < end:
- ar[j] = ord(string[i])
- j += 1
- i += 1
- return ar
- # Mode of Operation Encryption
- # stringIn - Input String
- # mode - mode of type modeOfOperation
- # hexKey - a hex key of the bit length size
- # size - the bit length of the key
- # hexIV - the 128 bit hex Initilization Vector
- def encrypt(self, stringIn, mode, key, size, IV):
- if len(key) % size:
- return None
- if len(IV) % 16:
- return None
- # the AES input/output
- plaintext = []
- iput = [0] * 16
- output = []
- ciphertext = [0] * 16
- # the output cipher string
- cipherOut = []
- # char firstRound
- firstRound = True
- if stringIn != None:
- for j in range(int(math.ceil(float(len(stringIn))/16))):
- start = j*16
- end = j*16+16
- if end > len(stringIn):
- end = len(stringIn)
- plaintext = self.convertString(stringIn, start, end, mode)
- # print 'PT@%s:%s' % (j, plaintext)
- if mode == self.modeOfOperation["CFB"]:
- if firstRound:
- output = self.aes.encrypt(IV, key, size)
- firstRound = False
- else:
- output = self.aes.encrypt(iput, key, size)
- for i in range(16):
- if len(plaintext)-1 < i:
- ciphertext[i] = 0 ^ output[i]
- elif len(output)-1 < i:
- ciphertext[i] = plaintext[i] ^ 0
- elif len(plaintext)-1 < i and len(output) < i:
- ciphertext[i] = 0 ^ 0
- else:
- ciphertext[i] = plaintext[i] ^ output[i]
- for k in range(end-start):
- cipherOut.append(ciphertext[k])
- iput = ciphertext
- elif mode == self.modeOfOperation["OFB"]:
- if firstRound:
- output = self.aes.encrypt(IV, key, size)
- firstRound = False
- else:
- output = self.aes.encrypt(iput, key, size)
- for i in range(16):
- if len(plaintext)-1 < i:
- ciphertext[i] = 0 ^ output[i]
- elif len(output)-1 < i:
- ciphertext[i] = plaintext[i] ^ 0
- elif len(plaintext)-1 < i and len(output) < i:
- ciphertext[i] = 0 ^ 0
- else:
- ciphertext[i] = plaintext[i] ^ output[i]
- for k in range(end-start):
- cipherOut.append(ciphertext[k])
- iput = output
- elif mode == self.modeOfOperation["CBC"]:
- for i in range(16):
- if firstRound:
- iput[i] = plaintext[i] ^ IV[i]
- else:
- iput[i] = plaintext[i] ^ ciphertext[i]
- # print 'IP@%s:%s' % (j, iput)
- firstRound = False
- ciphertext = self.aes.encrypt(iput, key, size)
- # always 16 bytes because of the padding for CBC
- for k in range(16):
- cipherOut.append(ciphertext[k])
- return mode, len(stringIn), cipherOut
- # Mode of Operation Decryption
- # cipherIn - Encrypted String
- # originalsize - The unencrypted string length - required for CBC
- # mode - mode of type modeOfOperation
- # key - a number array of the bit length size
- # size - the bit length of the key
- # IV - the 128 bit number array Initilization Vector
- def decrypt(self, cipherIn, originalsize, mode, key, size, IV):
- # cipherIn = unescCtrlChars(cipherIn)
- if len(key) % size:
- return None
- if len(IV) % 16:
- return None
- # the AES input/output
- ciphertext = []
- iput = []
- output = []
- plaintext = [0] * 16
- # the output plain text string
- stringOut = ''
- # char firstRound
- firstRound = True
- if cipherIn != None:
- for j in range(int(math.ceil(float(len(cipherIn))/16))):
- start = j*16
- end = j*16+16
- if j*16+16 > len(cipherIn):
- end = len(cipherIn)
- ciphertext = cipherIn[start:end]
- if mode == self.modeOfOperation["CFB"]:
- if firstRound:
- output = self.aes.encrypt(IV, key, size)
- firstRound = False
- else:
- output = self.aes.encrypt(iput, key, size)
- for i in range(16):
- if len(output)-1 < i:
- plaintext[i] = 0 ^ ciphertext[i]
- elif len(ciphertext)-1 < i:
- plaintext[i] = output[i] ^ 0
- elif len(output)-1 < i and len(ciphertext) < i:
- plaintext[i] = 0 ^ 0
- else:
- plaintext[i] = output[i] ^ ciphertext[i]
- for k in range(end-start):
- stringOut += chr(plaintext[k])
- iput = ciphertext
- elif mode == self.modeOfOperation["OFB"]:
- if firstRound:
- output = self.aes.encrypt(IV, key, size)
- firstRound = False
- else:
- output = self.aes.encrypt(iput, key, size)
- for i in range(16):
- if len(output)-1 < i:
- plaintext[i] = 0 ^ ciphertext[i]
- elif len(ciphertext)-1 < i:
- plaintext[i] = output[i] ^ 0
- elif len(output)-1 < i and len(ciphertext) < i:
- plaintext[i] = 0 ^ 0
- else:
- plaintext[i] = output[i] ^ ciphertext[i]
- for k in range(end-start):
- stringOut += chr(plaintext[k])
- iput = output
- elif mode == self.modeOfOperation["CBC"]:
- output = self.aes.decrypt(ciphertext, key, size)
- for i in range(16):
- if firstRound:
- plaintext[i] = IV[i] ^ output[i]
- else:
- plaintext[i] = iput[i] ^ output[i]
- firstRound = False
- if originalsize is not None and originalsize < end:
- for k in range(originalsize-start):
- stringOut += chr(plaintext[k])
- else:
- for k in range(end-start):
- stringOut += chr(plaintext[k])
- iput = ciphertext
- return stringOut
- ######################
- # end of aes.py code #
- ######################
- ###################################
- # pywallet crypter implementation #
- ###################################
- crypter = None
- try:
- from Crypto.Cipher import AES
- crypter = 'pycrypto'
- except:
- pass
- class Crypter_pycrypto( object ):
- def SetKeyFromPassphrase(self, vKeyData, vSalt, nDerivIterations, nDerivationMethod):
- if nDerivationMethod != 0:
- return 0
- data = vKeyData + vSalt
- for i in xrange(nDerivIterations):
- data = hashlib.sha512(data).digest()
- self.SetKey(data[0:32])
- self.SetIV(data[32:32+16])
- return len(data)
- def SetKey(self, key):
- self.chKey = key
- def SetIV(self, iv):
- self.chIV = iv[0:16]
- def Encrypt(self, data):
- return AES.new(self.chKey,AES.MODE_CBC,self.chIV).encrypt(data)[0:32]
- def Decrypt(self, data):
- return AES.new(self.chKey,AES.MODE_CBC,self.chIV).decrypt(data)[0:32]
- try:
- if not crypter:
- import ctypes
- import ctypes.util
- ssl = ctypes.cdll.LoadLibrary (ctypes.util.find_library ('ssl') or 'libeay32')
- crypter = 'ssl'
- except:
- pass
- class Crypter_ssl(object):
- def __init__(self):
- self.chKey = ctypes.create_string_buffer (32)
- self.chIV = ctypes.create_string_buffer (16)
- def SetKeyFromPassphrase(self, vKeyData, vSalt, nDerivIterations, nDerivationMethod):
- if nDerivationMethod != 0:
- return 0
- strKeyData = ctypes.create_string_buffer (vKeyData)
- chSalt = ctypes.create_string_buffer (vSalt)
- return ssl.EVP_BytesToKey(ssl.EVP_aes_256_cbc(), ssl.EVP_sha512(), chSalt, strKeyData,
- len(vKeyData), nDerivIterations, ctypes.byref(self.chKey), ctypes.byref(self.chIV))
- def SetKey(self, key):
- self.chKey = ctypes.create_string_buffer(key)
- def SetIV(self, iv):
- self.chIV = ctypes.create_string_buffer(iv)
- def Encrypt(self, data):
- buf = ctypes.create_string_buffer(len(data) + 16)
- written = ctypes.c_int(0)
- final = ctypes.c_int(0)
- ctx = ssl.EVP_CIPHER_CTX_new()
- ssl.EVP_CIPHER_CTX_init(ctx)
- ssl.EVP_EncryptInit_ex(ctx, ssl.EVP_aes_256_cbc(), None, self.chKey, self.chIV)
- ssl.EVP_EncryptUpdate(ctx, buf, ctypes.byref(written), data, len(data))
- output = buf.raw[:written.value]
- ssl.EVP_EncryptFinal_ex(ctx, buf, ctypes.byref(final))
- output += buf.raw[:final.value]
- return output
- def Decrypt(self, data):
- buf = ctypes.create_string_buffer(len(data) + 16)
- written = ctypes.c_int(0)
- final = ctypes.c_int(0)
- ctx = ssl.EVP_CIPHER_CTX_new()
- ssl.EVP_CIPHER_CTX_init(ctx)
- ssl.EVP_DecryptInit_ex(ctx, ssl.EVP_aes_256_cbc(), None, self.chKey, self.chIV)
- ssl.EVP_DecryptUpdate(ctx, buf, ctypes.byref(written), data, len(data))
- output = buf.raw[:written.value]
- ssl.EVP_DecryptFinal_ex(ctx, buf, ctypes.byref(final))
- output += buf.raw[:final.value]
- return output
- class Crypter_pure(object):
- def __init__(self):
- self.m = AESModeOfOperation()
- self.cbc = self.m.modeOfOperation["CBC"]
- self.sz = self.m.aes.keySize["SIZE_256"]
- def SetKeyFromPassphrase(self, vKeyData, vSalt, nDerivIterations, nDerivationMethod):
- if nDerivationMethod != 0:
- return 0
- data = vKeyData + vSalt
- for i in xrange(nDerivIterations):
- data = hashlib.sha512(data).digest()
- self.SetKey(data[0:32])
- self.SetIV(data[32:32+16])
- return len(data)
- def SetKey(self, key):
- self.chKey = [ord(i) for i in key]
- def SetIV(self, iv):
- self.chIV = [ord(i) for i in iv]
- def Encrypt(self, data):
- mode, size, cypher = self.m.encrypt(data, self.cbc, self.chKey, self.sz, self.chIV)
- return ''.join(map(chr, cypher))
- def Decrypt(self, data):
- chData = [ord(i) for i in data]
- return self.m.decrypt(chData, self.sz, self.cbc, self.chKey, self.sz, self.chIV)
- if crypter == 'pycrypto':
- crypter = Crypter_pycrypto()
- # print "Crypter: pycrypto"
- elif crypter == 'ssl':
- crypter = Crypter_ssl()
- # print "Crypter: ssl"
- else:
- crypter = Crypter_pure()
- # print "Crypter: pure"
- logging.warning("pycrypto or libssl not found, decryption may be slow")
- ##########################################
- # end of pywallet crypter implementation #
- ##########################################
- # secp256k1
- try:
- _p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL
- except:
- print "Python 3 is not supported, you need Python 2.7.x"
- exit(1)
- _r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L
- _b = 0x0000000000000000000000000000000000000000000000000000000000000007L
- _a = 0x0000000000000000000000000000000000000000000000000000000000000000L
- _Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L
- _Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8L
- try:
- import ecdsa
- from ecdsa import der
- curve_secp256k1 = ecdsa.ellipticcurve.CurveFp (_p, _a, _b)
- generator_secp256k1 = g = ecdsa.ellipticcurve.Point (curve_secp256k1, _Gx, _Gy, _r)
- randrange = random.SystemRandom().randrange
- secp256k1 = ecdsa.curves.Curve ( "secp256k1", curve_secp256k1, generator_secp256k1, (1, 3, 132, 0, 10) )
- ecdsa.curves.curves.append (secp256k1)
- except:
- missing_dep.append('ecdsa')
- # python-ecdsa code (EC_KEY implementation)
- class CurveFp( object ):
- def __init__( self, p, a, b ):
- self.__p = p
- self.__a = a
- self.__b = b
- def p( self ):
- return self.__p
- def a( self ):
- return self.__a
- def b( self ):
- return self.__b
- def contains_point( self, x, y ):
- return ( y * y - ( x * x * x + self.__a * x + self.__b ) ) % self.__p == 0
- class Point( object ):
- def __init__( self, curve, x, y, order = None ):
- self.__curve = curve
- self.__x = x
- self.__y = y
- self.__order = order
- if self.__curve: assert self.__curve.contains_point( x, y )
- if order: assert self * order == INFINITY
- def __add__( self, other ):
- if other == INFINITY: return self
- if self == INFINITY: return other
- assert self.__curve == other.__curve
- if self.__x == other.__x:
- if ( self.__y + other.__y ) % self.__curve.p() == 0:
- return INFINITY
- else:
- return self.double()
- p = self.__curve.p()
- l = ( ( other.__y - self.__y ) * \
- inverse_mod( other.__x - self.__x, p ) ) % p
- x3 = ( l * l - self.__x - other.__x ) % p
- y3 = ( l * ( self.__x - x3 ) - self.__y ) % p
- return Point( self.__curve, x3, y3 )
- def __mul__( self, other ):
- def leftmost_bit( x ):
- assert x > 0
- result = 1L
- while result <= x: result = 2 * result
- return result / 2
- e = other
- if self.__order: e = e % self.__order
- if e == 0: return INFINITY
- if self == INFINITY: return INFINITY
- assert e > 0
- e3 = 3 * e
- negative_self = Point( self.__curve, self.__x, -self.__y, self.__order )
- i = leftmost_bit( e3 ) / 2
- result = self
- while i > 1:
- result = result.double()
- if ( e3 & i ) != 0 and ( e & i ) == 0: result = result + self
- if ( e3 & i ) == 0 and ( e & i ) != 0: result = result + negative_self
- i = i / 2
- return result
- def __rmul__( self, other ):
- return self * other
- def __str__( self ):
- if self == INFINITY: return "infinity"
- return "(%d,%d)" % ( self.__x, self.__y )
- def double( self ):
- if self == INFINITY:
- return INFINITY
- p = self.__curve.p()
- a = self.__curve.a()
- l = ( ( 3 * self.__x * self.__x + a ) * \
- inverse_mod( 2 * self.__y, p ) ) % p
- x3 = ( l * l - 2 * self.__x ) % p
- y3 = ( l * ( self.__x - x3 ) - self.__y ) % p
- return Point( self.__curve, x3, y3 )
- def x( self ):
- return self.__x
- def y( self ):
- return self.__y
- def curve( self ):
- return self.__curve
- def order( self ):
- return self.__order
- INFINITY = Point( None, None, None )
- def inverse_mod( a, m ):
- if a < 0 or m <= a: a = a % m
- c, d = a, m
- uc, vc, ud, vd = 1, 0, 0, 1
- while c != 0:
- q, c, d = divmod( d, c ) + ( c, )
- uc, vc, ud, vd = ud - q*uc, vd - q*vc, uc, vc
- assert d == 1
- if ud > 0: return ud
- else: return ud + m
- class Signature( object ):
- def __init__( self, r, s ):
- self.r = r
- self.s = s
- class Public_key( object ):
- def __init__( self, generator, point, c=None ):
- self.curve = generator.curve()
- self.generator = generator
- self.point = point
- self.compressed = c
- n = generator.order()
- if not n:
- raise RuntimeError, "Generator point must have order."
- if not n * point == INFINITY:
- raise RuntimeError, "Generator point order is bad."
- if point.x() < 0 or n <= point.x() or point.y() < 0 or n <= point.y():
- raise RuntimeError, "Generator point has x or y out of range."
- def verifies( self, hash, signature ):
- G = self.generator
- n = G.order()
- r = signature.r
- s = signature.s
- if r < 1 or r > n-1: return False
- if s < 1 or s > n-1: return False
- c = inverse_mod( s, n )
- u1 = ( hash * c ) % n
- u2 = ( r * c ) % n
- xy = u1 * G + u2 * self.point
- v = xy.x() % n
- return v == r
- def ser(self):
- if self.compressed:
- pk=('%02x'%(2+(self.point.y()&1))) + '%064x' % self.point.x()
- else:
- pk='04%064x%064x' % (self.point.x(), self.point.y())
- return pk.decode('hex')
- def get_addr(self, v=0):
- return public_key_to_bc_address(self.ser(), v)
- class Private_key( object ):
- def __init__( self, public_key, secret_multiplier ):
- self.public_key = public_key
- self.secret_multiplier = secret_multiplier
- def der( self ):
- hex_der_key = '06052b8104000a30740201010420' + \
- '%064x' % self.secret_multiplier + \
- 'a00706052b8104000aa14403420004' + \
- '%064x' % self.public_key.point.x() + \
- '%064x' % self.public_key.point.y()
- return hex_der_key.decode('hex')
- def sign( self, hash, random_k ):
- G = self.public_key.generator
- n = G.order()
- k = random_k % n
- p1 = k * G
- r = p1.x()
- if r == 0: raise RuntimeError, "amazingly unlucky random number r"
- s = ( inverse_mod( k, n ) * \
- ( hash + ( self.secret_multiplier * r ) % n ) ) % n
- if s == 0: raise RuntimeError, "amazingly unlucky random number s"
- return Signature( r, s )
- class EC_KEY(object):
- def __init__( self, secret ):
- curve = CurveFp( _p, _a, _b )
- generator = Point( curve, _Gx, _Gy, _r )
- self.pubkey = Public_key( generator, generator * secret )
- self.privkey = Private_key( self.pubkey, secret )
- self.secret = secret
- # end of python-ecdsa code
- # pywallet openssl private key implementation
- def i2d_ECPrivateKey(pkey, compressed=False):#, crypted=True):
- part3='a081a53081a2020101302c06072a8648ce3d0101022100' # for uncompressed keys
- if compressed:
- if True:#not crypted: ## Bitcoin accepts both part3's for crypted wallets...
- part3='a08185308182020101302c06072a8648ce3d0101022100' # for compressed keys
- key = '3081d30201010420' + \
- '%064x' % pkey.secret + \
- part3 + \
- '%064x' % _p + \
- '3006040100040107042102' + \
- '%064x' % _Gx + \
- '022100' + \
- '%064x' % _r + \
- '020101a124032200'
- else:
- key = '308201130201010420' + \
- '%064x' % pkey.secret + \
- part3 + \
- '%064x' % _p + \
- '3006040100040107044104' + \
- '%064x' % _Gx + \
- '%064x' % _Gy + \
- '022100' + \
- '%064x' % _r + \
- '020101a144034200'
- return key.decode('hex') + i2o_ECPublicKey(pkey, compressed)
- def i2o_ECPublicKey(pkey, compressed=False):
- # public keys are 65 bytes long (520 bits)
- # 0x04 + 32-byte X-coordinate + 32-byte Y-coordinate
- # 0x00 = point at infinity, 0x02 and 0x03 = compressed, 0x04 = uncompressed
- # compressed keys: <sign> <x> where <sign> is 0x02 if y is even and 0x03 if y is odd
- if compressed:
- if pkey.pubkey.point.y() & 1:
- key = '03' + '%064x' % pkey.pubkey.point.x()
- else:
- key = '02' + '%064x' % pkey.pubkey.point.x()
- else:
- key = '04' + \
- '%064x' % pkey.pubkey.point.x() + \
- '%064x' % pkey.pubkey.point.y()
- return key.decode('hex')
- # bitcointools hashes and base58 implementation
- def hash_160(public_key):
- md = hashlib.new('ripemd160')
- md.update(hashlib.sha256(public_key).digest())
- return md.digest()
- def public_key_to_bc_address(public_key, v=None):
- if v==None:
- v=addrtype
- h160 = hash_160(public_key)
- return hash_160_to_bc_address(h160, v)
- def hash_160_to_bc_address(h160, v=None):
- if v==None:
- v=addrtype
- vh160 = chr(v) + h160
- h = Hash(vh160)
- addr = vh160 + h[0:4]
- return b58encode(addr)
- def bc_address_to_hash_160(addr):
- bytes = b58decode(addr, 25)
- return bytes[1:21]
- __b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
- __b58base = len(__b58chars)
- def b58encode(v):
- """ encode v, which is a string of bytes, to base58.
- """
- long_value = 0L
- for (i, c) in enumerate(v[::-1]):
- long_value += (256**i) * ord(c)
- result = ''
- while long_value >= __b58base:
- div, mod = divmod(long_value, __b58base)
- result = __b58chars[mod] + result
- long_value = div
- result = __b58chars[long_value] + result
- # Bitcoin does a little leading-zero-compression:
- # leading 0-bytes in the input become leading-1s
- nPad = 0
- for c in v:
- if c == '\0': nPad += 1
- else: break
- return (__b58chars[0]*nPad) + result
- def b58decode(v, length):
- """ decode v into a string of len bytes
- """
- long_value = 0L
- for (i, c) in enumerate(v[::-1]):
- long_value += __b58chars.find(c) * (__b58base**i)
- result = ''
- while long_value >= 256:
- div, mod = divmod(long_value, 256)
- result = chr(mod) + result
- long_value = div
- result = chr(long_value) + result
- nPad = 0
- for c in v:
- if c == __b58chars[0]: nPad += 1
- else: break
- result = chr(0)*nPad + result
- if length is not None and len(result) != length:
- return None
- return result
- # end of bitcointools base58 implementation
- # address handling code
- def long_hex(bytes):
- return bytes.encode('hex_codec')
- def Hash(data):
- return hashlib.sha256(hashlib.sha256(data).digest()).digest()
- def EncodeBase58Check(secret):
- hash = Hash(secret)
- return b58encode(secret + hash[0:4])
- def DecodeBase58Check(sec):
- vchRet = b58decode(sec, None)
- secret = vchRet[0:-4]
- csum = vchRet[-4:]
- hash = Hash(secret)
- cs32 = hash[0:4]
- if cs32 != csum:
- return None
- else:
- return secret
- def str_to_long(b):
- res = 0
- pos = 1
- for a in reversed(b):
- res += ord(a) * pos
- pos *= 256
- return res
- def PrivKeyToSecret(privkey):
- if len(privkey) == 279:
- return privkey[9:9+32]
- else:
- return privkey[8:8+32]
- def SecretToASecret(secret, compressed=False):
- prefix = chr((addrtype+128)&255)
- if addrtype==48: #assuming Litecoin
- prefix = chr(128)
- vchIn = prefix + secret
- if compressed: vchIn += '\01'
- return EncodeBase58Check(vchIn)
- def ASecretToSecret(sec):
- vch = DecodeBase58Check(sec)
- if not vch:
- return False
- if vch[0] != chr((addrtype+128)&255):
- print 'Warning: adress prefix seems bad (%d vs %d)'%(ord(vch[0]), (addrtype+128)&255)
- return vch[1:]
- def regenerate_key(sec):
- b = ASecretToSecret(sec)
- if not b:
- return False
- b = b[0:32]
- secret = int('0x' + b.encode('hex'), 16)
- return EC_KEY(secret)
- def GetPubKey(pkey, compressed=False):
- return i2o_ECPublicKey(pkey, compressed)
- def GetPrivKey(pkey, compressed=False):
- return i2d_ECPrivateKey(pkey, compressed)
- def GetSecret(pkey):
- return ('%064x' % pkey.secret).decode('hex')
- def is_compressed(sec):
- b = ASecretToSecret(sec)
- return len(b) == 33
- # bitcointools wallet.dat handling code
- def create_env(db_dir):
- db_env = DBEnv(0)
- r = db_env.open(db_dir, (DB_CREATE|DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_THREAD|DB_RECOVER))
- return db_env
- def parse_CAddress(vds):
- d = {'ip':'0.0.0.0','port':0,'nTime': 0}
- try:
- d['nVersion'] = vds.read_int32()
- d['nTime'] = vds.read_uint32()
- d['nServices'] = vds.read_uint64()
- d['pchReserved'] = vds.read_bytes(12)
- d['ip'] = socket.inet_ntoa(vds.read_bytes(4))
- d['port'] = vds.read_uint16()
- except:
- pass
- return d
- def deserialize_CAddress(d):
- return d['ip']+":"+str(d['port'])
- def parse_BlockLocator(vds):
- d = { 'hashes' : [] }
- nHashes = vds.read_compact_size()
- for i in xrange(nHashes):
- d['hashes'].append(vds.read_bytes(32))
- return d
- def deserialize_BlockLocator(d):
- result = "Block Locator top: "+d['hashes'][0][::-1].encode('hex_codec')
- return result
- def parse_setting(setting, vds):
- if setting[0] == "f": # flag (boolean) settings
- return str(vds.read_boolean())
- elif setting[0:4] == "addr": # CAddress
- d = parse_CAddress(vds)
- return deserialize_CAddress(d)
- elif setting == "nTransactionFee":
- return vds.read_int64()
- elif setting == "nLimitProcessors":
- return vds.read_int32()
- return 'unknown setting'
- class SerializationError(Exception):
- """ Thrown when there's a problem deserializing or serializing """
- def search_patterns_on_disk(device, size, inc, patternlist): # inc must be higher than 1k
- try:
- otype=os.O_RDONLY|os.O_BINARY
- except:
- otype=os.O_RDONLY
- try:
- fd = os.open(device, otype)
- except Exception as e:
- print "Can't open %s, check the path or try as root"%device
- print " Error:", e.args
- exit(0)
- i = 0
- data=''
- tzero=time.time()
- sizetokeep=0
- BlocksToInspect=dict(map(lambda x:[x,[]], patternlist))
- syst=systype()
- lendataloaded=None
- writeProgressEvery=100*Mo
- while i < int(size) and (lendataloaded!=0 or lendataloaded==None):
- if int(i/writeProgressEvery)!=int((i+inc)/writeProgressEvery):
- print "%.2f Go read"%(i/1e9)
- try:
- datakept=data[-sizetokeep:]
- data = datakept+os.read(fd, inc)
- lendataloaded = len(data)-len(datakept) #should be inc
- for text in patternlist:
- if text in data:
- BlocksToInspect[text].append([i-len(datakept), data, len(datakept)])
- pass
- sizetokeep=20 # 20 because all the patterns have a len<20. Could be higher.
- i += lendataloaded
- except Exception as exc:
- if lendataloaded%512>0:
- raise Exception("SPOD error 1: %d, %d"%(lendataloaded, i-len(datakept)))
- os.lseek(fd, lendataloaded, os.SEEK_CUR)
- print str(exc)
- i += lendataloaded
- continue
- os.close(fd)
- AllOffsets=dict(map(lambda x:[x,[]], patternlist))
- for text,blocks in BlocksToInspect.items():
- for offset,data,ldk in blocks: #ldk = len(datakept)
- offsetslist=[offset+m.start() for m in re.finditer(text, data)]
- AllOffsets[text].extend(offsetslist)
- AllOffsets['PRFdevice']=device
- AllOffsets['PRFdt']=time.time()-tzero
- AllOffsets['PRFsize']=i
- return AllOffsets
- def multiextract(s, ll):
- r=[]
- cursor=0
- for length in ll:
- r.append(s[cursor:cursor+length])
- cursor+=length
- if s[cursor:]!='':
- r.append(s[cursor:])
- return r
- class RecovCkey(object):
- def __init__(self, epk, pk):
- self.encrypted_pk=epk
- self.public_key=pk
- self.mkey=None
- self.privkey=None
- class RecovMkey(object):
- def __init__(self, ekey, salt, nditer, ndmethod, nid):
- self.encrypted_key=ekey
- self.salt=salt
- self.iterations=nditer
- self.method=ndmethod
- self.id=nid
- def readpartfile(fd, offset, length): #make everything 512*n because of windows...
- rest=offset%512
- new_offset=offset-rest
- big_length=512*(int((length+rest-1)/512)+1)
- os.lseek(fd, new_offset, os.SEEK_SET)
- d=os.read(fd, big_length)
- return d[rest:rest+length]
- def recov_ckey(fd, offset):
- d=readpartfile(fd, offset-49, 122)
- me=multiextract(d, [1,48,4,4,1])
- checks=[]
- checks.append([0, '30'])
- checks.append([3, '636b6579'])
- if sum(map(lambda x:int(me[x[0]]!=x[1].decode('hex')), checks)): #number of false statements
- return None
- return me
- def recov_mkey(fd, offset):
- d=readpartfile(fd, offset-72, 84)
- me=multiextract(d, [4,48,1,8,4,4,1,2,8,4])
- checks=[]
- checks.append([0, '43000130'])
- checks.append([2, '08'])
- checks.append([6, '00'])
- checks.append([8, '090001046d6b6579'])
- if sum(map(lambda x:int(me[x[0]]!=x[1].decode('hex')), checks)): #number of false statements
- return None
- return me
- def recov_uckey(fd, offset):
- checks=[]
- d=readpartfile(fd, offset-217, 223)
- if d[-7]=='\x26':
- me=multiextract(d, [2,1,4,1,32,141,33,2,1,6])
- checks.append([0, '3081'])
- checks.append([2, '02010104'])
- elif d[-7]=='\x46':
- d=readpartfile(fd, offset-282, 286)
- me=multiextract(d, [2,1,4,1,32,173,65,1,2,5])
- checks.append([0, '8201'])
- checks.append([2, '02010104'])
- checks.append([-1, '460001036b'])
- else:
- return None
- if sum(map(lambda x:int(me[x[0]]!=x[1].decode('hex')), checks)): #number of false statements
- return None
- return me
- def starts_with(s, b):
- return len(s)>=len(b) and s[:len(b)]==b
- def recov(device, passes, size=102400, inc=10240, outputdir='.'):
- if inc%512>0:
- inc-=inc%512 #inc must be 512*n on Windows... Don't ask me why...
- nameToDBName={'mkey':'\x09\x00\x01\x04mkey','ckey':'\x27\x00\x01\x04ckey','key':'\x00\x01\x03key',}
- if not starts_with(device, 'PartialRecoveryFile:'):
- r=search_patterns_on_disk(device, size, inc, map(lambda x:nameToDBName[x], ['mkey', 'ckey', 'key']))
- f=open(outputdir+'/pywallet_partial_recovery_%d.dat'%ts(), 'w')
- f.write(str(r))
- f.close()
- print "\nRead %.1f Go in %.1f minutes\n"%(r['PRFsize']/1e9, r['PRFdt']/60.0)
- else:
- prf=device[20:]
- f=open(prf, 'r')
- content=f.read()
- f.close()
- cmd=("z = "+content+"")
- exec cmd in locals()
- r=z
- device=r['PRFdevice']
- print "\nLoaded %.1f Go from %s\n"%(r['PRFsize']/1e9, device)
- try:
- otype=os.O_RDONLY|os.O_BINARY
- except:
- otype=os.O_RDONLY
- fd = os.open(device, otype)
- mkeys=[]
- crypters=[]
- syst=systype()
- for offset in r[nameToDBName['mkey']]:
- s=recov_mkey(fd, offset)
- if s==None:
- continue
- newmkey=RecovMkey(s[1],s[3],int(s[5][::-1].encode('hex'), 16),int(s[4][::-1].encode('hex'), 16),int(s[-1][::-1].encode('hex'), 16))
- mkeys.append([offset,newmkey])
- print "Found", len(mkeys), 'possible wallets'
- ckeys=[]
- for offset in r[nameToDBName['ckey']]:
- s=recov_ckey(fd, offset)
- if s==None:
- continue
- newckey=RecovCkey(s[1], s[5][:int(s[4].encode('hex'),16)])
- ckeys.append([offset,newckey])
- print "Found", len(ckeys), 'possible encrypted keys'
- uckeys=[]
- for offset in r[nameToDBName['key']]:
- s=recov_uckey(fd, offset)
- if s==None:
- continue
- uckeys.append(s[4])
- print "Found", len(uckeys), 'possible unencrypted keys'
- os.close(fd)
- list_of_possible_keys_per_master_key=dict(map(lambda x:[x[1],[]], mkeys))
- for cko,ck in ckeys:
- tl=map(lambda x:[abs(x[0]-cko)]+x, mkeys)
- tl=sorted(tl, key=lambda x:x[0])
- list_of_possible_keys_per_master_key[tl[0][2]].append(ck)
- cpt=0
- mki=1
- tzero=time.time()
- if len(passes)==0:
- if len(ckeys)>0:
- print "Can't decrypt them as you didn't provide any passphrase."
- else:
- for mko,mk in mkeys:
- list_of_possible_keys=list_of_possible_keys_per_master_key[mk]
- sys.stdout.write( "\nPossible wallet #"+str(mki))
- sys.stdout.flush()
- for ppi,pp in enumerate(passes):
- sys.stdout.write( "\n with passphrase #"+str(ppi+1)+" ")
- sys.stdout.flush()
- failures_in_a_row=0
- # print "SKFP params:", pp, mk.salt, mk.iterations, mk.method
- res = crypter.SetKeyFromPassphrase(pp, mk.salt, mk.iterations, mk.method)
- if res == 0:
- print "Unsupported derivation method"
- sys.exit(1)
- masterkey = crypter.Decrypt(mk.encrypted_key)
- crypter.SetKey(masterkey)
- for ck in list_of_possible_keys:
- if cpt%10==9 and failures_in_a_row==0:
- sys.stdout.write('.')
- sys.stdout.flush()
- if failures_in_a_row>5:
- break
- crypter.SetIV(Hash(ck.public_key))
- secret = crypter.Decrypt(ck.encrypted_pk)
- compressed = ck.public_key[0] != '\04'
- pkey = EC_KEY(int('0x' + secret.encode('hex'), 16))
- if ck.public_key != GetPubKey(pkey, compressed):
- failures_in_a_row+=1
- else:
- failures_in_a_row=0
- ck.mkey=mk
- ck.privkey=secret
- cpt+=1
- mki+=1
- print "\n"
- tone=time.time()
- try:
- calcspeed=1.0*cpt/(tone-tzero)*60 #calc/min
- except:
- calcspeed=1.0
- if calcspeed==0:
- calcspeed=1.0
- ckeys_not_decrypted=filter(lambda x:x[1].privkey==None, ckeys)
- refused_to_test_all_pps=True
- if len(ckeys_not_decrypted)==0:
- print "All the found encrypted private keys have been decrypted."
- return map(lambda x:x[1].privkey, ckeys)
- else:
- print "Private keys not decrypted: %d"%len(ckeys_not_decrypted)
- print "Trying all the remaining possibilities (%d) might take up to %d minutes."%(len(ckeys_not_decrypted)*len(passes)*len(mkeys),int(len(ckeys_not_decrypted)*len(passes)*len(mkeys)/calcspeed))
- cont=raw_input("Do you want to test them? (y/n): ")
- while len(cont)==0:
- cont=raw_input("Do you want to test them? (y/n): ")
- if cont[0]=='y':
- refused_to_test_all_pps=False
- cpt=0
- for dist,mko,mk in tl:
- for ppi,pp in enumerate(passes):
- res = crypter.SetKeyFromPassphrase(pp, mk.salt, mk.iterations, mk.method)
- if res == 0:
- logging.error("Unsupported derivation method")
- sys.exit(1)
- masterkey = crypter.Decrypt(mk.encrypted_key)
- crypter.SetKey(masterkey)
- for cko,ck in ckeys_not_decrypted:
- tl=map(lambda x:[abs(x[0]-cko)]+x, mkeys)
- tl=sorted(tl, key=lambda x:x[0])
- if mk==tl[0][2]:
- continue #because already tested
- crypter.SetIV(Hash(ck.public_key))
- secret = crypter.Decrypt(ck.encrypted_pk)
- compressed = ck.public_key[0] != '\04'
- pkey = EC_KEY(int('0x' + secret.encode('hex'), 16))
- if ck.public_key == GetPubKey(pkey, compressed):
- ck.mkey=mk
- ck.privkey=secret
- cpt+=1
- print
- ckeys_not_decrypted=filter(lambda x:x[1].privkey==None, ckeys)
- if len(ckeys_not_decrypted)==0:
- print "All the found encrypted private keys have been finally decrypted."
- elif not refused_to_test_all_pps:
- print "Private keys not decrypted: %d"%len(ckeys_not_decrypted)
- print "Try another password, check the size of your partition or seek help"
- uncrypted_ckeys=filter(lambda x:x!=None, map(lambda x:x[1].privkey, ckeys))
- uckeys.extend(uncrypted_ckeys)
- return uckeys
- def ts():
- return int(time.mktime(datetime.now().timetuple()))
- def check_postkeys(key, postkeys):
- for i in postkeys:
- if key[:len(i)] == i:
- return True
- return False
- def one_element_in(a, string):
- for i in a:
- if i in string:
- return True
- return False
- def first_read(device, size, prekeys, inc=10000):
- t0 = ts()-1
- try:
- fd = os.open (device, os.O_RDONLY)
- except:
- print("Can't open %s, check the path or try as root"%device)
- exit(0)
- prekey = prekeys[0]
- data = ""
- i = 0
- data = os.read (fd, i)
- before_contained_key = False
- contains_key = False
- ranges = []
- while i < int(size):
- if i%(10*Mio) > 0 and i%(10*Mio) <= inc:
- print("\n%.2f/%.2f Go"%(i/1e9, size/1e9))
- t = ts()
- speed = i/(t-t0)
- ETAts = size/speed + t0
- d = datetime.fromtimestamp(ETAts)
- print(d.strftime(" ETA: %H:%M:%S"))
- try:
- data = os.read (fd, inc)
- except Exception as exc:
- os.lseek(fd, inc, os.SEEK_CUR)
- print str(exc)
- i += inc
- continue
- contains_key = one_element_in(prekeys, data)
- if not before_contained_key and contains_key:
- ranges.append(i)
- if before_contained_key and not contains_key:
- ranges.append(i)
- before_contained_key = contains_key
- i += inc
- os.close (fd)
- return ranges
- def shrink_intervals(device, ranges, prekeys, inc=1000):
- prekey = prekeys[0]
- nranges = []
- fd = os.open (device, os.O_RDONLY)
- for j in range(len(ranges)/2):
- before_contained_key = False
- contains_key = False
- bi = ranges[2*j]
- bf = ranges[2*j+1]
- mini_blocks = []
- k = bi
- while k <= bf + len(prekey) + 1:
- mini_blocks.append(k)
- k += inc
- mini_blocks.append(k)
- for k in range(len(mini_blocks)/2):
- mini_blocks[2*k] -= len(prekey) +1
- mini_blocks[2*k+1] += len(prekey) +1
- bi = mini_blocks[2*k]
- bf = mini_blocks[2*k+1]
- os.lseek(fd, bi, 0)
- data = os.read(fd, bf-bi+1)
- contains_key = one_element_in(prekeys, data)
- if not before_contained_key and contains_key:
- nranges.append(bi)
- if before_contained_key and not contains_key:
- nranges.append(bi+len(prekey) +1+len(prekey) +1)
- before_contained_key = contains_key
- os.close (fd)
- return nranges
- def find_offsets(device, ranges, prekeys):
- prekey = prekeys[0]
- list_offsets = []
- to_read = 0
- fd = os.open (device, os.O_RDONLY)
- for i in range(len(ranges)/2):
- bi = ranges[2*i]-len(prekey)-1
- os.lseek(fd, bi, 0)
- bf = ranges[2*i+1]+len(prekey)+1
- to_read += bf-bi+1
- buf = ""
- for j in range(len(prekey)):
- buf += "\x00"
- curs = bi
- while curs <= bf:
- data = os.read(fd, 1)
- buf = buf[1:] + data
- if buf in prekeys:
- list_offsets.append(curs)
- curs += 1
- os.close (fd)
- return [to_read, list_offsets]
- def read_keys(device, list_offsets):
- found_hexkeys = []
- fd = os.open (device, os.O_RDONLY)
- for offset in list_offsets:
- os.lseek(fd, offset+1, 0)
- data = os.read(fd, 40)
- hexkey = data[1:33].encode('hex')
- after_key = data[33:39].encode('hex')
- if hexkey not in found_hexkeys and check_postkeys(after_key.decode('hex'), postkeys):
- found_hexkeys.append(hexkey)
- os.close (fd)
- return found_hexkeys
- def read_device_size(size):
- if size[-2] == 'i':
- unit = size[-3:]
- value = float(size[:-3])
- else:
- unit = size[-2:]
- value = float(size[:-2])
- exec 'unit = %s' % unit
- return int(value * unit)
- def md5_2(a):
- return hashlib.md5(a).digest()
- def md5_file(nf):
- try:
- fichier = file(nf, 'r').read()
- return md5_2(fichier)
- except:
- return 'zz'
- def md5_onlinefile(add):
- page = urllib.urlopen(add).read()
- return md5_2(page)
- class KEY:
- def __init__ (self):
- self.prikey = None
- self.pubkey = None
- def generate (self, secret=None):
- if secret:
- exp = int ('0x' + secret.encode ('hex'), 16)
- self.prikey = ecdsa.SigningKey.from_secret_exponent (exp, curve=secp256k1)
- else:
- self.prikey = ecdsa.SigningKey.generate (curve=secp256k1)
- self.pubkey = self.prikey.get_verifying_key()
- return self.prikey.to_der()
- def set_privkey (self, key):
- if len(key) == 279:
- seq1, rest = der.remove_sequence (key)
- integer, rest = der.remove_integer (seq1)
- octet_str, rest = der.remove_octet_string (rest)
- tag1, cons1, rest, = der.remove_constructed (rest)
- tag2, cons2, rest, = der.remove_constructed (rest)
- point_str, rest = der.remove_bitstring (cons2)
- self.prikey = ecdsa.SigningKey.from_string(octet_str, curve=secp256k1)
- else:
- self.prikey = ecdsa.SigningKey.from_der (key)
- def set_pubkey (self, key):
- key = key[1:]
- self.pubkey = ecdsa.VerifyingKey.from_string (key, curve=secp256k1)
- def get_privkey (self):
- _p = self.prikey.curve.curve.p ()
- _r = self.prikey.curve.generator.order ()
- _Gx = self.prikey.curve.generator.x ()
- _Gy = self.prikey.curve.generator.y ()
- encoded_oid2 = der.encode_oid (*(1, 2, 840, 10045, 1, 1))
- encoded_gxgy = "\x04" + ("%64x" % _Gx).decode('hex') + ("%64x" % _Gy).decode('hex')
- param_sequence = der.encode_sequence (
- ecdsa.der.encode_integer(1),
- der.encode_sequence (
- encoded_oid2,
- der.encode_integer (_p),
- ),
- der.encode_sequence (
- der.encode_octet_string("\x00"),
- der.encode_octet_string("\x07"),
- ),
- der.encode_octet_string (encoded_gxgy),
- der.encode_integer (_r),
- der.encode_integer (1),
- );
- encoded_vk = "\x00\x04" + self.pubkey.to_string ()
- return der.encode_sequence (
- der.encode_integer (1),
- der.encode_octet_string (self.prikey.to_string ()),
- der.encode_constructed (0, param_sequence),
- der.encode_constructed (1, der.encode_bitstring (encoded_vk)),
- )
- def get_pubkey (self):
- return "\x04" + self.pubkey.to_string()
- def sign (self, hash):
- sig = self.prikey.sign_digest (hash, sigencode=ecdsa.util.sigencode_der)
- return sig.encode('hex')
- def verify (self, hash, sig):
- return self.pubkey.verify_digest (sig, hash, sigdecode=ecdsa.util.sigdecode_der)
- def bool_to_int(b):
- if b:
- return 1
- return 0
- class BCDataStream(object):
- def __init__(self):
- self.input = None
- self.read_cursor = 0
- def clear(self):
- self.input = None
- self.read_cursor = 0
- def write(self, bytes): # Initialize with string of bytes
- if self.input is None:
- self.input = bytes
- else:
- self.input += bytes
- def map_file(self, file, start): # Initialize with bytes from file
- self.input = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ)
- self.read_cursor = start
- def seek_file(self, position):
- self.read_cursor = position
- def close_file(self):
- self.input.close()
- def read_string(self):
- # Strings are encoded depending on length:
- # 0 to 252 : 1-byte-length followed by bytes (if any)
- # 253 to 65,535 : byte'253' 2-byte-length followed by bytes
- # 65,536 to 4,294,967,295 : byte '254' 4-byte-length followed by bytes
- # ... and the Bitcoin client is coded to understand:
- # greater than 4,294,967,295 : byte '255' 8-byte-length followed by bytes of string
- # ... but I don't think it actually handles any strings that big.
- if self.input is None:
- raise SerializationError("call write(bytes) before trying to deserialize")
- try:
- length = self.read_compact_size()
- except IndexError:
- raise SerializationError("attempt to read past end of buffer")
- return self.read_bytes(length)
- def write_string(self, string):
- # Length-encoded as with read-string
- self.write_compact_size(len(string))
- self.write(string)
- def read_bytes(self, length):
- try:
- result = self.input[self.read_cursor:self.read_cursor+length]
- self.read_cursor += length
- return result
- except IndexError:
- raise SerializationError("attempt to read past end of buffer")
- return ''
- def read_boolean(self): return self.read_bytes(1)[0] != chr(0)
- def read_int16(self): return self._read_num('<h')
- def read_uint16(self): return self._read_num('<H')
- def read_int32(self): return self._read_num('<i')
- def read_uint32(self): return self._read_num('<I')
- def read_int64(self): return self._read_num('<q')
- def read_uint64(self): return self._read_num('<Q')
- def write_boolean(self, val): return self.write(chr(bool_to_int(val)))
- def write_int16(self, val): return self._write_num('<h', val)
- def write_uint16(self, val): return self._write_num('<H', val)
- def write_int32(self, val): return self._write_num('<i', val)
- def write_uint32(self, val): return self._write_num('<I', val)
- def write_int64(self, val): return self._write_num('<q', val)
- def write_uint64(self, val): return self._write_num('<Q', val)
- def read_compact_size(self):
- size = ord(self.input[self.read_cursor])
- self.read_cursor += 1
- if size == 253:
- size = self._read_num('<H')
- elif size == 254:
- size = self._read_num('<I')
- elif size == 255:
- size = self._read_num('<Q')
- return size
- def write_compact_size(self, size):
- if size < 0:
- raise SerializationError("attempt to write size < 0")
- elif size < 253:
- self.write(chr(size))
- elif size < 2**16:
- self.write('\xfd')
- self._write_num('<H', size)
- elif size < 2**32:
- self.write('\xfe')
- self._write_num('<I', size)
- elif size < 2**64:
- self.write('\xff')
- self._write_num('<Q', size)
- def _read_num(self, format):
- (i,) = struct.unpack_from(format, self.input, self.read_cursor)
- self.read_cursor += struct.calcsize(format)
- return i
- def _write_num(self, format, num):
- s = struct.pack(format, num)
- self.write(s)
- def open_wallet(db_env, walletfile, writable=False):
- db = DB(db_env)
- if writable:
- DB_TYPEOPEN = DB_CREATE
- else:
- DB_TYPEOPEN = DB_RDONLY
- flags = DB_THREAD | DB_TYPEOPEN
- try:
- r = db.open(walletfile, "main", DB_BTREE, flags)
- except DBError:
- r = True
- if r is not None:
- logging.error("Couldn't open wallet.dat/main. Try quitting Bitcoin and running this again.")
- sys.exit(1)
- return db
- def inversetxid(txid):
- if len(txid) is not 64:
- print("Bad txid")
- return "CORRUPTEDTXID:"+txid
- # exit(0)
- new_txid = ""
- for i in range(32):
- new_txid += txid[62-2*i];
- new_txid += txid[62-2*i+1];
- return new_txid
- def parse_wallet(db, item_callback):
- kds = BCDataStream()
- vds = BCDataStream()
- def parse_TxIn(vds):
- d = {}
- d['prevout_hash'] = vds.read_bytes(32).encode('hex')
- d['prevout_n'] = vds.read_uint32()
- d['scriptSig'] = vds.read_bytes(vds.read_compact_size()).encode('hex')
- d['sequence'] = vds.read_uint32()
- return d
- def parse_TxOut(vds):
- d = {}
- d['value'] = vds.read_int64()/1e8
- d['scriptPubKey'] = vds.read_bytes(vds.read_compact_size()).encode('hex')
- return d
- for (key, value) in db.items():
- d = { }
- kds.clear(); kds.write(key)
- vds.clear(); vds.write(value)
- type = kds.read_string()
- d["__key__"] = key
- d["__value__"] = value
- d["__type__"] = type
- try:
- if type == "tx":
- d["tx_id"] = inversetxid(kds.read_bytes(32).encode('hex_codec'))
- start = vds.read_cursor
- d['version'] = vds.read_int32()
- n_vin = vds.read_compact_size()
- d['txIn'] = []
- for i in xrange(n_vin):
- d['txIn'].append(parse_TxIn(vds))
- n_vout = vds.read_compact_size()
- d['txOut'] = []
- for i in xrange(n_vout):
- d['txOut'].append(parse_TxOut(vds))
- d['lockTime'] = vds.read_uint32()
- d['tx'] = vds.input[start:vds.read_cursor].encode('hex_codec')
- d['txv'] = value.encode('hex_codec')
- d['txk'] = key.encode('hex_codec')
- elif type == "name":
- d['hash'] = kds.read_string()
- d['name'] = vds.read_string()
- elif type == "version":
- d['version'] = vds.read_uint32()
- elif type == "minversion":
- d['minversion'] = vds.read_uint32()
- elif type == "setting":
- d['setting'] = kds.read_string()
- d['value'] = parse_setting(d['setting'], vds)
- elif type == "key":
- d['public_key'] = kds.read_bytes(kds.read_compact_size())
- d['private_key'] = vds.read_bytes(vds.read_compact_size())
- elif type == "wkey":
- d['public_key'] = kds.read_bytes(kds.read_compact_size())
- d['private_key'] = vds.read_bytes(vds.read_compact_size())
- d['created'] = vds.read_int64()
- d['expires'] = vds.read_int64()
- d['comment'] = vds.read_string()
- elif type == "defaultkey":
- d['key'] = vds.read_bytes(vds.read_compact_size())
- elif type == "pool":
- d['n'] = kds.read_int64()
- d['nVersion'] = vds.read_int32()
- d['nTime'] = vds.read_int64()
- d['public_key'] = vds.read_bytes(vds.read_compact_size())
- elif type == "acc":
- d['account'] = kds.read_string()
- d['nVersion'] = vds.read_int32()
- d['public_key'] = vds.read_bytes(vds.read_compact_size())
- elif type == "acentry":
- d['account'] = kds.read_string()
- d['n'] = kds.read_uint64()
- d['nVersion'] = vds.read_int32()
- d['nCreditDebit'] = vds.read_int64()
- d['nTime'] = vds.read_int64()
- d['otherAccount'] = vds.read_string()
- d['comment'] = vds.read_string()
- elif type == "bestblock":
- d['nVersion'] = vds.read_int32()
- d.update(parse_BlockLocator(vds))
- elif type == "ckey":
- d['public_key'] = kds.read_bytes(kds.read_compact_size())
- d['encrypted_private_key'] = vds.read_bytes(vds.read_compact_size())
- elif type == "mkey":
- d['nID'] = kds.read_uint32()
- d['encrypted_key'] = vds.read_string()
- d['salt'] = vds.read_string()
- d['nDerivationMethod'] = vds.read_uint32()
- d['nDerivationIterations'] = vds.read_uint32()
- d['otherParams'] = vds.read_string()
- item_callback(type, d)
- except Exception, e:
- traceback.print_exc()
- print("ERROR parsing wallet.dat, type %s" % type)
- print("key data: %s"%key)
- print("key data in hex: %s"%key.encode('hex_codec'))
- print("value data in hex: %s"%value.encode('hex_codec'))
- sys.exit(1)
- def delete_from_wallet(db_env, walletfile, typedel, kd):
- db = open_wallet(db_env, walletfile, True)
- kds = BCDataStream()
- vds = BCDataStream()
- deleted_items = 0
- if not isinstance(kd, list):
- kd=[kd]
- if typedel=='tx' and kd!=['all']:
- for keydel in kd:
- db.delete('\x02\x74\x78'+keydel.decode('hex')[::-1])
- deleted_items+=1
- else:
- for i,keydel in enumerate(kd):
- for (key, value) in db.items():
- kds.clear(); kds.write(key)
- vds.clear(); vds.write(value)
- type = kds.read_string()
- if typedel == "tx" and type == "tx":
- db.delete(key)
- deleted_items+=1
- elif typedel == "key":
- if type == "key" or type == "ckey":
- if keydel == public_key_to_bc_address(kds.read_bytes(kds.read_compact_size())):
- db.delete(key)
- deleted_items+=1
- elif type == "pool":
- vds.read_int32()
- vds.read_int64()
- if keydel == public_key_to_bc_address(vds.read_bytes(vds.read_compact_size())):
- db.delete(key)
- deleted_items+=1
- elif type == "name":
- if keydel == kds.read_string():
- db.delete(key)
- deleted_items+=1
- db.close()
- return deleted_items
- def merge_keys_lists(la, lb):
- lr={}
- llr=[]
- for k in la:
- lr[k[0]]=k[1]
- for k in lb:
- if k[0] in lr.keys():
- lr[k[0]]=lr[k[0]]+" / "+k[1]
- else:
- lr[k[0]]=k[1]
- for k,j in lr.items():
- llr.append([k,j])
- return llr
- def merge_wallets(wadir, wa, wbdir, wb, wrdir, wr, passphrase_a, passphrase_b, passphrase_r):
- global passphrase
- passphrase_LAST=passphrase
- #Read Wallet 1
- passphrase=passphrase_a
- dba_env = create_env(wadir)
- crypted_a = read_wallet(json_db, dba_env, wa, True, True, "", None)['crypted']
- list_keys_a=[]
- for i in json_db['keys']:
- try:
- label=i['label']
- except:
- label="#Reserve"
- try:
- list_keys_a.append([i['secret'], label])
- except:
- pass
- if len(list_keys_a)==0:
- return [False, "Something went wrong with the first wallet."]
- #Read Wallet 2
- passphrase=passphrase_b
- dbb_env = create_env(wbdir)
- crypted_b = read_wallet(json_db, dbb_env, wb, True, True, "", None)['crypted']
- list_keys_b=[]
- for i in json_db['keys']:
- try:
- label=i['label']
- except:
- label="#Reserve"
- try:
- list_keys_b.append([i['secret'], label])
- except:
- pass
- if len(list_keys_b)==0:
- return [False, "Something went wrong with the second wallet."]
- m=merge_keys_lists(list_keys_a,list_keys_b)
- #Create new wallet
- dbr_env = create_env(wrdir)
- create_new_wallet(dbr_env, wr, 80100)
- dbr = open_wallet(dbr_env, wr, True)
- update_wallet(dbr, 'minversion', { 'minversion' : 60000})
- if len(passphrase_r)>0:
- NPP_salt=random_string(16).decode('hex')
- NPP_rounds=int(50000+random.random()*20000)
- NPP_method=0
- NPP_MK=random_string(64).decode('hex')
- crypter.SetKeyFromPassphrase(passphrase_r, NPP_salt, NPP_rounds, NPP_method)
- NPP_EMK = crypter.Encrypt(NPP_MK)
- update_wallet(dbr, 'mkey', {
- "encrypted_key": NPP_EMK,
- 'nDerivationIterations' : NPP_rounds,
- 'nDerivationMethod' : NPP_method,
- 'nID' : 1,
- 'otherParams' : ''.decode('hex'),
- "salt": NPP_salt
- })
- dbr.close()
- t='\n'.join(map(lambda x:';'.join(x), m))
- passphrase=passphrase_r
- global global_merging_message
- global_merging_message=["Merging...","Merging..."]
- thread.start_new_thread(import_csv_keys, ("\x00"+t, wrdir, wr,))
- t=""
- passphrase=passphrase_LAST
- return [True]
- def random_string(l, alph="0123456789abcdef"):
- r=""
- la=len(alph)
- for i in range(l):
- r+=alph[int(la*(random.random()))]
- return r
- def update_wallet(db, types, datas, paramsAreLists=False):
- """Write a single item to the wallet.
- db must be open with writable=True.
- type and data are the type code and data dictionary as parse_wallet would
- give to item_callback.
- data's __key__, __value__ and __type__ are ignored; only the primary data
- fields are used.
- """
- if not paramsAreLists:
- types=[types]
- datas=[datas]
- if len(types)!=len(datas):
- raise Exception("UpdateWallet: sizes are different")
- for it,type in enumerate(types):
- data=datas[it]
- d = data
- kds = BCDataStream()
- vds = BCDataStream()
- # Write the type code to the key
- kds.write_string(type)
- vds.write("") # Ensure there is something
- try:
- if type == "tx":
- # raise NotImplementedError("Writing items of type 'tx'")
- kds.write(d['txi'][6:].decode('hex_codec'))
- vds.write(d['txv'].decode('hex_codec'))
- elif type == "name":
- kds.write_string(d['hash'])
- vds.write_string(d['name'])
- elif type == "version":
- vds.write_uint32(d['version'])
- elif type == "minversion":
- vds.write_uint32(d['minversion'])
- elif type == "setting":
- raise NotImplementedError("Writing items of type 'setting'")
- kds.write_string(d['setting'])
- #d['value'] = parse_setting(d['setting'], vds)
- elif type == "key":
- kds.write_string(d['public_key'])
- vds.write_string(d['private_key'])
- elif type == "wkey":
- kds.write_string(d['public_key'])
- vds.write_string(d['private_key'])
- vds.write_int64(d['created'])
- vds.write_int64(d['expires'])
- vds.write_string(d['comment'])
- elif type == "defaultkey":
- vds.write_string(d['key'])
- elif type == "pool":
- kds.write_int64(d['n'])
- vds.write_int32(d['nVersion'])
- vds.write_int64(d['nTime'])
- vds.write_string(d['public_key'])
- elif type == "acc":
- kds.write_string(d['account'])
- vds.write_int32(d['nVersion'])
- vds.write_string(d['public_key'])
- elif type == "acentry":
- kds.write_string(d['account'])
- kds.write_uint64(d['n'])
- vds.write_int32(d['nVersion'])
- vds.write_int64(d['nCreditDebit'])
- vds.write_int64(d['nTime'])
- vds.write_string(d['otherAccount'])
- vds.write_string(d['comment'])
- elif type == "bestblock":
- vds.write_int32(d['nVersion'])
- vds.write_compact_size(len(d['hashes']))
- for h in d['hashes']:
- vds.write(h)
- elif type == "ckey":
- kds.write_string(d['public_key'])
- vds.write_string(d['encrypted_private_key'])
- elif type == "mkey":
- kds.write_uint32(d['nID'])
- vds.write_string(d['encrypted_key'])
- vds.write_string(d['salt'])
- vds.write_uint32(d['nDerivationMethod'])
- vds.write_uint32(d['nDerivationIterations'])
- vds.write_string(d['otherParams'])
- else:
- print "Unknown key type: "+type
- # Write the key/value pair to the database
- db.put(kds.input, vds.input)
- except Exception, e:
- print("ERROR writing to wallet.dat, type %s"%type)
- print("data dictionary: %r"%data)
- traceback.print_exc()
- def create_new_wallet(db_env, walletfile, version):
- db_out = DB(db_env)
- try:
- r = db_out.open(walletfile, "main", DB_BTREE, DB_CREATE)
- except DBError:
- r = True
- if r is not None:
- logging.error("Couldn't open %s."%walletfile)
- sys.exit(1)
- db_out.put("0776657273696f6e".decode('hex'), ("%08x"%version).decode('hex')[::-1])
- db_out.close()
- def rewrite_wallet(db_env, walletfile, destFileName, pre_put_callback=None):
- db = open_wallet(db_env, walletfile)
- db_out = DB(db_env)
- try:
- r = db_out.open(destFileName, "main", DB_BTREE, DB_CREATE)
- except DBError:
- r = True
- if r is not None:
- logging.error("Couldn't open %s."%destFileName)
- sys.exit(1)
- def item_callback(type, d):
- if (pre_put_callback is None or pre_put_callback(type, d)):
- db_out.put(d["__key__"], d["__value__"])
- parse_wallet(db, item_callback)
- db_out.close()
- db.close()
- # end of bitcointools wallet.dat handling code
- # wallet.dat reader / writer
- addr_to_keys={}
- def read_wallet(json_db, db_env, walletfile, print_wallet, print_wallet_transactions, transaction_filter, include_balance, vers=-1, FillPool=False):
- global passphrase, addr_to_keys
- crypted=False
- private_keys = []
- private_hex_keys = []
- if vers > -1:
- global addrtype
- oldaddrtype = addrtype
- addrtype = vers
- db = open_wallet(db_env, walletfile, writable=FillPool)
- json_db['keys'] = []
- json_db['pool'] = []
- json_db['tx'] = []
- json_db['names'] = {}
- json_db['ckey'] = []
- json_db['mkey'] = {}
- def item_callback(type, d):
- if type == "tx":
- json_db['tx'].append({"tx_id" : d['tx_id'], "txin" : d['txIn'], "txout" : d['txOut'], "tx_v" : d['txv'], "tx_k" : d['txk']})
- elif type == "name":
- json_db['names'][d['hash']] = d['name']
- elif type == "version":
- json_db['version'] = d['version']
- elif type == "minversion":
- json_db['minversion'] = d['minversion']
- elif type == "setting":
- if not json_db.has_key('settings'): json_db['settings'] = {}
- json_db["settings"][d['setting']] = d['value']
- elif type == "defaultkey":
- json_db['defaultkey'] = public_key_to_bc_address(d['key'])
- elif type == "key":
- addr = public_key_to_bc_address(d['public_key'])
- compressed = d['public_key'][0] != '\04'
- sec = SecretToASecret(PrivKeyToSecret(d['private_key']), compressed)
- hexsec = ASecretToSecret(sec).encode('hex')[:32]
- private_keys.append(sec)
- addr_to_keys[addr]=[hexsec, d['public_key'].encode('hex')]
- json_db['keys'].append({'addr' : addr, 'sec' : sec, 'hexsec' : hexsec, 'secret' : hexsec, 'pubkey':d['public_key'].encode('hex'), 'compressed':compressed, 'private':d['private_key'].encode('hex')})
- elif type == "wkey":
- if not json_db.has_key('wkey'): json_db['wkey'] = []
- json_db['wkey']['created'] = d['created']
- elif type == "pool":
- """ d['n'] = kds.read_int64()
- d['nVersion'] = vds.read_int32()
- d['nTime'] = vds.read_int64()
- d['public_key'] = vds.read_bytes(vds.read_compact_size())"""
- try:
- json_db['pool'].append( {'n': d['n'], 'addr': public_key_to_bc_address(d['public_key']), 'addr2': public_key_to_bc_address(d['public_key'].decode('hex')), 'addr3': public_key_to_bc_address(d['public_key'].encode('hex')), 'nTime' : d['nTime'], 'nVersion' : d['nVersion'], 'public_key_hex' : d['public_key'] } )
- except:
- json_db['pool'].append( {'n': d['n'], 'addr': public_key_to_bc_address(d['public_key']), 'nTime' : d['nTime'], 'nVersion' : d['nVersion'], 'public_key_hex' : d['public_key'].encode('hex') } )
- elif type == "acc":
- json_db['acc'] = d['account']
- print("Account %s (current key: %s)"%(d['account'], public_key_to_bc_address(d['public_key'])))
- elif type == "acentry":
- json_db['acentry'] = (d['account'], d['nCreditDebit'], d['otherAccount'], time.ctime(d['nTime']), d['n'], d['comment'])
- elif type == "bestblock":
- json_db['bestblock'] = d['hashes'][0][::-1].encode('hex_codec')
- elif type == "ckey":
- crypted=True
- compressed = d['public_key'][0] != '\04'
- json_db['keys'].append({ 'pubkey': d['public_key'].encode('hex'),'addr': public_key_to_bc_address(d['public_key']), 'encrypted_privkey': d['encrypted_private_key'].encode('hex_codec'), 'compressed':compressed})
- elif type == "mkey":
- json_db['mkey']['nID'] = d['nID']
- json_db['mkey']['encrypted_key'] = d['encrypted_key'].encode('hex_codec')
- json_db['mkey']['salt'] = d['salt'].encode('hex_codec')
- json_db['mkey']['nDerivationMethod'] = d['nDerivationMethod']
- json_db['mkey']['nDerivationIterations'] = d['nDerivationIterations']
- json_db['mkey']['otherParams'] = d['otherParams']
- if passphrase:
- res = crypter.SetKeyFromPassphrase(passphrase, d['salt'], d['nDerivationIterations'], d['nDerivationMethod'])
- if res == 0:
- logging.error("Unsupported derivation method")
- sys.exit(1)
- masterkey = crypter.Decrypt(d['encrypted_key'])
- crypter.SetKey(masterkey)
- else:
- json_db[type] = 'unsupported'
- print "Wallet data not recognized: "+str(d)
- list_of_reserve_not_in_pool=[]
- parse_wallet(db, item_callback)
- nkeys = len(json_db['keys'])
- i = 0
- for k in json_db['keys']:
- i+=1
- addr = k['addr']
- if include_balance:
- # print("%3d/%d %s %s" % (i, nkeys, k["addr"], k["balance"]))
- k["balance"] = balance(balance_site, k["addr"])
- # print(" %s" % (i, nkeys, k["addr"], k["balance"]))
- if addr in json_db['names'].keys():
- k["label"] = json_db['names'][addr]
- k["reserve"] = 0
- else:
- k["reserve"] = 1
- list_of_reserve_not_in_pool.append(k['pubkey'])
- def rnip_callback(a):
- list_of_reserve_not_in_pool.remove(a['public_key_hex'])
- if FillPool:
- map(rnip_callback, json_db['pool'])
- cpt=1
- for p in list_of_reserve_not_in_pool:
- update_wallet(db, 'pool', { 'public_key' : p.decode('hex'), 'n' : cpt, 'nTime' : ts(), 'nVersion':80100 })
- cpt+=1
- db.close()
- crypted = 'salt' in json_db['mkey']
- if not crypted:
- print "The wallet is not encrypted"
- if crypted and not passphrase:
- print "The wallet is encrypted but no passphrase is used"
- if crypted and passphrase:
- check = True
- ppcorrect=True
- for k in json_db['keys']:
- if 'encrypted_privkey' in k:
- ckey = k['encrypted_privkey'].decode('hex')
- public_key = k['pubkey'].decode('hex')
- crypter.SetIV(Hash(public_key))
- secret = crypter.Decrypt(ckey)
- compressed = public_key[0] != '\04'
- if check:
- check = False
- pkey = EC_KEY(int('0x' + secret.encode('hex'), 16))
- if public_key != GetPubKey(pkey, compressed):
- print "The wallet is encrypted and the passphrase is incorrect"
- ppcorrect=False
- break
- sec = SecretToASecret(secret, compressed)
- k['sec'] = sec
- k['hexsec'] = secret[:32].encode('hex')
- k['secret'] = secret.encode('hex')
- k['compressed'] = compressed
- addr_to_keys[k['addr']]=[sec, k['pubkey']]
- # del(k['ckey'])
- # del(k['secret'])
- # del(k['pubkey'])
- private_keys.append(sec)
- if ppcorrect:
- print "The wallet is encrypted and the passphrase is correct"
- for k in json_db['keys']:
- if k['compressed'] and 'secret' in k:
- k['secret']+="01"
- # del(json_db['pool'])
- # del(json_db['names'])
- if vers > -1:
- addrtype = oldaddrtype
- return {'crypted':crypted}
- def importprivkey(db, sec, label, reserve, keyishex, verbose=True, addrv=addrtype):
- if keyishex is None:
- pkey = regenerate_key(sec)
- compressed = is_compressed(sec)
- elif len(sec) == 64:
- pkey = EC_KEY(str_to_long(sec.decode('hex')))
- compressed = False
- elif len(sec) == 66:
- pkey = EC_KEY(str_to_long(sec[:-2].decode('hex')))
- compressed = True
- else:
- print("Hexadecimal private keys must be 64 or 66 characters long (specified one is "+str(len(sec))+" characters long)")
- return False
- if not pkey:
- return False
- secret = GetSecret(pkey)
- private_key = GetPrivKey(pkey, compressed)
- public_key = GetPubKey(pkey, compressed)
- addr = public_key_to_bc_address(public_key, addrv)
- if verbose:
- print "Address (%s): %s"%(aversions[addrv], addr)
- print "Privkey (%s): %s"%(aversions[addrv], SecretToASecret(secret, compressed))
- print "Hexprivkey: %s"%(secret.encode('hex'))
- print "Hash160: %s"%(bc_address_to_hash_160(addr).encode('hex'))
- if not compressed:
- print "Pubkey: 04%.64x%.64x"%(pkey.pubkey.point.x(), pkey.pubkey.point.y())
- else:
- print "Pubkey: 0%d%.64x"%(2+(pkey.pubkey.point.y()&1), pkey.pubkey.point.x())
- if int(secret.encode('hex'), 16)>_r:
- print 'Beware, 0x%s is equivalent to 0x%.33x</b>'%(secret.encode('hex'), int(secret.encode('hex'), 16)-_r)
- global crypter, passphrase, json_db
- crypted = False
- if 'mkey' in json_db.keys() and 'salt' in json_db['mkey']:
- crypted = True
- if crypted:
- if passphrase:
- cry_master = json_db['mkey']['encrypted_key'].decode('hex')
- cry_salt = json_db['mkey']['salt'].decode('hex')
- cry_rounds = json_db['mkey']['nDerivationIterations']
- cry_method = json_db['mkey']['nDerivationMethod']
- crypter.SetKeyFromPassphrase(passphrase, cry_salt, cry_rounds, cry_method)
- # if verbose:
- # print "Import with", passphrase, "", cry_master.encode('hex'), "", cry_salt.encode('hex')
- masterkey = crypter.Decrypt(cry_master)
- crypter.SetKey(masterkey)
- crypter.SetIV(Hash(public_key))
- e = crypter.Encrypt(secret)
- ck_epk=e
- update_wallet(db, 'ckey', { 'public_key' : public_key, 'encrypted_private_key' : ck_epk })
- else:
- update_wallet(db, 'key', { 'public_key' : public_key, 'private_key' : private_key })
- if not reserve:
- update_wallet(db, 'name', { 'hash' : addr, 'name' : label })
- return True
- def balance(site, address):
- page=urllib.urlopen("%s=%s" % (site, address))
- json_acc = json.loads(page.read().split("<end>")[0])
- if json_acc['0'] == 0:
- return "Invalid address"
- elif json_acc['0'] == 2:
- return "Never used"
- else:
- return json_acc['balance']
- def read_jsonfile(filename):
- filin = open(filename, 'r')
- txdump = filin.read()
- filin.close()
- return json.loads(txdump)
- def write_jsonfile(filename, array):
- filout = open(filename, 'w')
- filout.write(json.dumps(array, sort_keys=True, indent=0))
- filout.close()
- def keyinfo(sec, keyishex):
- if keyishex is None:
- pkey = regenerate_key(sec)
- compressed = is_compressed(sec)
- elif len(sec) == 64:
- pkey = EC_KEY(str_to_long(sec.decode('hex')))
- compressed = False
- elif len(sec) == 66:
- pkey = EC_KEY(str_to_long(sec[:-2].decode('hex')))
- compressed = True
- else:
- print("Hexadecimal private keys must be 64 or 66 characters long (specified one is "+str(len(sec))+" characters long)")
- exit(0)
- if not pkey:
- return False
- secret = GetSecret(pkey)
- private_key = GetPrivKey(pkey, compressed)
- public_key = GetPubKey(pkey, compressed)
- addr = public_key_to_bc_address(public_key)
- print "Address (%s): %s" % ( aversions[addrtype], addr )
- print "Privkey (%s): %s" % ( aversions[addrtype], SecretToASecret(secret, compressed) )
- print "Hexprivkey: %s" % secret.encode('hex')
- print "Hash160: %s"%(bc_address_to_hash_160(addr).encode('hex'))
- return True
- def css_wui():
- return """html, body {
- height: 100%;
- width: 100%;
- padding: 0;
- margin: 0;
- }
- body {
- margin: 0px;
- padding: 0px;
- background: url(data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAABLAAD/4QMpaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjAtYzA2MSA2NC4xNDA5NDksIDIwMTAvMTIvMDctMTA6NTc6MDEgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzUgV2luZG93cyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDozRjJGNUI0ODZBN0YxMUUyQkZGRUNDQzgwNjYxQkJENCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDozRjJGNUI0OTZBN0YxMUUyQkZGRUNDQzgwNjYxQkJENCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjNGMkY1QjQ2NkE3RjExRTJCRkZFQ0NDODA2NjFCQkQ0IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjNGMkY1QjQ3NkE3RjExRTJCRkZFQ0NDODA2NjFCQkQ0Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+/+4ADkFkb2JlAGTAAAAAAf/bAIQAAwICAgICAwICAwUDAwMFBQQDAwQF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%3D%3D) repeat;
- font-family: 'Open Sans', sans-serif;
- font-size: 10pt;
- color: #B0B0B0;
- }
- h1, h2, h3 {
- margin: 0;
- padding: 0;
- }
- h2
- {
- font-weight: 400;
- font-family: 'Archivo Narrow', sans-serif;
- font-size: 2.50em;
- }
- p, ol, ul {
- margin-top: 0px;
- }
- p {
- line-height: 180%;
- }
- strong {
- }
- a {
- color: #1492C4;
- }
- a:hover {
- text-decoration: none;
- }
- a img {
- border: none;
- }
- img.border {
- border: 10px solid rgba(255,255,255,.10);
- }
- img.alignleft {
- float: left;
- margin-right: 30px;
- }
- img.alignright {
- float: right;
- }
- img.aligncenter {
- margin: 0px auto;
- }
- hr {
- display: none;
- }
- #retour-pyw{
- overflow: auto;
- }
- #uptodate{
- position:absolute;
- top:0px;
- right:0px;
- background: rgba(0,0,0,0.70);
- padding:10px;
- }
- #full-screen-background-image {
- z-index: -999;
- min-height: 100%;
- min-width: 1024px;
- width: 100%;
- height: auto;
- position: fixed;
- top: 0;
- left: 0;
- }
- #wrapper {
- position: relative;
- width: 100%;
- min-height: 400px;
- #margin: 30px auto;
- margin-top:10px; #decalage p/r haut
- }
- #wrapper {
- overflow: hidden;
- }
- .container {
- width: 1000px;
- margin: 0px auto;
- }
- .clearfix {
- clear: both;
- }
- /** HEADER */
- #header-wrapper-title
- {
- overflow: hidden;
- height: 80px;
- margin-bottom: 10px;
- background: rgba(0,0,0,0);
- }
- #header-wrapper
- {
- overflow: hidden;
- height: 50px;
- margin-bottom: 20px;
- background: rgba(0,0,0,0.70);
- }
- #header {
- overflow: hidden;
- }
- /** LOGO */
- #logo {
- float: left;
- #width: 300px;
- height: 50px;
- }
- #logo h1, #logo p {
- margin: 0px;
- line-height: normal;
- }
- #logo h1 a {
- padding-left: 00px;
- text-decoration: none;
- font-size: 2.50em;
- font-weight: 400;
- font-family: 'Archivo Narrow', sans-serif;
- color: #FFFFFF;
- }
- /** MENU */
- #menu {
- float: left;
- height: 50px;
- }
- #menu ul {
- margin: 0px;
- padding: 0px;
- list-style: none;
- line-height: normal;
- }
- #menu li {
- float: left;
- margin-right: 10px;
- padding: 0px 5px 0px 5px;
- }
- #menu a {
- display: block;
- height: 50px;
- padding: 0px 10px;
- line-height: 50px;
- text-decoration: none;
- text-transform: uppercase;
- color: #FFFFFF;
- }
- #menu a:hover {
- text-decoration: none;
- background: rgba(0,0,0,0.70);
- }
- #menu .active
- {
- background: rgba(0,0,0,0.70);
- }
- /** PAGE */
- #page {
- overflow: hidden;
- margin-bottom: 20px;
- }
- /** CONTENT */
- #content {
- float: left;
- width: 950px;
- padding: 40px;
- background: rgba(0,0,0,0.70);
- }
- #content h2 a
- {
- display: block;
- padding: 0px 0px 20px 0px;
- text-decoration: none;
- color: #FFFFFF;
- }
- #content #box1
- {
- margin-bottom: 0px;
- }
- /** SIDEBAR */
- #sidebar {
- float: right;
- width: 350px;
- padding: 20px;
- background: rgba(0,0,0,0.70);
- }
- #sidebar h2
- {
- padding: 0px 0px 00px 0px;
- color: #FFFFFF;
- }
- /* Footer */
- #footer {
- overflow: hidden;
- margin: 00px auto 0px auto;
- padding: 10px 0px;
- background: rgba(0,0,0,0.70);
- }
- #footer p {
- text-align: center;
- font-size: 12px;
- }
- #footer a {
- }
- /** LIST STYLE 1 */
- ul.style1 {
- margin: 0px;
- padding: 10px 0px 0px 0px;
- list-style: none;
- }
- ul.style1 li {
- clear: both;
- margin-bottom: 25px;
- padding: 30px 0px 40px 0px;
- border-top: 1px solid #000000;
- box-shadow: inset 0 1px 0 rgba(255,255,255,.10);
- }
- ul.style1 h3 {
- padding-bottom: 5px;
- font-size: 14px;
- color: #FFFFFF;
- }
- ul.style1 p {
- line-height: 150%;
- }
- ul.style1 .button-style {
- float: left;
- margin-top: 0px;
- }
- ul.style1 .first {
- padding-top: 0px;
- border-top: none;
- box-shadow: none;
- }
- /** LIST STYLE 3 */
- ul.style3 {
- margin: 0px;
- padding: 0px;
- list-style: none;
- }
- ul.style3 li {
- padding: 10px 0px 10px 0px;
- border-top: 1px solid #000000;
- box-shadow: inset 0 1px 0 rgba(255,255,255,.10);
- }
- ul.style3 a {
- text-decoration: none;
- color: #949494;
- }
- ul.style3 a:hover {
- text-decoration: underline;
- }
- ul.style3 .first {
- padding-top: 0px;
- border-top: none;
- box-shadow: none;
- }
- ul.style3 .date {
- width: 87px;
- background-color: #1F768D;
- margin-top: 20px;
- height: 24px;
- line-height: 24px;
- text-align: center;
- font-size: 12px;
- color: #FFFFFF;
- }
- ul.style3 .first .date
- {
- margin-top: 0px;
- }
- .button-style
- {
- display: inline-block;
- background-color: #1F768D;
- margin-top: 0px;
- padding: 5px 30px;
- height: 24px;
- line-height: 24px;
- text-decoration: none;
- text-align: center;
- color: #FFFFFF;
- }
- .button-style-red
- {
- color: #ffffff;
- display: inline-block;
- background-color: #a12323;
- margin-top: 20px;
- padding: 5px 30px;
- height: 24px;
- line-height: 24px;
- text-decoration: none;
- text-align: center;
- }
- .entry
- {
- margin-bottom: 30px;
- }
- """
- def onclick_on_tab(page):
- list=['DumpPage','ImportPage','DeletePage','InfoPage','AboutPage','PassphrasePage','TxPage']
- r=''
- for p in list:
- if p!=page:
- r+="document.getElementById('"+p+"').style.display='none';"
- r+="document.getElementById('"+p+"Button').className='';"
- r+="document.getElementById('"+page+"').style.display='block';"
- r+="document.getElementById('"+page+"Button').className='active';"
- return r
- def html_wui(listcontent,uptodate_text):
- global pywversion
- return """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>Pywallet Web Interface - Pywallet """+pywversion+"""</title>
- <!--link href='http://fonts.googleapis.com/css?family=Archivo+Narrow:400,700|Open+Sans:400,600,700' rel='stylesheet' type='text/css'-->
- <!--link href="default.css" rel="stylesheet" type="text/css" media="all" /-->
- <style type="text/css">
- @font-face {
- font-family: 'Archivo Narrow';
- font-style: normal;
- font-weight: 400;
- src: local('Archivo Narrow Regular'), local('ArchivoNarrow-Regular'), url('data:application/x-font-woff;base64,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') format('woff');
- }
- @font-face {
- font-family: 'Archivo Narrow';
- font-style: normal;
- font-weight: 700;
- src: local('Archivo Narrow Bold'), local('ArchivoNarrow-Bold'), url('data:application/x-font-woff;base64,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') format('woff');
- }
- @font-face {
- font-family: 'Open Sans';
- font-style: normal;
- font-weight: 400;
- src: local('Open Sans'), local('OpenSans'), url('data:application/x-font-woff;base64,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') format('woff');
- }
- @font-face {
- font-family: 'Open Sans';
- font-style: normal;
- font-weight: 600;
- src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url('data:application/x-font-woff;base64,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') format('woff');
- }
- @font-face {
- font-family: 'Open Sans';
- font-style: normal;
- font-weight: 700;
- src: local('Open Sans Bold'), local('OpenSans-Bold'), url('data:application/x-font-woff;base64,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') format('woff');
- }
- """+css_wui()+"""
- </style>
- </head>
- <body>
- <div id="wrapper">
- <div id="header-wrapper-title">
- <div id="header" class="container">
- <div id="logo" style="height: 150px;">
- <h1><a href="#">Pywallet """+str(pywversion)+"""</a></h1>
- </div>
- </div>
- </div>
- <div id="header-wrapper">
- <div style="width:300px;float: left;"> </div>
- <div id="menu">
- <ul>
- <li id="DumpPageButton" class="active"><a href="#" accesskey="1" title="" onclick=" """+onclick_on_tab('DumpPage')+""" " >Dump</a></li>
- <li id="ImportPageButton"><a href="#" accesskey="2" title="" onclick=" """+onclick_on_tab('ImportPage')+""" " >Import</a></li>
- <li id="InfoPageButton"><a href="#" accesskey="3" title="" onclick=" """+onclick_on_tab('InfoPage')+""" " >Info</a></li>
- <li id="DeletePageButton"><a href="#" accesskey="4" title="" onclick=" """+onclick_on_tab('DeletePage')+""" " >Delete</a></li>
- <li id="PassphrasePageButton"><a href="#" accesskey="5" title="" onclick=" """+onclick_on_tab('PassphrasePage')+""" " >Passphrase</a></li>
- <li id="TxPageButton"><a href="#" accesskey="6" title="" onclick=" """+onclick_on_tab('TxPage')+""" " >Transaction</a></li>
- <li id="AboutPageButton"><a href="#" accesskey="7" title="" onclick=" """+onclick_on_tab('AboutPage')+""" " >About</a></li>
- <li id="QuitPageButton"><a href="quit">Stop</a></li>
- </ul>
- </div>
- </div>
- <div id="page" class="container">
- <div id="content">
- """+listcontent+"""
- </div>
- <div id="sidebar" style="display:none;">
- <a href="#" class="button-style-red" style="float:right;position:relative;top:-15px;" onclick="document.getElementById('content').style.width='950px';document.getElementById('content').style.display='block';document.getElementById('sidebar').style.display='none';document.getElementById('sidebar').style.width='350px';">Close</a>
- <a href="#" class="button-style" style="float:right;position:relative;top:5px;left:-10px;" onclick="
- if(document.getElementById('content').style.display=='none'){
- document.getElementById('sidebar').style.width='350px';
- document.getElementById('content').style.width='500px';
- document.getElementById('content').style.display='block';
- this.innerHTML='Full page';
- }else{
- document.getElementById('sidebar').style.width='970px';
- document.getElementById('content').style.display='none';
- this.innerHTML='Reduce';
- }
- document.getElementById('sidebar').style.display='block';
- ">Full page</a>
- <h2 style="positive:relative;top:-20px;">Data</h2>
- <br />
- <br />
- <p id="retour-pyw">
- </p>
- </div>
- </div>
- <div id="footer">
- <p><a href="http://pywallet.tk">Instructions to use Pywallet</a></p>
- </div>
- </div>
- <div id="uptodate">"""+uptodate_text+"""</div>
- </body>
- </html>
- """
- def WI_FormInit(title, action, divname):
- return "<li><h3>%s</h3>"%title
- return '<style>#h'+divname+':hover{color:red;}</style><h3 id="h'+divname+'" onClick="document.getElementById(\''+divname+'\').style.display=(document.getElementById(\''+divname+'\').style.display==\'none\')?\'block\':\'none\';document.getElementById(\'iconOF_'+divname+'\').innerHTML=image_showdiv(\''+divname+'\');"><span style="width:21px;" id="iconOF_'+divname+'"><img src="http://creation-entreprise.comprendrechoisir.com/img/puce_tab_down.png" /></span> '+title+'</h3><div id="'+divname+'"><form style="margin-left:15px;" action="'+action+'" method=get>'
- def WI_InputText(label, name, id, value, size=30):
- return '%s<input type=text name="%s" id="%s" value="%s" size=%s /><br />'%(label, name, id, value, size)
- def WI_InputPassword(label, name, id, value, size=30):
- return '%s<input type=password name="%s" id="%s" value="%s" size=%s /><br />'%(label, name, id, value, size)
- def WI_Submit(value, local_block, local_button, function):
- return """<br /><a href="#" class="button-style" onClick="document.getElementById('content').style.width='500px';document.getElementById('sidebar').style.display='block';%s();return false;">%s</a>"""%(function,value)
- def WI_CloseButton(local_block, local_button):
- return '<input type=button value="Close" onClick="document.getElementById(\'%s\').style.display=\'none\';document.getElementById(\'%s\').style.display=\'none\';" id="%s" style="display:none;" />'%(local_block, local_button, local_button)
- def WI_ReturnDiv(local_block):
- return '<div id="%s" style="display:none;margin:10px 3%% 10px;padding:10px;overflow:auto;width:90%%;max-height:600px;background-color:#fff8dd;"></div>'%(local_block)
- def WI_FormEnd():
- return "</li>"
- def WI_RadioButton(name, value, id, checked, label):
- return ' <input type="radio" name="%s" value="%s" id="%s" %s >%s<br>'%(name, value, id, checked, label)
- def WI_Checkbox(name, value, id, other, label):
- return '<input type="checkbox" name="%s" value="%s" id="%s" %s />%s'%(name, value, id, other, label)
- def WI_Endiv(t,name,title, desc,hidden=False):
- return '<div id="'+name+'" style="display:'+X_if_else('none',hidden,'block')+';"><div id="box1"><h2 class="title"><a href="#">'+title+'</a></h2>'+X_if_else('<p>'+desc+'</p>',desc!='','')+'</div><div ><ul class="style1">'+t+'</ul></div></div>'
- def WI_AjaxFunction(name, command_when_ready, query_string, command_until_ready):
- return '\n\
- function ajax%s(){\n\
- var ajaxRequest;\n\
- try{\n\
- ajaxRequest = new XMLHttpRequest();\n\
- } catch (e){\n\
- try{\n\
- ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");\n\
- } catch (e) {\n\
- try{\n\
- ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");\n\
- } catch (e){\n\
- alert("Your browser broke!");\n\
- return false;\n\
- }\n\
- }\n\
- }\n\
- ajaxRequest.onreadystatechange = function(){\n\
- if(ajaxRequest.readyState == 4){\n\
- %s\n\
- }\n\
- };\n\
- var queryString = %s;\n\
- ajaxRequest.open("GET", queryString, true);\n\
- %s\n\
- ajaxRequest.send(null);\n\
- }\n\
- \n\
- '%(name, command_when_ready, query_string, command_until_ready)
- def X_if_else(iftrue, cond, iffalse):
- if cond:
- return iftrue
- return iffalse
- def export_all_keys(db, ks, filename):
- txt=";".join(ks)+"\n"
- for i in db['keys']:
- try:
- j=i.copy()
- if 'label' not in j:
- j['label']='#Reserve'
- t=";".join([str(j[k]) for k in ks])
- txt+=t+"\n"
- except:
- return False
- try:
- myFile = open(filename, 'w')
- myFile.write(txt)
- myFile.close()
- return True
- except:
- return False
- def import_csv_keys(filename, wdir, wname, nbremax=9999999):
- global global_merging_message
- if filename[0]=="\x00": #yeah, dirty workaround
- content=filename[1:]
- else:
- filen = open(filename, "r")
- content = filen.read()
- filen.close()
- db_env = create_env(wdir)
- read_wallet(json_db, db_env, wname, True, True, "", None)
- db = open_wallet(db_env, wname, writable=True)
- content=content.split('\n')
- content=content[:min(nbremax, len(content))]
- for i in range(len(content)):
- c=content[i]
- global_merging_message = ["Merging: "+str(round(100.0*(i+1)/len(content),1))+"%" for j in range(2)]
- if ';' in c and len(c)>0 and c[0]!="#":
- cs=c.split(';')
- sec,label=cs[0:2]
- v=addrtype
- if len(cs)>2:
- v=int(cs[2])
- reserve=False
- if label=="#Reserve":
- reserve=True
- keyishex=None
- if abs(len(sec)-65)==1:
- keyishex=True
- importprivkey(db, sec, label, reserve, keyishex, verbose=False, addrv=v)
- global_merging_message = ["Merging done.", ""]
- db.close()
- read_wallet(json_db, db_env, wname, True, True, "", None, -1, True) #Fill the pool if empty
- return True
- def dep_text_aboutpage(val):
- if val:
- return "<span style='color:#bb0000;'>Not found</span>"
- else:
- return "<span style='color:#00bb00;'>Found</span>"
- CTX_adds=''
- if 'twisted' not in missing_dep:
- class WIRoot(resource.Resource):
- def render_GET(self, request):
- try:
- request.args['update'][0]
- return update_pyw()
- except:
- True
- uptodate=md5_last_pywallet[1]==md5_pywallet
- checking_finished=bool(md5_last_pywallet[0])
- color="#DDDDFF"
- if checking_finished:
- if uptodate:
- color="#DDFFDD"
- else:
- color="#FFDDDD"
- check_version_text = \
- X_if_else(
- X_if_else(
- 'Pywallet is up-to-date',
- uptodate,
- 'Pywallet is <span style="color:red;font-weight:none;">not</span> up-to-date<br /><a href="#" onclick="ajaxUpdatePyw();return false;">Click to update</a>'),
- checking_finished,
- 'Checking version...'
- )
- if beta_version:
- check_version_text="You are using a beta version<br />Thank you for your help"
- color="#DDDDDD"
- global pywversion
- header = '<h1 title="'+pyw_filename+' in '+pyw_path+'">Pywallet Web Interface v'+pywversion+'</h1><h3>CLOSE BITCOIN BEFORE USE!</h3><div style="position:fixed;top:5px;right:5px;border:solid 1px black;padding:15px;background-color:'+color+';font-weight:bold;text-align:center;">' + check_version_text + '</div><br /><br />'
- CPPForm = WI_FormInit('Change passphrase:', 'ChangePP', 'divformcpp') + \
- WI_InputPassword('', 'pp', 'cppf-pp', '') + \
- WI_Submit('Change', 'CPPDiv', 'cppf-close', 'ajaxCPP') + \
- WI_CloseButton('CPPDiv', 'cppf-close') + \
- WI_ReturnDiv('CPPDiv') + \
- WI_FormEnd()
- DWForm = WI_FormInit('Dump your wallet:', 'DumpWallet', 'divformdw') + \
- WI_InputText('Wallet Directory: ', 'dir', 'dwf-dir', determine_db_dir()) + \
- WI_InputText('Wallet Filename: ', 'name', 'dwf-name', determine_db_name(), 20) + \
- WI_InputText('<span style="border: 0 dashed;border-bottom-width:1px;" title="0 for Bitcoin, 52 for Namecoin, 111 for testnets">Version</span>:', 'vers', 'dwf-vers', '0', 1) + \
- WI_Checkbox('bal', 'y', 'dwf-bal', '', ' Dump with balance (can take minutes)') + "<br />" + \
- WI_Submit('Dump wallet', 'DWDiv', 'dwf-close', 'ajaxDW') + \
- WI_CloseButton('DWDiv', 'dwf-close') + \
- WI_ReturnDiv('DWDiv') + \
- WI_FormEnd()
- MWForm = WI_FormInit('Merge two wallets:', 'MergeWallets', 'divformmw') + \
- WI_InputText('Wallet 1 Directory: ', 'dir1', 'mwf-dir1', determine_db_dir()) + \
- WI_InputText('Wallet 1 Filename: ', 'name1', 'mwf-name1', determine_db_name(), 20) + \
- WI_InputPassword('<span style="border: 0 dashed;border-bottom-width:1px;" title="empty if none">Wallet 1 Passphrase: </span>', 'pass1', 'mwf-pass1', '') + "<br />" + \
- WI_InputText('Wallet 2 Directory: ', 'dir2', 'mwf-dir2', determine_db_dir()) + \
- WI_InputText('Wallet 2 Filename: ', 'name2', 'mwf-name2', "", 20) + \
- WI_InputPassword('<span style="border: 0 dashed;border-bottom-width:1px;" title="empty if none">Wallet 2 Passphrase: </span>', 'pass2', 'mwf-pass2', '') + "<br />" + \
- WI_InputText('Merged Wallet Directory: ', 'dirm', 'mwf-dirm', determine_db_dir()) + \
- WI_InputText('Merged Wallet Filename: ', 'namem', 'mwf-namem', "", 20) + \
- WI_InputPassword('<span style="border: 0 dashed;border-bottom-width:1px;" title="empty if none">Merged Wallet Passphrase: </span>', 'passm1', 'mwf-passm1', '') + \
- WI_InputPassword('Repeat Wallet Passphrase: ', 'passm2', 'mwf-passm2', '') + \
- WI_Submit('Merge wallets', 'MWDiv', 'mwf-close', 'ajaxMW') + \
- WI_CloseButton('MWDiv', 'mwf-close') + \
- WI_ReturnDiv('MWDiv') + \
- WI_FormEnd()
- DKForm = WI_FormInit('Dump your keys:', 'DumpKeys', 'divformdk') + \
- WI_InputText('Wallet Directory: ', 'dir', 'dkf-dir', determine_db_dir()) + \
- WI_InputText('Wallet Filename: ', 'name', 'dkf-name', determine_db_name(), 20) + \
- WI_InputText('<span style="border: 0 dashed;border-bottom-width:1px;" title="0 for Bitcoin, 52 for Namecoin, 111 for testnets">Version</span>:', 'vers', 'dkf-vers', '0', 1) + \
- WI_InputText('Output file: ', 'file', 'dkf-file', '', 60) + \
- WI_InputText('<span style="border: 0 dashed;border-bottom-width:1px;" title="to be chosen from the ones in wallet dump, separated with \',\', e.g. \'addr,secret\'">Data to print: </span>', 'keys', 'dkf-keys', '') + \
- WI_Checkbox('bal', 'y', 'dkf-bal', '', ' Dump with balance (can take minutes)') + "<br />" + \
- WI_Submit('Dump keys', 'DKDiv', 'dkf-close', 'ajaxDK') + \
- WI_CloseButton('DKDiv', 'dkf-close') + \
- WI_ReturnDiv('DKDiv') + \
- WI_FormEnd()
- IKForm = WI_FormInit('Import keys:', 'ImportKeys', 'divformik') + \
- "The CSV file must have the following format: '5PrivateKey;Label'<br />" + \
- WI_InputText('Wallet Directory: ', 'dir', 'ikf-dir', determine_db_dir()) + \
- WI_InputText('Wallet Filename: ', 'name', 'ikf-name', determine_db_name(), 20) + \
- WI_InputText('<span style="border: 0 dashed;border-bottom-width:1px;" title="Format: \'privkey;label\', label=\'#Reserve\' to make the key a pool one">CSV file path</span>: ', 'file', 'ikf-file', '', 60) + \
- WI_Submit('Import keys', 'IKDiv', 'ikf-close', 'ajaxIK') + \
- WI_CloseButton('IKDiv', 'ikf-close') + \
- WI_ReturnDiv('IKDiv') + \
- WI_FormEnd()
- DTxForm = WI_FormInit('Dump your transactions to a file:', 'DumpTx', 'divformdtx') + \
- WI_InputText('Wallet Directory: ', 'dir', 'dt-dir', determine_db_dir()) + \
- WI_InputText('Wallet Filename: ', 'name', 'dt-name', determine_db_name(), 20) + \
- WI_InputText('Output file: ', 'file', 'dt-file', '') + \
- WI_Submit('Dump tx\'s', 'DTxDiv', 'dt-close', 'ajaxDTx') + \
- WI_CloseButton('DTxDiv', 'dt-close') + \
- WI_ReturnDiv('DTxDiv') + \
- WI_FormEnd()
- prehide_ecdsa=""
- posthide_ecdsa=""
- if 'ecdsa' in missing_dep:
- prehide_ecdsa="<span style='display:none;'>"
- posthide_ecdsa="</span>"
- InfoForm = WI_FormInit('Get some info about one key'+X_if_else(' and sign/verify messages', 'ecdsa' not in missing_dep,'')+':', 'Info', 'divforminfo') + \
- WI_InputText('Key: ', 'key', 'if-key', '', 60) + \
- prehide_ecdsa + WI_InputText('Message: ', 'msg', 'if-msg', '', 30) + posthide_ecdsa + \
- prehide_ecdsa + WI_InputText('Signature: ', 'sig', 'if-sig', '', 30) + posthide_ecdsa + \
- prehide_ecdsa + WI_InputText('Pubkey: ', 'pubkey', 'if-pubkey', '', 30) + posthide_ecdsa + \
- WI_InputText('<span style="border: 0 dashed;border-bottom-width:1px;" title="0 for Bitcoin, 52 for Namecoin, 111 for testnets">Version</span>:', 'vers', 'if-vers', '0', 1) + \
- "Format:<br />" + \
- WI_RadioButton('format', 'reg', 'if-reg', 'CHECKED', ' Regular, base 58') + \
- WI_RadioButton('format', 'hex', 'if-hex', '', ' Hexadecimal, 64 characters long') + \
- "You want:<br />" + \
- WI_RadioButton('i-need', '1', 'if-n-info', 'CHECKED', ' Info') + \
- prehide_ecdsa + WI_RadioButton('i-need', '2', 'if-n-sv', '', ' Sign and verify') + posthide_ecdsa +\
- prehide_ecdsa + WI_RadioButton('i-need', '3', 'if-n-both', '', ' Both') + posthide_ecdsa + \
- WI_Submit('Get info', 'InfoDiv', 'if-close', 'ajaxInfo') + \
- WI_CloseButton('InfoDiv', 'if-close') + \
- WI_ReturnDiv('InfoDiv') + \
- WI_FormEnd()
- ImportForm = WI_FormInit('Import a key into your wallet:', 'Import', 'divformimport') + \
- WI_InputText('Wallet Directory: ', 'dir', 'impf-dir', determine_db_dir(), 30) + \
- WI_InputText('Wallet Filename:', 'name', 'impf-name', determine_db_name(), 20) + \
- WI_InputText('Key:', 'key', 'impf-key', '', 65) + \
- WI_InputText('Label:', 'label', 'impf-label', '') + \
- WI_Checkbox('reserve', 'true', 'impf-reserve', 'onClick="document.getElementById(\'impf-label\').disabled=document.getElementById(\'impf-reserve\').checked"', ' Reserve') + "<br />" + \
- WI_InputText('<span style="border: 0 dashed;border-bottom-width:1px;" title="0 for Bitcoin, 52 for Namecoin, 111 for testnets">Version</span>:', 'vers', 'impf-vers', '0', 1) + \
- "Format:<br />" + \
- WI_Checkbox('format', 'hex', 'impf-hex', '', ' Hexadecimal, instead of base58') + "<br />" + \
- WI_Checkbox('format', 'cry', 'impf-cry', 'hidden=true', '<!-- Crypt-->') + \
- WI_Checkbox('format', 'com', 'impf-com', 'hidden=true', '<!--Compressed key-->') + \
- WI_Submit('Import key', 'ImportDiv', 'impf-close', 'ajaxImport') + \
- WI_CloseButton('ImportDiv', 'impf-close') + \
- WI_ReturnDiv('ImportDiv') + \
- WI_FormEnd()
- # WI_RadioButton('format', 'reg', 'impf-reg', 'CHECKED', ' Regular, base 58') + \
- # WI_RadioButton('format', 'hex', 'impf-hex', '', ' Hexadecimal, 64 characters long') + \
- ImportROForm = WI_FormInit('Import a read-only address (encrypted wallets only):', 'Import', 'divformimportro') + \
- WI_InputText('Wallet Directory: ', 'dir', 'irof-dir', determine_db_dir(), 30) + \
- WI_InputText('Wallet Filename:', 'name', 'irof-name', determine_db_name(), 20) + \
- WI_InputText('Public key (starting with 04): ', 'pub', 'irof-pub', '', 40) + \
- WI_InputText('Label: ', 'label', 'irof-label', '') + \
- WI_Submit('Import address', 'ImportDiv', 'irof-close', 'ajaxImportRO') + \
- WI_CloseButton('ImportRODiv', 'irof-close') + \
- WI_ReturnDiv('ImportRODiv') + \
- WI_FormEnd()
- DeleteForm = WI_FormInit('Delete keys from your wallet:', 'Delete', 'divformdelete') + \
- WI_InputText('Wallet Directory: ', 'dir', 'd-dir', determine_db_dir(), 40) + \
- WI_InputText('Wallet Filename:', 'name', 'd-name', determine_db_name()) + \
- WI_InputText('<span style="border: 0 dashed;border-bottom-width:1px;" title="divided by \'-\'">Keys</span>:', 'key', 'd-key', '', 65) + \
- "Type:<br />" + \
- WI_RadioButton('d-type', 'tx', 'd-r-tx', 'CHECKED', ' Transaction (type "all" in "Keys" to delete them all)') + \
- WI_RadioButton('d-type', 'key', 'd-r-key', '', ' Bitcoin address') + \
- WI_Submit('Delete', 'DeleteDiv', 'd-close', 'ajaxDelete') + \
- WI_CloseButton('DeleteDiv', 'd-close') + \
- WI_ReturnDiv('DeleteDiv') + \
- WI_FormEnd()
- ImportTxForm = WI_FormInit('Import a transaction into your wallet:', 'ImportTx', 'divformimporttx') + \
- WI_InputText('Wallet Directory: ', 'dir', 'it-dir', determine_db_dir(), 40) + \
- WI_InputText('Wallet Filename:', 'name', 'it-name', determine_db_name()) + \
- WI_InputText('Txk:', 'key', 'it-txk', '', 65) + \
- WI_InputText('Txv:', 'label', 'it-txv', '', 65) + \
- WI_Submit('Import', 'ImportTxDiv', 'it-close', 'ajaxImportTx') + \
- WI_CloseButton('ImportTxDiv', 'it-close') + \
- WI_ReturnDiv('ImportTxDiv') + \
- WI_FormEnd()
- BalanceForm = WI_FormInit('Print the balance of a Bitcoin address:', 'Balance', 'divformbalance') + \
- WI_InputText('Key:', 'key', 'bf-key', '', 35) + \
- WI_Submit('Get balance', 'BalanceDiv', 'gb-close', 'ajaxBalance') + \
- WI_CloseButton('BalanceDiv', 'gb-close') + \
- WI_ReturnDiv('BalanceDiv') + \
- WI_FormEnd()
- global CTX_adds, addr_to_keys
- CTX_adds2=CTX_adds.split('|')+addr_to_keys.keys()
- CreateTxForm = WI_FormInit('Create transaction', 'CTX', 'divformctx') + \
- X_if_else("Additional addresses used: " + ', '.join(CTX_adds.split('|'))+"<br /><br />",len(CTX_adds)>0,"No additional addresses used<br /><br />") + \
- listtx_txt(CTX_adds) + \
- WI_FormEnd()
- CreateTxForm2 = WI_FormInit('Check addresses funds', 'ListTransactions', 'divformctx') + \
- WI_InputText('<span style="border: 0 dashed;border-bottom-width:1px;" title="Divided by a |">Addresses</span>: ', 'adds', 'ctx-adds', '', 35) + \
- WI_Submit('Check ', '', '', 'ajaxCTx') + \
- WI_FormEnd()
- Misc = ''
- Javascript = '<script language="javascript" type="text/javascript">interv1=0;\
- totalin=0;\
- totalout=0;\
- \
- function majfee(){\
- document.getElementById("tot_in").innerHTML=(totalin)/100000000;\
- document.getElementById("tot_out").innerHTML=(totalout)/100000000;\
- document.getElementById("tot_fee").innerHTML=(totalin-totalout)/100000000;\
- }\
- \
- function image_showdiv(a){\
- if(document.getElementById(a).style.display!="none")r="http://creation-entreprise.comprendrechoisir.com/img/puce_tab_down.png";\
- else{\
- r="http://creation-entreprise.comprendrechoisir.com/img/puce_tab.png";}\
- \
- return "<img src=\'"+r+"\' />";\
- \
- }\
- function get_radio_value(radioform){\
- var rad_val;\
- for (var i=0; i < radioform.length; i++){\
- if (radioform[i].checked){\
- rad_val = radioform[i].value;\
- }\
- }\
- return rad_val;\
- }' + \
- WI_AjaxFunction('UpdatePyw', 'document.getElementById("uptodate").innerHTML = ajaxRequest.responseText;setTimeout(function() {window.location.reload();}, 2000);', '"/?update=1"', 'document.getElementById("uptodate").innerHTML = "Updating...";') + \
- WI_AjaxFunction('CTx', 'document.getElementById("retour-pyw").innerHTML = ajaxRequest.responseText;', '"/ListTransactions?addresses="+document.getElementById("ctx-adds").value', 'document.getElementById("retour-pyw").innerHTML = "Loading...";') + \
- WI_AjaxFunction('CPP', 'document.getElementById("retour-pyw").innerHTML = ajaxRequest.responseText;', '"/ChangePP?pp="+document.getElementById("cppf-pp").value', 'document.getElementById("retour-pyw").innerHTML = "Loading...";') + \
- WI_AjaxFunction('DW', 'document.getElementById("retour-pyw").innerHTML = ajaxRequest.responseText;', '"/DumpWallet?dir="+document.getElementById("dwf-dir").value+"&name="+document.getElementById("dwf-name").value+"&bal="+document.getElementById("dwf-bal").checked+"&version="+document.getElementById("dwf-vers").value', 'document.getElementById("retour-pyw").innerHTML = "Loading...";') + \
- WI_AjaxFunction('MW', 'document.getElementById("retour-pyw").innerHTML = ajaxRequest.responseText;', '"/MergeWallets?dir1="+document.getElementById("mwf-dir1").value+"&name1="+document.getElementById("mwf-name1").value+"&pass1="+encodeURIComponent(document.getElementById("mwf-pass1").value)+"&dir2="+document.getElementById("mwf-dir2").value+"&name2="+document.getElementById("mwf-name2").value+"&pass2="+encodeURIComponent(document.getElementById("mwf-pass2").value)+"&dirm="+document.getElementById("mwf-dirm").value+"&namem="+document.getElementById("mwf-namem").value+"&passm1="+encodeURIComponent(document.getElementById("mwf-passm1").value)+"&passm2="+encodeURIComponent(document.getElementById("mwf-passm2").value)+""', 'document.getElementById("retour-pyw").innerHTML = "Merging wallets... This may take a few minutes.";interv1=setInterval(ajaxUpdateMW,300);') + \
- WI_AjaxFunction('UpdateMW', 'if(ajaxRequest.responseText.length>0){document.getElementById("retour-pyw").innerHTML = ajaxRequest.responseText;}else{clearInterval(interv1);}', '"/Others?action=update_mwdiv"', '') + \
- WI_AjaxFunction('DK', 'document.getElementById("retour-pyw").innerHTML = ajaxRequest.responseText;', '"/DumpWallet?dir="+document.getElementById("dkf-dir").value+"&filetw="+document.getElementById("dkf-file").value+"&keys="+document.getElementById("dkf-keys").value+"&bal="+document.getElementById("dkf-bal").checked+"&name="+document.getElementById("dkf-name").value+"&version="+document.getElementById("dkf-vers").value', 'document.getElementById("retour-pyw").innerHTML = "Loading...";') + \
- WI_AjaxFunction('IK', 'document.getElementById("retour-pyw").innerHTML = ajaxRequest.responseText;', '"/Import?dir="+document.getElementById("ikf-dir").value+"&file="+document.getElementById("ikf-file").value+"&name="+document.getElementById("ikf-name").value', 'document.getElementById("retour-pyw").innerHTML = "Loading...";') + \
- WI_AjaxFunction('DTx', 'document.getElementById("retour-pyw").innerHTML = ajaxRequest.responseText;', '"/DumpTx?dir="+document.getElementById("dt-dir").value+"&name="+document.getElementById("dt-name").value+"&file="+document.getElementById("dt-file").value', 'document.getElementById("retour-pyw").innerHTML = "Loading...";') + \
- WI_AjaxFunction('Info', 'document.getElementById("retour-pyw").innerHTML = ajaxRequest.responseText;', '"/Info?key="+document.getElementById("if-key").value+"&msg="+document.getElementById("if-msg").value+"&pubkey="+document.getElementById("if-pubkey").value+"&sig="+document.getElementById("if-sig").value+"&vers="+document.getElementById("if-vers").value+"&format="+(document.getElementById("if-hex").checked?"hex":"reg")+"&need="+get_radio_value(document.getElementsByName("i-need"))', 'document.getElementById("retour-pyw").innerHTML = "Loading...";') + \
- WI_AjaxFunction('Import', 'document.getElementById("retour-pyw").innerHTML = ajaxRequest.responseText;', '"/Import?dir="+document.getElementById("impf-dir").value+"&name="+document.getElementById("impf-name").value+"&key="+document.getElementById("impf-key").value+"&label="+document.getElementById("impf-label").value+"&vers="+document.getElementById("impf-vers").value+"&com="+document.getElementById("impf-com").checked+"&cry="+document.getElementById("impf-cry").checked+"&format="+document.getElementById("impf-hex").checked+(document.getElementById("impf-reserve").checked?"&reserve=1":"")', 'document.getElementById("retour-pyw").innerHTML = "Loading...";') + \
- WI_AjaxFunction('ImportRO', 'document.getElementById("retour-pyw").innerHTML = ajaxRequest.responseText;', '"/Import?dir="+document.getElementById("irof-dir").value+"&name="+document.getElementById("irof-name").value+"&pub="+document.getElementById("irof-pub").value+"&label="+document.getElementById("irof-label").value', 'document.getElementById("retour-pyw").innerHTML = "Loading...";') + \
- WI_AjaxFunction('Balance', 'document.getElementById("retour-pyw").innerHTML = "Balance of " + document.getElementById("bf-key").value + ": " + ajaxRequest.responseText;', '"/Balance?key="+document.getElementById("bf-key").value', 'document.getElementById("retour-pyw").innerHTML = "Loading...";') + \
- WI_AjaxFunction('Delete', 'document.getElementById("retour-pyw").innerHTML = ajaxRequest.responseText;', '"/Delete?dir="+document.getElementById("d-dir").value+"&name="+document.getElementById("d-name").value+"&keydel="+document.getElementById("d-key").value+"&typedel="+get_radio_value(document.getElementsByName("d-type"))', 'document.getElementById("retour-pyw").innerHTML = "Loading...";') + \
- WI_AjaxFunction('ImportTx', 'document.getElementById("retour-pyw").innerHTML = ajaxRequest.responseText;', '"/ImportTx?dir="+document.getElementById("it-dir").value+"&name="+document.getElementById("it-name").value+"&txk="+document.getElementById("it-txk").value+"&txv="+document.getElementById("it-txv").value', 'document.getElementById("retour-pyw").innerHTML = "Loading...";') + \
- '</script>'
- # WI_AjaxFunction('Import', 'document.getElementById("ImportDiv").innerHTML = ajaxRequest.responseText;', '"/Import?dir="+document.getElementById("impf-dir").value+"&name="+document.getElementById("impf-name").value+"&key="+document.getElementById("impf-key").value+"&label="+document.getElementById("impf-label").value+"&vers="+document.getElementById("impf-vers").value+"&format="+(document.getElementById("impf-hex").checked?"hex":"reg")+(document.getElementById("impf-reserve").checked?"&reserve=1":"")', 'document.getElementById("ImportDiv").innerHTML = "Loading...";') + \
- page = '<html><head><title>Pywallet Web Interface</title></head><body>' + header + Javascript + CPPForm + DWForm + MWForm + DKForm + IKForm + DTxForm + InfoForm + ImportForm + ImportTxForm + DeleteForm + BalanceForm + Misc + '</body></html>'
- AboutPage="\
- Pywallet is a tool to manage wallet files, developped by jackjack. <a href='https://bitcointalk.org/index.php?topic=34028'>Support thread</a> is on bitcointalk.<br />\
- <br />\
- To support pywallet's development or if you think it's worth something, you can send anything you want to 1AQDfx22pKGgXnUZFL1e4UKos3QqvRzNh5.\
- \
- <br /><br /><br /><br /><b>Dependencies:</b><br />\
- \
- ecdsa: "+dep_text_aboutpage('ecdsa' in missing_dep)+"\
- \
- <br /><br /><b>Pywallet path:</b> "+pyw_path+"/"+pyw_filename+"\
- "
- return html_wui(Javascript + \
- WI_Endiv(DWForm+DKForm+DTxForm, 'DumpPage', 'Dump', '') + \
- WI_Endiv(ImportForm+IKForm+MWForm+ImportTxForm+ImportROForm,'ImportPage', 'Import', "Don't forget to close Bitcoin when you modify your wallet", True) + \
- WI_Endiv(DeleteForm,'DeletePage', 'Delete', "Don't forget to close Bitcoin when you modify your wallet", True) + \
- WI_Endiv(CPPForm,'PassphrasePage', 'Change passphrase', '', True) + \
- WI_Endiv(InfoForm+BalanceForm,'InfoPage', 'Info', '', True) + \
- WI_Endiv(CreateTxForm2+CreateTxForm,'TxPage', 'Manage transactions', 'You can here create your own transactions. <br />By default, the unspent transactions from addresses previously dumped are shown, but you can add other addresses to check.<br />You can\'t create a transaction if you didn\'t dump the private keys of each input beforehand.', True) + \
- WI_Endiv(AboutPage,'AboutPage','About','', True)
- ,check_version_text
- )
- return page
- def getChild(self, name, request):
- if name == '':
- return self
- else:
- if name in VIEWS.keys():
- return resource.Resource.getChild(self, name, request)
- else:
- return WI404()
- class WIDumpWallet(resource.Resource):
- def render_GET(self, request):
- try:
- wdir=request.args['dir'][0]
- wname=request.args['name'][0]
- version = int(request.args['version'][0])
- log.msg('Wallet Dir: %s' %(wdir))
- log.msg('Wallet Name: %s' %(wname))
- if not os.path.isfile(wdir+"/"+wname):
- return '%s/%s doesn\'t exist'%(wdir, wname)
- try:
- bal=request.args['bal'][0]=='true'
- except:
- bal=false
- read_wallet(json_db, create_env(wdir), wname, True, True, "", bal, version)
- # print wdir
- # print wname
- # print json_db #json.dumps(json_db, sort_keys=True, indent=4)
- try:
- kfile=request.args['filetw'][0]
- kkeys=request.args['keys'][0]
- # print kkeys.split(',')
- reteak=export_all_keys(json_db, kkeys.split(','), kfile)
- return 'File'+X_if_else("",reteak," not")+' written'
- except:
- return 'Wallet: %s/%s<br />Dump:<pre>%s</pre>'%(wdir, wname, json.dumps(json_db, sort_keys=True, indent=4))
- except:
- log.err()
- return 'Error in dump page'
- def render_POST(self, request):
- return self.render_GET(request)
- class WIDumpTx(resource.Resource):
- def render_GET(self, request):
- try:
- wdir=request.args['dir'][0]
- wname=request.args['name'][0]
- jsonfile=request.args['file'][0]
- log.msg('Wallet Dir: %s' %(wdir))
- log.msg('Wallet Name: %s' %(wname))
- if not os.path.isfile(wdir+"/"+wname):
- return '%s/%s doesn\'t exist'%(wdir, wname)
- if os.path.isfile(jsonfile):
- return '%s exists'%(jsonfile)
- read_wallet(json_db, create_env(wdir), wname, True, True, "", None)
- write_jsonfile(jsonfile, json_db['tx'])
- return 'Wallet: %s/%s<br />Transations dumped in %s'%(wdir, wname, jsonfile)
- except:
- log.err()
- return 'Error in dumptx page'
- def render_POST(self, request):
- return self.render_GET(request)
- class WIMergeWallets(resource.Resource):
- def render_GET(self, request):
- try:
- dir1=request.args['dir1'][0]
- name1=request.args['name1'][0]
- pass1=request.args['pass1'][0]
- dir2=request.args['dir2'][0]
- name2=request.args['name2'][0]
- pass2=request.args['pass2'][0]
- dirm=request.args['dirm'][0]
- namem=request.args['namem'][0]
- passm1=request.args['passm1'][0]
- passm2=request.args['passm2'][0]
- if passm1!=passm2:
- return 'The passphrases for the merged wallet don\'t match. Aborted.'
- r=merge_wallets(dir1, name1, dir2, name2, dirm, namem, pass1, pass2, passm1)
- if r[0]:
- return "Merging in progress..."
- else:
- return r[1]
- return ret
- except:
- log.err()
- return 'Error in mergewallets page'
- def render_POST(self, request):
- return self.render_GET(request)
- class WIChangePP(resource.Resource):
- def render_GET(self, request):
- try:
- global passphrase
- passphrase=request.args['pp'][0]
- return 'Done'
- except:
- log.err()
- return 'Error while changing passphrase'
- def render_POST(self, request):
- return self.render_GET(request)
- class WIOthers(resource.Resource):
- def render_GET(self, request):
- try:
- global passphrase
- global global_merging_message
- action=request.args['action'][0]
- if action=="update_mwdiv":
- ret=global_merging_message[0]
- global_merging_message[0]=global_merging_message[1]
- global_merging_message[1]=""
- return ret
- return 'Done'
- except:
- log.err()
- return 'Error while WIOthers'
- def render_POST(self, request):
- return self.render_GET(request)
- class WIBalance(resource.Resource):
- def render_GET(self, request):
- try:
- return "%s"%str(balance(balance_site, request.args['key'][0]).encode('utf-8'))
- except:
- log.err()
- return 'Error in balance page'
- def render_POST(self, request):
- return self.render_GET(request)
- class WIDelete(resource.Resource):
- def render_GET(self, request):
- try:
- wdir=request.args['dir'][0]
- wname=request.args['name'][0]
- keydel=request.args['keydel'][0]
- typedel=request.args['typedel'][0]
- db_env = create_env(wdir)
- if not os.path.isfile(wdir+"/"+wname):
- return '%s/%s doesn\'t exist'%(wdir, wname)
- deleted_items = delete_from_wallet(db_env, wname, typedel, keydel.split('-'))
- return "%s:%s has been successfully deleted from %s/%s, resulting in %d deleted item%s"%(typedel, keydel, wdir, wname, deleted_items, iais(deleted_items))
- except:
- log.err()
- return 'Error in delete page'
- def render_POST(self, request):
- return self.render_GET(request)
- def message_to_hash(msg, msgIsHex=False):
- str = ""
- # str += '04%064x%064x'%(pubkey.point.x(), pubkey.point.y())
- # str += "Padding text - "
- str += msg
- if msgIsHex:
- str = str.decode('hex')
- hash = Hash(str)
- return hash
- def sign_message(secret, msg, msgIsHex=False):
- k = KEY()
- k.generate(secret)
- return k.sign(message_to_hash(msg, msgIsHex))
- def verify_message_signature(pubkey, sign, msg, msgIsHex=False):
- k = KEY()
- k.set_pubkey(pubkey.decode('hex'))
- return k.verify(message_to_hash(msg, msgIsHex), sign.decode('hex'))
- OP_DUP = 118;
- OP_HASH160 = 169;
- OP_EQUALVERIFY = 136;
- OP_CHECKSIG = 172;
- XOP_DUP = "%02x"%OP_DUP;
- XOP_HASH160 = "%02x"%OP_HASH160;
- XOP_EQUALVERIFY = "%02x"%OP_EQUALVERIFY;
- XOP_CHECKSIG = "%02x"%OP_CHECKSIG;
- BTC = 1e8
- def ct(l_prevh, l_prevn, l_prevsig, l_prevpubkey, l_value_out, l_pubkey_out, is_msg_to_sign=-1, oldScriptPubkey=""):
- scriptSig = True
- if is_msg_to_sign is not -1:
- scriptSig = False
- index = is_msg_to_sign
- ret = ""
- ret += inverse_str("%08x"%1)
- nvin = len(l_prevh)
- ret += "%02x"%nvin
- for i in range(nvin):
- txin_ret = ""
- txin_ret2 = ""
- txin_ret += inverse_str(l_prevh[i])
- txin_ret += inverse_str("%08x"%l_prevn[i])
- if scriptSig:
- txin_ret2 += "%02x"%(1+len(l_prevsig[i])/2)
- txin_ret2 += l_prevsig[i]
- txin_ret2 += "01"
- txin_ret2 += "%02x"%(len(l_prevpubkey[i])/2)
- txin_ret2 += l_prevpubkey[i]
- txin_ret += "%02x"%(len(txin_ret2)/2)
- txin_ret += txin_ret2
- elif index == i:
- txin_ret += "%02x"%(len(oldScriptPubkey)/2)
- txin_ret += oldScriptPubkey
- else:
- txin_ret += "00"
- ret += txin_ret
- ret += "ffffffff"
- nvout = len(l_value_out)
- ret += "%02x"%nvout
- for i in range(nvout):
- txout_ret = ""
- txout_ret += inverse_str("%016x"%(l_value_out[i]))
- txout_ret += "%02x"%(len(l_pubkey_out[i])/2+5)
- txout_ret += "%02x"%OP_DUP
- txout_ret += "%02x"%OP_HASH160
- txout_ret += "%02x"%(len(l_pubkey_out[i])/2)
- txout_ret += l_pubkey_out[i]
- txout_ret += "%02x"%OP_EQUALVERIFY
- txout_ret += "%02x"%OP_CHECKSIG
- ret += txout_ret
- ret += "00000000"
- if not scriptSig:
- ret += "01000000"
- return ret
- def create_transaction(secret_key, hashes_txin, indexes_txin, pubkey_txin, prevScriptPubKey, amounts_txout, scriptPubkey):
- li1 = len(secret_key)
- li2 = len(hashes_txin)
- li3 = len(indexes_txin)
- li4 = len(pubkey_txin)
- li5 = len(prevScriptPubKey)
- if li1 != li2 or li2 != li3 or li3 != li4 or li4 != li5:
- print("Error in the number of tx inputs")
- exit(0)
- lo1 = len(amounts_txout)
- lo2 = len(scriptPubkey)
- if lo1 != lo2:
- print("Error in the number of tx outputs")
- exit(0)
- sig_txin = []
- i=0
- for cpt in hashes_txin:
- sig_txin.append(sign_message(secret_key[i].decode('hex'), ct(hashes_txin, indexes_txin, sig_txin, pubkey_txin, amounts_txout, scriptPubkey, i, prevScriptPubKey[i]), True)+"01")
- i+=1
- tx = ct(hashes_txin, indexes_txin, sig_txin, pubkey_txin, amounts_txout, scriptPubkey)
- hashtx = Hash(tx.decode('hex')).encode('hex')
- for i in range(len(sig_txin)):
- try:
- verify_message_signature(pubkey_txin[i], sig_txin[i][:-2], ct(hashes_txin, indexes_txin, sig_txin, pubkey_txin, amounts_txout, scriptPubkey, i, prevScriptPubKey[i]), True)
- print("sig %2d: verif ok"%i)
- except:
- print("sig %2d: verif error"%i)
- exit(0)
- # tx += end_of_wallettx([], int(time.time()))
- # return [inverse_str(hashtx), "027478" + hashtx, tx]
- return [inverse_str(hashtx), "", tx]
- def inverse_str(string):
- ret = ""
- for i in range(len(string)/2):
- ret += string[len(string)-2-2*i];
- ret += string[len(string)-2-2*i+1];
- return ret
- def read_table(table, beg, end):
- rows = table.split(beg)
- for i in range(len(rows)):
- rows[i] = rows[i].split(end)[0]
- return rows
- def read_blockexplorer_table(table):
- cell = []
- rows = read_table(table, '<tr>', '</tr>')
- for i in range(len(rows)):
- cell.append(read_table(rows[i], '<td>', '</td>'))
- del cell[i][0]
- del cell[0]
- del cell[0]
- return cell
- txin_amounts = {}
- def bc_address_to_available_tx(address, testnet=False):
- TN=""
- if testnet:
- TN="testnet"
- blockexplorer_url = "http://blockexplorer.com/"+TN+"/address/"
- ret = ""
- txin = []
- txin_no = {}
- global txin_amounts
- txout = []
- balance = 0
- txin_is_used = {}
- page = urllib.urlopen("%s/%s" % (blockexplorer_url, address))
- try:
- table = page.read().split('<table class="txtable">')[1]
- table = table.split("</table>")[0]
- except:
- return {address:[]}
- cell = read_blockexplorer_table(table)
- for i in range(len(cell)):
- txhash = read_table(cell[i][0], '/tx/', '#')[1]
- post_hash = read_table(cell[i][0], '#', '">')[1]
- io = post_hash[0]
- no_tx = post_hash[1:]
- if io in 'i':
- txout.append([txhash, post_hash])
- else:
- txin.append(txhash+no_tx)
- txin_no[txhash+no_tx] = post_hash[1:]
- txin_is_used[txhash+no_tx] = 0
- #hashblock = read_table(cell[i][1], '/block/', '">')[1]
- #blocknumber = read_table(cell[i][1], 'Block ', '</a>')[1]
- txin_amounts[txhash+no_tx] = round(float(cell[i][2]), 8)
- # if cell[i][3][:4] in 'Sent' and io in 'o':
- # print(cell[i][3][:4])
- # print(io)
- # return 'error'
- # if cell[i][3][:4] in 'Rece' and io in 'i':
- # print(cell[i][3][:4])
- # print(io)
- # return 'error'
- balance = round(float(cell[i][5]), 8)
- for tx in txout:
- pagetx = urllib.urlopen("http://blockexplorer.com/"+TN+"/tx/"+tx[0])
- table_in = pagetx.read().split('<a name="outputs">Outputs</a>')[0].split('<table class="txtable">')[1].split("</table>")[0]
- cell = read_blockexplorer_table(table_in)
- for i in range(len(cell)):
- txhash = read_table(cell[i][0], '/tx/', '#')[1]
- no_tx = read_table(cell[i][0], '#', '">')[1][1:]
- if txhash+no_tx in txin:
- txin_is_used[txhash+no_tx] = 1
- ret = []
- for tx in txin:
- if not txin_is_used[tx]:
- ret.append([tx,txin_amounts[tx],txin_no[tx]])
- return {address : ret}
- def write_avtx(list_avtx, testnet=False):
- TN=""
- if testnet:
- TN="testnet"
- gret = "<table border=1>"
- for add in list_avtx:
- notnull = False
- try:
- hexsec = " -> " + bc_address_to_sec[add]
- except:
- hexsec = ""
- ret = '<tr><td colspan=3 align="center" rowspan=1><a href="http://blockexplorer.com/'+TN+'/address/' +add + '">' + add + "</a>" + hexsec + '</td></tr>'
- a = list_avtx[add]
- for array in a:
- notnull = True
- no_tx = array[0][64:]
- array[0] = array[0][:64]
- link = "http://blockexplorer.com/"+TN+"/rawtx/"+array[0]
- pagetx = urllib.urlopen(link)
- ScriptPubkey = str(json.loads(pagetx.read())['out'][int(array[2])]['scriptPubKey'])
- # ret += '<a href="http://blockexplorer.com/tx/' +array[0] + '">' + array[0] + "#" + no_tx + "</a>: " + str(array[1]) + " & " + ScriptPubkey + "<br />"
- ret += '<tr><td><a href="http://blockexplorer.com/'+TN+'/tx/' +array[0] + '#' + no_tx + '">' + array[0] + "</a></td><td>" + str(array[1]) + "</td><td>" + ScriptPubkey + "</td></tr>"
- ret+="<tr><td colspan=3></td></tr>"
- # ret += "<br />" + "<br />"
- if notnull is False:
- ret = ""
- gret += ret
- gret=gret[:-len("<tr><td colspan=3></td></tr>")]
- return gret+"</table>"
- ct_txin = []
- ct_txout = []
- empty_txin={'hash':'', 'index':'', 'sig':'##', 'pubkey':'', 'oldscript':'', 'addr':''}
- empty_txout={'amount':'', 'script':''}
- class tx():
- ins=[]
- outs=[]
- tosign=False
- def hashtypeone(index,script):
- global empty_txin
- for i in range(len(ins)):
- self.ins[i]=empty_txin
- self.ins[index]['pubkey']=""
- self.ins[index]['oldscript']=s
- self.tosign=True
- def copy():
- r=tx()
- r.ins=self.ins[:]
- r.outs=self.outs[:]
- return r
- def sign(n=-1):
- if n==-1:
- for i in range(len(ins)):
- self.sign(i)
- return "done"
- global json_db
- txcopy=self.copy()
- txcopy.hashtypeone(i, self.ins[n]['oldscript'])
- sec=''
- for k in json_db['keys']:
- if k['addr']==self.ins[n]['addr'] and 'hexsec' in k:
- sec=k['hexsec']
- if sec=='':
- print "priv key not found (addr:"+self.ins[n]['addr']+")"
- return ""
- self.ins[n]['sig']=sign_message(sec.decode('hex'), txcopy.get_tx(), True)
- def ser():
- r={}
- r['ins']=self.ins
- r['outs']=self.outs
- r['tosign']=self.tosign
- return json.dumps(r)
- def unser(r):
- s=json.loads(r)
- self.ins=s['ins']
- self.outs=s['outs']
- self.tosign=s['tosign']
- def get_tx():
- r=''
- ret += inverse_str("%08x"%1)
- ret += "%02x"%len(self.ins)
- for i in range(len(self.ins)):
- txin=self.ins[i]
- ret += inverse_str(txin['hash'])
- ret += inverse_str("%08x"%txin['index'])
- if txin['pubkey']!="":
- tmp += "%02x"%(1+len(txin['sig'])/2)
- tmp += txin['sig']
- tmp += "01"
- tmp += "%02x"%(len(txin['pubkey'])/2)
- tmp += txin['pubkey']
- ret += "%02x"%(len(tmp)/2)
- ret += tmp
- elif txin['oldscript']!="":
- ret += "%02x"%(len(txin['oldscript'])/2)
- ret += txin['oldscript']
- else:
- ret += "00"
- ret += "ffffffff"
- ret += "%02x"%len(self.outs)
- for i in range(len(self.outs)):
- txout=self.outs[i]
- ret += inverse_str("%016x"%(txout['amount']))
- if txout['script'][:2]=='s:': #script
- script=txout['script'][:2]
- ret += "%02x"%(len(script)/2)
- ret += script
- else: #address
- ret += "%02x"%(len(txout['script'])/2+5)
- ret += "%02x"%OP_DUP
- ret += "%02x"%OP_HASH160
- ret += "%02x"%(len(txout['script'])/2)
- ret += txout['script']
- ret += "%02x"%OP_EQUALVERIFY
- ret += "%02x"%OP_CHECKSIG
- ret += "00000000"
- if not self.tosign:
- ret += "01000000"
- return ret
- def listtx_txt(adds):
- untx_site="http://blockchain.info/unspent?active="
- ret=''
- table="""<form action='CT' method=post><table border=1>"""
- utx=untx_site+adds
- try:
- utxs=json.loads(urllib.urlopen(utx).read())["unspent_outputs"]
- except:
- return "No inputs"
- table+="<tr>\
- <td>Use</td>\
- <td>Tx hash</td>\
- <td>Script</td>\
- <td>Amount</td>\
- </tr>"
- for tx in utxs:
- txhash=str(tx["tx_hash"]).decode('hex')[::-1].encode('hex')
- txn=int(tx["tx_output_n"])
- txscript=str(tx["script"])
- txvalue=int(tx["value"])
- table+="<tr>"
- table+="<td>\
- <input type=checkbox onchange='totalin+=(this.checked?1:-1)*"+str(txvalue)+";majfee();' value='' defaultChecked=false name='txin_"+txhash+"_use_"+random_string(6)+"' >\
- <input type=hidden name='txin_"+txhash+"_h' value='"+str(txhash)+"'>\
- <input type=hidden name='txin_"+txhash+"_n' value='"+str(txn)+"'>\
- <input type=hidden name='txin_"+txhash+"_script' value='"+txscript+"'>\
- <input type=hidden name='txin_"+txhash+"_amin' value='"+str(txvalue)+"'>\
- </td>"
- # table+="<td>"+a+"</td>"
- table+="<td>"+txhash+"</td>"
- table+="<!--td>"+str(txn)+"</td-->"
- if txscript[:6]+txscript[-4:]=="76a91488ac":
- table+="<td>Address "+hash_160_to_bc_address(txscript[6:-4].decode('hex'))+"</td>"
- table+="<input type=hidden name='txin_"+txhash+"_add' value='"+hash_160_to_bc_address(txscript[6:-4].decode('hex'))+"'>"
- else:
- table+="<td>"+txscript+"</td>"
- table+="<td>"+str(txvalue/1e8)+"</td>"
- table+="</tr>\n"
- table+="</table>"
- ret+=table
- ret+="<span id='tot_in'>0</span> BTC (inputs) - <span id='tot_out'>0</span> BTC (outputs) = <span id='tot_fee'>0</span> BTC (fee)<br /><br />"
- txouts=""
- nbretxouts=30
- unserouts=["parseFloat(document.getElementById(\"txout_am_"+str(i)+"\").value)" for i in range(nbretxouts)]
- serouts="+".join(unserouts)
- for i in range(nbretxouts):
- txouts+="<span id='txout_"+str(i)+"' style='display:"+X_if_else("inline",i<3,"none")+";' >\
- Amount: <input value='0' onchange='totalout=Math.round(("+serouts+")*100000000);majfee();' name='txout_am_"+str(i)+"' id='txout_am_"+str(i)+"' /> Script: <input name='txout_script_"+str(i)+"' />\
- \
- \
- \
- <br />"+X_if_else("<input type=button id='button_txout_"+str(i)+"' value='Add a txout' onclick='document.getElementById(\"txout_"+str(i+X_if_else(0,i==nbretxouts-1,1))+"\").style.display=\"block\";document.getElementById(\"button_txout_"+str(i)+"\").style.display=\"none\";' />",i>=2,"")+"</span>"
- ret+=txouts
- ret+="<input type=submit value='Create' /></form>"
- # ret+=WI_Submit('Create', '', '', 'ajaxCTX2')
- return ret
- if 'twisted' not in missing_dep:
- class WIInfo(resource.Resource):
- def render_GET(self, request):
- global addrtype
- try:
- sec = request.args['key'][0]
- format = request.args['format'][0]
- addrtype = int(request.args['vers'][0])
- msgIsHex = False
- msgIsFile = False
- try:
- msg = request.args['msg'][0]
- if msg[0:4] == "Hex:":
- msg = msg[4:]
- msgIsHex = True
- elif msg[0:5] == "File:":
- msg = msg[5:]
- if not os.path.isfile(msg):
- return '%s doesn\'t exist'%(msg)
- filin = open(msg, 'r')
- msg = filin.read()
- filin.close()
- msgIsFile = True
- sig = request.args['sig'][0]
- pubkey = request.args['pubkey'][0]
- need = int(request.args['need'][0])
- except:
- need = 1
- ret = ""
- if sec is not '':
- if format in 'reg':
- pkey = regenerate_key(sec)
- compressed = is_compressed(sec)
- elif len(sec) == 64:
- pkey = EC_KEY(str_to_long(sec.decode('hex')))
- compressed = False
- elif len(sec) == 66:
- pkey = EC_KEY(str_to_long(sec[:-2].decode('hex')))
- compressed = True
- else:
- return "Hexadecimal private keys must be 64 characters long"
- if not pkey:
- return "Bad private key"
- secret = GetSecret(pkey)
- private_key = GetPrivKey(pkey, compressed)
- public_key = GetPubKey(pkey, compressed)
- addr = public_key_to_bc_address(public_key)
- if need & 1:
- ret += "Address (%s): %s<br />"%(aversions[addrtype], addr)
- ret += "Privkey (%s): %s<br />"%(aversions[addrtype], SecretToASecret(secret, compressed))
- ret += "Hexprivkey: %s<br />"%(secret.encode('hex'))
- ret += "Hash160: %s<br />"%(bc_address_to_hash_160(addr).encode('hex'))
- # ret += "Inverted hexprivkey: %s<br />"%(inversetxid(secret.encode('hex')))
- ret += "Pubkey: <span style='font-size:60%%;'>04%.64x%.64x</span><br />"%(pkey.pubkey.point.x(), pkey.pubkey.point.y())
- ret += X_if_else('<br /><br /><b>Beware, 0x%s is equivalent to 0x%.33x</b>'%(secret.encode('hex'), int(secret.encode('hex'), 16)-_r), (int(secret.encode('hex'), 16)>_r), '')
- if 'ecdsa' not in missing_dep and need & 2:
- if sec is not '' and msg is not '':
- if need & 1:
- ret += "<br />"
- ret += "Signature of '%s' by %s: <span style='font-size:60%%;'>%s</span><br />Pubkey: <span style='font-size:60%%;'>04%.64x%.64x</span><br />"%(X_if_else(msg, not msgIsFile, request.args['msg'][0]), addr, sign_message(secret, msg, msgIsHex), pkey.pubkey.point.x(), pkey.pubkey.point.y())
- if sig is not '' and msg is not '' and pubkey is not '':
- addr = public_key_to_bc_address(pubkey.decode('hex'))
- try:
- verify_message_signature(pubkey, sig, msg, msgIsHex)
- ret += "<br /><span style='color:#005500;'>Signature of '%s' by %s is <span style='font-size:60%%;'>%s</span></span><br />"%(X_if_else(msg, not msgIsFile, request.args['msg'][0]), addr, sig)
- except:
- ret += "<br /><span style='color:#990000;'>Signature of '%s' by %s is NOT <span style='font-size:60%%;'>%s</span></span><br />"%(X_if_else(msg, not msgIsFile, request.args['msg'][0]), addr, sig)
- return ret
- except:
- log.err()
- return 'Error in info page'
- def render_POST(self, request):
- return self.render_GET(request)
- class WIImportTx(resource.Resource):
- def render_GET(self, request):
- global addrtype
- try:
- wdir=request.args['dir'][0]
- wname=request.args['name'][0]
- txk=request.args['txk'][0]
- txv=request.args['txv'][0]
- d = {}
- if not os.path.isfile(wdir+"/"+wname):
- return '%s/%s doesn\'t exist'%(wdir, wname)
- if txk not in "file":
- dd = [{'tx_k':txk, 'tx_v':txv}]
- else:
- if not os.path.isfile(txv):
- return '%s doesn\'t exist'%(txv)
- dd = read_jsonfile(txv)
- db_env = create_env(wdir)
- read_wallet(json_db, db_env, wname, True, True, "", None)
- db = open_wallet(db_env, wname, writable=True)
- i=0
- for tx in dd:
- d = {'txi':tx['tx_k'], 'txv':tx['tx_v']}
- print(d)
- update_wallet(db, "tx", d)
- i+=1
- db.close()
- return "<pre>hash: %s\n%d transaction%s imported in %s/%s<pre>" % (inverse_str(txk[6:]), i, iais(i), wdir, wname)
- except:
- log.err()
- return 'Error in importtx page'
- def render_POST(self, request):
- return self.render_GET(request)
- class WIQuit(resource.Resource):
- def render_GET(self, request):
- reactor.stop()
- def render_POST(self, request):
- return self.render_GET(request)
- class WICTListTx(resource.Resource):
- def render_GET(self, request):
- global CTX_adds
- try:
- adds=request.args['addresses'][0]
- CTX_adds=adds
- except:
- return "You must provide at least one address to see the transaction you can spend. Divided by |"
- ret=""
- ret=listtx_txt(adds)
- return "Refresh to display available incoming transactions"
- def render_POST(self, request):
- return self.render_GET(request)
- class WICT(resource.Resource):
- def render_GET(self, request):
- #CT?sec=s&hashesin=h&indexes=1&pubkeys=p&prevspk=r&amounts=2453628&spk=spk#tbend
- global txin_amounts, json_db
- display = ""
- try:
- testnet=request.args['testnet'][0]
- TN="testnet"
- except:
- TN=""
- try:
- list_sec, list_hin, list_indexes, list_pubs, list_scriptin, list_outam, list_scriptout, list_amin = [[] for i in range(8)]
- txin_to_use=[]
- txouts_nos=[]
- txouts_not_empty=[]
- for i in request.args:
- if i[:4]=='txin' and i[-10:-7]=='use':
- txin_to_use.append(i.split('_')[1])
- if i[:4]=='txou' and i.split('_')[2] not in txouts_nos:
- p=i.split('_')[1]
- no=i.split('_')[2]
- txouts_nos.append(no)
- for no in txouts_nos:
- if request.args['txout_am_'+no][0]!='' and request.args['txout_am_'+no][0]!='0':
- list_outam.append(request.args['txout_am_'+no][0])
- list_scriptout.append(request.args['txout_script_'+no][0])
- global addr_to_keys
- for h in txin_to_use:
- if request.args['txin_'+h+'_add'][0] not in addr_to_keys.keys():
- return "<br />No private key for "+request.args['txin_'+h+'_add'][0]+", please dump a wallet containing this address<br /><br /><a href='http://localhost:"+str(webport)+"'>Return to Pywallet</a>"
- list_hin.append(h)
- list_indexes.append(request.args['txin_'+h+'_n'][0])
- list_scriptin.append(request.args['txin_'+h+'_script'][0])
- list_sec.append(addr_to_keys[request.args['txin_'+h+'_add'][0]][0])
- list_pubs.append(addr_to_keys[request.args['txin_'+h+'_add'][0]][1])
- list_amin.append(request.args['txin_'+h+'_amin'][0])
- sec=",".join(list_sec)
- hashesin=",".join(list_hin)
- indexes=",".join(list_indexes)
- pubkeys=",".join(list_pubs)
- prevspk=",".join(list_scriptin)
- amins=",".join(list_amin)
- amounts=",".join(list_outam)
- spk=",".join(list_scriptout)
- except:
- display += "error"
- return display
- secret_key = sec.split(',')
- hashes_txin = hashesin.split(',')
- indexes_txin = indexes.split(',')
- for i in range(len(indexes_txin)):
- indexes_txin[i] = int(indexes_txin[i])
- pubkey_txin = pubkeys.split(',')
- am_txin = amins.split(',')
- prevScriptPubKey = prevspk.split(',')
- amounts_txout = amounts.split(',')
- for i in range(len(amounts_txout)):
- amounts_txout[i] = int(1e8*float(amounts_txout[i]))
- spk_txout = spk.split(',')
- tx = create_transaction(secret_key, hashes_txin, indexes_txin, pubkey_txin, prevScriptPubKey, amounts_txout, spk_txout)
- display += "Inputs: (go to <a href='CTTest'>CTTest</a> before)<br />"
- sum_in = 0
- for i in range(len(hashes_txin)):
- try:
- # ain = txin_amounts[hashes_txin[i] + ("%d"%indexes_txin[i])]
- ain=int(am_txin[i])/1e8
- aaa = ", %.8f BTC"%ain
- sum_in += ain
- except:
- aaa = ""
- display += ('%d: <a href="http://blockexplorer.com/'+TN+'/tx/%s#o%d">%s #%d</a>%s<br />')%(i, hashes_txin[i], indexes_txin[i], hashes_txin[i], indexes_txin[i], aaa)
- display += "<br /><br />Outputs:<br />"
- sum_out = 0
- for i in range(len(spk_txout)):
- sum_out += amounts_txout[i]/BTC
- display += '%.8f BTC to %s<br />'%(amounts_txout[i]/BTC, hash_160_to_bc_address(spk_txout[i].decode('hex')))
- display += "<br />"
- display += "<br />"
- display += "In: %.8f BTC"%sum_in
- display += "<br />"
- display += "Out: %.8f BTC"%sum_out
- display += "<br />"
- display += "Fee: %.8f BTC"%(sum_in-sum_out)
- display += "<br />"
- display += "<br />"
- display += "<br />"
- display += ("<pre>Transaction hash: "+tx[0])
- display += "<br />"
- # display += ("tx_k: "+tx[1])
- # display += "<br />"
- display += ("Raw transaction: "+tx[2])
- display += "</pre><br />"
- return display
- def render_POST(self, request):
- return self.render_GET(request)
- class WICTTest(resource.Resource):
- def render_GET(self, request):
- try:
- request.args['testnet'][0]
- testnet=True
- except:
- testnet=False
- list_avtx = {}
- i = 0
- try:
- for add in request.args['addresses'][0].split(','):
- print "Address %d: %s"%(i, add)
- list_avtx[add] = bc_address_to_available_tx(add, testnet)[add]
- i += 1
- print(list_avtx)
- display = ""
- display += write_avtx(list_avtx, testnet)
- except:
- display="You must provide at least one address to see the transaction you can spend.<br /><a href='CTTest?addresses=1BAdzvknPux2zqG2eNawvgitCW1aqwE4bb'>Like this</a>"
- return display
- def render_POST(self, request):
- return self.render_GET(request)
- class WIImport(resource.Resource):
- def render_GET(self, request):
- global addrtype
- try:
- pub=request.args['pub'][0]
- try:
- wdir=request.args['dir'][0]
- wname=request.args['name'][0]
- label=request.args['label'][0]
- db_env = create_env(wdir)
- db = open_wallet(db_env, wname, writable=True)
- update_wallet(db, 'ckey', { 'public_key' : pub.decode('hex'), 'encrypted_private_key' : random_string(96).decode('hex') })
- update_wallet(db, 'name', { 'hash' : public_key_to_bc_address(pub.decode('hex')), 'name' : "Read-only: "+label })
- db.close()
- return "Read-only address "+public_key_to_bc_address(pub.decode('hex'))+" imported"
- except:
- return "Read-only address "+public_key_to_bc_address(pub.decode('hex'))+" not imported"
- except:
- pass
- try:
- wdir=request.args['dir'][0]
- wname=request.args['name'][0]
- try: #Import a single key
- addrtype = int(request.args['vers'][0])
- format = X_if_else('hex', request.args['format'][0]=='true', 'reg')
- reserve=request.args.has_key('reserve')
- label=request.args['label'][0]
- compressed=request.args['com'][0]=='true'
- tocrypt=request.args['cry'][0]=='true'
- sec = request.args['key'][0]
- except: #Import csv file
- ret=import_csv_keys(request.args['file'][0],wdir,wname)
- return "File "+X_if_else("", ret, "not ")+"imported"
- if format in 'reg':
- pkey = regenerate_key(sec)
- compressed = is_compressed(sec)
- elif len(sec) == 64:
- pkey = EC_KEY(str_to_long(sec.decode('hex')))
- compressed = False
- elif len(sec) == 66:
- pkey = EC_KEY(str_to_long(sec[:-2].decode('hex')))
- compressed = True
- else:
- return "Hexadecimal private keys must be 64 or 66 characters long"
- if not pkey:
- return "Bad private key"
- if not os.path.isfile(wdir+"/"+wname):
- return '%s/%s doesn\'t exist'%(wdir, wname)
- db_env = create_env(wdir)
- ret_read = read_wallet(json_db, db_env, wname, True, True, "", None)
- tocrypt = ret_read['crypted']
- db = open_wallet(db_env, wname, writable=True)
- secret = GetSecret(pkey)
- private_key = GetPrivKey(pkey, compressed)
- public_key = GetPubKey(pkey, compressed)
- addr = public_key_to_bc_address(public_key)
- if (format in 'reg' and sec in private_keys) or (format not in 'reg' and sec in private_hex_keys):
- return "Already exists"
- if not tocrypt:
- update_wallet(db, 'key', { 'public_key' : public_key, 'private_key' : private_key })
- else:
- cry_master = json_db['mkey']['encrypted_key'].decode('hex')
- cry_salt = json_db['mkey']['salt'].decode('hex')
- cry_rounds = json_db['mkey']['nDerivationIterations']
- cry_method = json_db['mkey']['nDerivationMethod']
- crypter.SetKeyFromPassphrase(passphrase, cry_salt, cry_rounds, cry_method)
- masterkey = crypter.Decrypt(cry_master)
- crypter.SetKey(masterkey)
- crypter.SetIV(Hash(public_key))
- e = crypter.Encrypt(secret)
- ck_epk=e
- update_wallet(db, 'ckey', { 'public_key' : public_key, 'encrypted_private_key' : ck_epk })
- if not reserve:
- update_wallet(db, 'name', { 'hash' : addr, 'name' : label })
- db.close()
- return "<pre>Address: %s\nPrivkey: %s\nHexkey: %s\nKey (%scrypted, %scompressed) imported in %s/%s<pre>" % (addr, SecretToASecret(secret, compressed), secret.encode('hex'), X_if_else("",tocrypt,"un"), X_if_else("",compressed,"un"), wdir, wname)
- except:
- log.err()
- return 'Error in import page'
- def render_POST(self, request):
- return self.render_GET(request)
- class WI404(resource.Resource):
- def render_GET(self, request):
- return 'Page Not Found'
- def update_pyw():
- if md5_last_pywallet[0] and md5_last_pywallet[1] not in md5_pywallet:
- dl=urllib.urlopen('https://raw.github.com/jackjack-jj/pywallet/master/pywallet.py').read()
- if len(dl)>40 and md5_2(dl)==md5_last_pywallet[1]:
- filout = open(pyw_path+"/"+pyw_filename, 'w')
- filout.write(dl)
- filout.close()
- thread.start_new_thread(restart_pywallet, ())
- return "Updated, restarting..."
- else:
- return "Problem when downloading new version ("+md5_2(dl)+"/"+md5_last_pywallet[1]+")"
- def restart_pywallet():
- thread.start_new_thread(start_pywallet, ())
- time.sleep(2)
- reactor.stop()
- def start_pywallet():
- a=Popen("python "+pyw_path+"/"+pyw_filename+" --web --port "+str(webport)+" --wait 3", shell=True, bufsize=-1, stdout=PIPE).stdout
- a.close()
- def clone_wallet(parentPath, clonePath):
- types,datas=[],[]
- parentdir,parentname=os.path.split(parentPath)
- wdir,wname=os.path.split(clonePath)
- db_env = create_env(parentdir)
- read_wallet(json_db, db_env, parentname, True, True, "", False)
- types.append('version')
- datas.append({'version':json_db['version']})
- types.append('defaultkey')
- datas.append({'key':json_db['defaultkey']})
- for k in json_db['keys']:
- types.append('ckey')
- datas.append({'public_key':k['pubkey'].decode('hex'),'encrypted_private_key':random_string(96).decode('hex')})
- for k in json_db['pool']:
- types.append('pool')
- datas.append({'n':k['n'],'nVersion':k['nVersion'],'nTime':k['nTime'],'public_key':k['public_key_hex'].decode('hex')})
- for addr,label in json_db['names'].items():
- types.append('name')
- datas.append({'hash':addr,'name':'Watch:'+label})
- db_env = create_env(wdir)
- create_new_wallet(db_env, wname, 60000)
- db = open_wallet(db_env, wname, True)
- NPP_salt=random_string(16).decode('hex')
- NPP_rounds=int(50000+random.random()*20000)
- NPP_method=0
- NPP_MK=random_string(64).decode('hex')
- crypter.SetKeyFromPassphrase(random_string(64), NPP_salt, NPP_rounds, NPP_method)
- NPP_EMK = crypter.Encrypt(NPP_MK)
- update_wallet(db, 'mkey', {
- "encrypted_key": NPP_EMK,
- 'nDerivationIterations' : NPP_rounds,
- 'nDerivationMethod' : NPP_method,
- 'nID' : 1,
- 'otherParams' : ''.decode('hex'),
- "salt": NPP_salt
- })
- db.close()
- read_wallet(json_db, db_env, wname, True, True, "", False)
- db = open_wallet(db_env, wname, writable=True)
- update_wallet(db, types, datas, True)
- db.close()
- print "Wallet successfully cloned to:\n %s"%clonePath
- import thread
- md5_last_pywallet = [False, ""]
- def retrieve_last_pywallet_md5():
- global md5_last_pywallet
- md5_last_pywallet = [True, md5_onlinefile('https://raw.github.com/jackjack-jj/pywallet/master/pywallet.py')]
- from optparse import OptionParser
- if __name__ == '__main__':
- parser = OptionParser(usage="%prog [options]", version="%prog 1.1")
- parser.add_option("--passphrase", dest="passphrase",
- help="passphrase for the encrypted wallet")
- parser.add_option("--dumpwallet", dest="dump", action="store_true",
- help="dump wallet in json format")
- parser.add_option("--dumpwithbalance", dest="dumpbalance", action="store_true",
- help="includes balance of each address in the json dump, takes about 2 minutes per 100 addresses")
- parser.add_option("--importprivkey", dest="key",
- help="import private key from vanitygen")
- parser.add_option("--importhex", dest="keyishex", action="store_true",
- help="KEY is in hexadecimal format")
- parser.add_option("--datadir", dest="datadir",
- help="wallet directory (defaults to bitcoin default)")
- parser.add_option("--wallet", dest="walletfile",
- help="wallet filename (defaults to wallet.dat)",
- default="wallet.dat")
- parser.add_option("--label", dest="label",
- help="label shown in the adress book (defaults to '')",
- default="")
- parser.add_option("--testnet", dest="testnet", action="store_true",
- help="use testnet subdirectory and address type")
- parser.add_option("--namecoin", dest="namecoin", action="store_true",
- help="use namecoin address type")
- parser.add_option("--otherversion", dest="otherversion",
- help="use other network address type, whose version is OTHERVERSION")
- parser.add_option("--info", dest="keyinfo", action="store_true",
- help="display pubkey, privkey (both depending on the network) and hexkey")
- parser.add_option("--reserve", dest="reserve", action="store_true",
- help="import as a reserve key, i.e. it won't show in the adress book")
- parser.add_option("--multidelete", dest="multidelete",
- help="deletes data in your wallet, according to the file provided")
- parser.add_option("--balance", dest="key_balance",
- help="prints balance of KEY_BALANCE")
- parser.add_option("--web", dest="web", action="store_true",
- help="run pywallet web interface")
- parser.add_option("--port", dest="port",
- help="port of web interface (defaults to 8989)")
- parser.add_option("--recover", dest="recover", action="store_true",
- help="recover your deleted keys, use with recov_size and recov_device")
- parser.add_option("--recov_device", dest="recov_device",
- help="device to read (e.g. /dev/sda1 or E: or a file)")
- parser.add_option("--recov_size", dest="recov_size",
- help="number of bytes to read (e.g. 20Mo or 50Gio)")
- parser.add_option("--recov_outputdir", dest="recov_outputdir",
- help="output directory where the recovered wallet will be put")
- parser.add_option("--clone_watchonly_from", dest="clone_watchonly_from",
- help="path of the original wallet")
- parser.add_option("--clone_watchonly_to", dest="clone_watchonly_to",
- help="path of the resulting watch-only wallet")
- parser.add_option("--dont_check_walletversion", dest="dcv", action="store_true",
- help="don't check if wallet version > %d before running (WARNING: this may break your wallet, be sure you know what you do)"%max_version)
- parser.add_option("--wait", dest="nseconds",
- help="wait NSECONDS seconds before launch")
- # parser.add_option("--forcerun", dest="forcerun",
- # action="store_true",
- # help="run even if pywallet detects bitcoin is running")
- (options, args) = parser.parse_args()
- # a=Popen("ps xa | grep ' bitcoin'", shell=True, bufsize=-1, stdout=PIPE).stdout
- # aread=a.read()
- # nl = aread.count("\n")
- # a.close()
- # if nl > 2:
- # print('Bitcoin seems to be running: \n"%s"'%(aread))
- # if options.forcerun is None:
- # exit(0)
- if options.nseconds:
- time.sleep(int(options.nseconds))
- if options.passphrase:
- passphrase = options.passphrase
- if options.clone_watchonly_from is not None and options.clone_watchonly_to:
- clone_wallet(options.clone_watchonly_from, options.clone_watchonly_to)
- exit(0)
- if options.recover:
- if options.recov_size is None or options.recov_device is None or options.recov_outputdir is None:
- print("You must provide the device, the number of bytes to read and the output directory")
- exit(0)
- device = options.recov_device
- if len(device) in [2,3] and device[1]==':':
- device="\\\\.\\"+device
- size = read_device_size(options.recov_size)
- passphraseRecov=''
- while passphraseRecov=='':
- passphraseRecov=raw_input("Enter the passphrase for the wallet that will contain all the recovered keys: ")
- passphrase=passphraseRecov
- passes=[]
- p=' '
- print '\nEnter the possible passphrases used in your deleted wallets.'
- print "Don't forget that more passphrases = more time to test the possibilities."
- print 'Write one passphrase per line and end with an empty line.'
- while p!='':
- p=raw_input("Possible passphrase: ")
- if p!='':
- passes.append(p)
- print "\nStarting recovery."
- recoveredKeys=recov(device, passes, size, 10240, options.recov_outputdir)
- recoveredKeys=list(set(recoveredKeys))
- # print recoveredKeys[0:5]
- db_env = create_env(options.recov_outputdir)
- recov_wallet_name = "recovered_wallet_%s.dat"%ts()
- create_new_wallet(db_env, recov_wallet_name, 32500)
- if passphraseRecov!="I don't want to put a password on the recovered wallet and I know what can be the consequences.":
- db = open_wallet(db_env, recov_wallet_name, True)
- NPP_salt=random_string(16).decode('hex')
- NPP_rounds=int(50000+random.random()*20000)
- NPP_method=0
- NPP_MK=random_string(64).decode('hex')
- crypter.SetKeyFromPassphrase(passphraseRecov, NPP_salt, NPP_rounds, NPP_method)
- NPP_EMK = crypter.Encrypt(NPP_MK)
- update_wallet(db, 'mkey', {
- "encrypted_key": NPP_EMK,
- 'nDerivationIterations' : NPP_rounds,
- 'nDerivationMethod' : NPP_method,
- 'nID' : 1,
- 'otherParams' : ''.decode('hex'),
- "salt": NPP_salt
- })
- db.close()
- read_wallet(json_db, db_env, recov_wallet_name, True, True, "", False)
- db = open_wallet(db_env, recov_wallet_name, True)
- print "\n\nImporting:"
- for i,sec in enumerate(recoveredKeys):
- sec=sec.encode('hex')
- print("\nImporting key %4d/%d:"%(i+1, len(recoveredKeys)))
- importprivkey(db, sec, "recovered: %s"%sec, None, True)
- importprivkey(db, sec+'01', "recovered: %s"%sec, None, True)
- db.close()
- print("\n\nThe new wallet %s/%s contains the %d recovered key%s"%(options.recov_outputdir, recov_wallet_name, len(recoveredKeys), iais(len(recoveredKeys))))
- exit(0)
- if 'bsddb' in missing_dep:
- print("pywallet needs 'bsddb' package to run, please install it")
- exit(0)
- if 'twisted' in missing_dep and options.web is not None:
- print("'twisted' package is not installed, pywallet web interface can't be launched")
- exit(0)
- if 'ecdsa' in missing_dep:
- print("'ecdsa' package is not installed, pywallet won't be able to sign/verify messages")
- if 'twisted' not in missing_dep:
- VIEWS = {
- 'DumpWallet': WIDumpWallet(),
- 'MergeWallets': WIMergeWallets(),
- 'Import': WIImport(),
- 'ImportTx': WIImportTx(),
- 'DumpTx': WIDumpTx(),
- 'Info': WIInfo(),
- 'Delete': WIDelete(),
- 'Balance': WIBalance(),
- 'ChangePP': WIChangePP(),
- 'Others': WIOthers(),
- 'LoadBalances': WICTTest(),
- 'CTTest': WICTTest(),
- 'ListTransactions': WICTListTx(),
- 'CreateTransaction': WICT(),
- 'CT': WICT(),
- 'quit': WIQuit()
- }
- if options.dcv is not None:
- max_version = 10 ** 9
- if options.datadir is not None:
- wallet_dir = options.datadir
- if options.walletfile is not None:
- wallet_name = options.walletfile
- if 'twisted' not in missing_dep and options.web is not None:
- md5_pywallet = md5_file(pyw_path+"/"+pyw_filename)
- thread.start_new_thread(retrieve_last_pywallet_md5, ())
- webport = 8989
- if options.port is not None:
- webport = int(options.port)
- root = WIRoot()
- for viewName, className in VIEWS.items():
- root.putChild(viewName, className)
- log.startLogging(sys.stdout)
- log.msg('Starting server: %s' %str(datetime.now()))
- server = server.Site(root)
- reactor.listenTCP(webport, server)
- reactor.run()
- exit(0)
- if options.key_balance is not None:
- print(balance(balance_site, options.key_balance))
- exit(0)
- if options.dump is None and options.key is None and options.multidelete is None:
- print "A mandatory option is missing\n"
- parser.print_help()
- exit(0)
- if options.testnet:
- db_dir += "/testnet"
- addrtype = 111
- if options.namecoin or options.otherversion is not None:
- if options.datadir is None and options.keyinfo is None:
- print("You must provide your wallet directory")
- exit(0)
- else:
- if options.namecoin:
- addrtype = 52
- else:
- addrtype = int(options.otherversion)
- if options.keyinfo is not None:
- if not keyinfo(options.key, options.keyishex):
- print "Bad private key"
- exit(0)
- db_dir = determine_db_dir()
- db_env = create_env(db_dir)
- if options.multidelete is not None:
- filename=options.multidelete
- filin = open(filename, 'r')
- content = filin.read().split('\n')
- filin.close()
- typedel=content[0]
- kd=filter(bool,content[1:])
- try:
- r=delete_from_wallet(db_env, determine_db_name(), typedel, kd)
- print '%d element%s deleted'%(r, 's'*(int(r>1)))
- except:
- print "Error: do not try to delete a non-existing transaction."
- exit(1)
- exit(0)
- read_wallet(json_db, db_env, determine_db_name(), True, True, "", options.dumpbalance is not None)
- if json_db.get('minversion') > max_version:
- print "Version mismatch (must be <= %d)" % max_version
- #exit(1)
- if options.dump:
- print json.dumps(json_db, sort_keys=True, indent=4)
- elif options.key:
- if json_db['version'] > max_version:
- print "Version mismatch (must be <= %d)" % max_version
- elif (options.keyishex is None and options.key in private_keys) or (options.keyishex is not None and options.key in private_hex_keys):
- print "Already exists"
- else:
- db = open_wallet(db_env, determine_db_name(), writable=True)
- if importprivkey(db, options.key, options.label, options.reserve, options.keyishex):
- print "Imported successfully"
- else:
- print "Bad private key"
- db.close()
Add Comment
Please, Sign In to add comment