some address generation work completed

This commit is contained in:
Jonathan Warren 2013-01-16 11:52:52 -05:00
parent f18eb5c91b
commit f0666e6544
11 changed files with 1809 additions and 232 deletions

View File

@ -95,6 +95,12 @@ def calculateInventoryHash(data):
return sha2.digest()[0:32] return sha2.digest()[0:32]
def encodeAddress(version,stream,ripe): def encodeAddress(version,stream,ripe):
if version >= 2:
if ripe[:2] == '\x00\x00':
ripe = ripe[2:]
elif ripe[:1] == '\x00':
ripe = ripe[1:]
print 'within encodeAddress, length of ripe is:', len(ripe)
a = encodeVarint(version) + encodeVarint(stream) + ripe a = encodeVarint(version) + encodeVarint(stream) + ripe
sha = hashlib.new('sha512') sha = hashlib.new('sha512')
sha.update(a) sha.update(a)
@ -162,15 +168,30 @@ def decodeAddress(address):
#print 'addressVersionNumber', addressVersionNumber #print 'addressVersionNumber', addressVersionNumber
#print 'bytesUsedByVersionNumber', bytesUsedByVersionNumber #print 'bytesUsedByVersionNumber', bytesUsedByVersionNumber
if addressVersionNumber != 1: if addressVersionNumber > 2:
print 'cannot decode version address version numbers this high' print 'cannot decode address version numbers this high'
status = 'versiontoohigh'
return status,0,0,0
elif addressVersionNumber == 0:
print 'cannot decode address version numbers of zero.'
status = 'versiontoohigh' status = 'versiontoohigh'
return status,0,0,0 return status,0,0,0
streamNumber, bytesUsedByStreamNumber = decodeVarint(data[bytesUsedByVersionNumber:10+bytesUsedByVersionNumber]) streamNumber, bytesUsedByStreamNumber = decodeVarint(data[bytesUsedByVersionNumber:])
#print streamNumber #print streamNumber
status = 'success' status = 'success'
return status,addressVersionNumber,streamNumber,data[-24:-4] if addressVersionNumber == 1:
return status,addressVersionNumber,streamNumber,data[-24:-4]
elif addressVersionNumber == 2:
if len(data[bytesUsedByVersionNumber+bytesUsedByStreamNumber:-4]) == 19:
print 'within decode address, lenth I think is 19'
return status,addressVersionNumber,streamNumber,'\x00'+data[bytesUsedByVersionNumber+bytesUsedByStreamNumber:-4]
elif len(data[bytesUsedByVersionNumber+bytesUsedByStreamNumber:-4]) == 20:
print 'within decode address, lenth I think is 20'
return status,addressVersionNumber,streamNumber,data[bytesUsedByVersionNumber+bytesUsedByStreamNumber:-4]
elif len(data[bytesUsedByVersionNumber+bytesUsedByStreamNumber:-4]) == 18:
print 'within decode address, lenth I think is 18'
return status,addressVersionNumber,streamNumber,'\x00\x00'+data[bytesUsedByVersionNumber+bytesUsedByStreamNumber:-4]
def addBMIfNotPresent(address): def addBMIfNotPresent(address):
if address[:3] != 'BM-': if address[:3] != 'BM-':

View File

@ -48,6 +48,11 @@ from time import strftime, localtime
import os import os
import string import string
import socks import socks
import pyelliptic
from pyelliptic import highlevelcrypto
from pyelliptic.openssl import OpenSSL
import ctypes
from pyelliptic import arithmetic
#For each stream to which we connect, one outgoingSynSender thread will exist and will create 8 connections with peers. #For each stream to which we connect, one outgoingSynSender thread will exist and will create 8 connections with peers.
class outgoingSynSender(QThread): class outgoingSynSender(QThread):
@ -64,7 +69,7 @@ class outgoingSynSender(QThread):
time.sleep(1) time.sleep(1)
resetTime = int(time.time()) #used below to clear out the alreadyAttemptedConnectionsList periodically so that we will retry connecting to hosts to which we have already tried to connect. resetTime = int(time.time()) #used below to clear out the alreadyAttemptedConnectionsList periodically so that we will retry connecting to hosts to which we have already tried to connect.
while True: while True:
#time.sleep(999999)#I'm using this to prevent connections for testing. time.sleep(999999)#I'm using this to prevent connections for testing.
if len(self.selfInitiatedConnectionList) < 8: #maximum number of outgoing connections = 8 if len(self.selfInitiatedConnectionList) < 8: #maximum number of outgoing connections = 8
random.seed() random.seed()
HOST, = random.sample(knownNodes[self.streamNumber], 1) HOST, = random.sample(knownNodes[self.streamNumber], 1)
@ -2084,43 +2089,151 @@ class addressGenerator(QThread):
def __init__(self, parent = None): def __init__(self, parent = None):
QThread.__init__(self, parent) QThread.__init__(self, parent)
def setup(self,streamNumber,label): def setup(self,addressVersionNumber,streamNumber,label="(no label)",numberOfAddressesToMake=1,deterministicPassphrase="",eighteenByteRipe=False):
self.addressVersionNumber = addressVersionNumber
self.streamNumber = streamNumber self.streamNumber = streamNumber
self.label = label self.label = label
self.numberOfAddressesToMake = numberOfAddressesToMake
self.deterministicPassphrase = deterministicPassphrase
self.eighteenByteRipe = eighteenByteRipe
def run(self): def run(self):
statusbar = 'Generating new ' + str(config.getint('bitmessagesettings', 'bitstrength')) + ' bit RSA key. This takes a minute on average. If you want to generate multiple addresses now, you can; they will queue.' if self.addressVersionNumber == 2:
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar)
(pubkey, privkey) = rsa.newkeys(config.getint('bitmessagesettings', 'bitstrength'))
print privkey['n']
print privkey['e']
print privkey['d']
print privkey['p']
print privkey['q']
sha = hashlib.new('sha512') if self.deterministicPassphrase == "":
#sha.update(str(pubkey.n)+str(pubkey.e)) statusbar = 'Generating one new address'
sha.update(convertIntToString(pubkey.n)+convertIntToString(pubkey.e)) self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar)
ripe = hashlib.new('ripemd160') #This next section is a little bit strange. We're going to generate keys over and over until we
ripe.update(sha.digest()) #find one that starts with either \x00 or \x00\x00. Then when we pack them into a Bitmessage address,
address = encodeAddress(1,self.streamNumber,ripe.digest()) #we won't store the \x00 or \x00\x00 bytes thus making the address shorter.
while True:
potentialPrivSigningKey = OpenSSL.rand(32)
potentialPrivEncryptionKey = OpenSSL.rand(32)
potentialPubSigningKey = self.pointMult(potentialPrivSigningKey)
potentialPubEncryptionKey = self.pointMult(potentialPrivEncryptionKey)
#print 'potentialPubSigningKey', potentialPubSigningKey.encode('hex')
#print 'potentialPubEncryptionKey', potentialPubEncryptionKey.encode('hex')
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Finished generating address. Writing to keys.dat') ripe = hashlib.new('ripemd160')
config.add_section(address) sha = hashlib.new('sha512')
config.set(address,'label',self.label) sha.update(potentialPubSigningKey+potentialPubEncryptionKey)
config.set(address,'enabled','true') ripe.update(sha.digest())
config.set(address,'decoy','false') #print 'potential ripe.digest', ripe.digest().encode('hex')
config.set(address,'n',str(privkey['n'])) if self.eighteenByteRipe:
config.set(address,'e',str(privkey['e'])) if ripe.digest()[:2] == '\x00\x00':
config.set(address,'d',str(privkey['d'])) break
config.set(address,'p',str(privkey['p'])) else:
config.set(address,'q',str(privkey['q'])) if ripe.digest()[:1] == '\x00':
with open(appdata + 'keys.dat', 'wb') as configfile: break
config.write(configfile) print 'ripe.digest', ripe.digest().encode('hex')
if ripe.digest()[:2] == '\x00\x00':
address = encodeAddress(2,self.streamNumber,ripe.digest()[2:])
print 'address has 18 byte ripe:', address
elif ripe.digest()[:1] == '\x00':
address = encodeAddress(2,self.streamNumber,ripe.digest()[1:])
print 'address has 19 byte ripe:', address
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Finished generating address. Writing to keys.dat')
status,addressVersionNumber,streamNumber,hash = decodeAddress(address)
print status,addressVersionNumber,streamNumber,hash.encode('hex')
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Done generating address') #An excellent way for us to store our keys is in Wallet Import Format. Let us convert now.
self.emit(SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.label,address,str(self.streamNumber)) #https://en.bitcoin.it/wiki/Wallet_import_format
privSigningKey = '\x80'+potentialPrivSigningKey
checksum = hashlib.sha256(hashlib.sha256(privSigningKey).digest()).digest()[0:4]
privSigningKeyWIF = arithmetic.changebase(privSigningKey + checksum,256,58)
print 'privSigningKeyWIF',privSigningKeyWIF
privEncryptionKey = '\x80'+potentialPrivEncryptionKey
checksum = hashlib.sha256(hashlib.sha256(privEncryptionKey).digest()).digest()[0:4]
privEncryptionKeyWIF = arithmetic.changebase(privEncryptionKey + checksum,256,58)
print 'privEncryptionKeyWIF',privEncryptionKeyWIF
config.add_section(address)
print 'self.label', self.label
config.set(address,'label',self.label)
config.set(address,'enabled','true')
config.set(address,'decoy','false')
config.set(address,'privSigningKey',privSigningKeyWIF)
config.set(address,'privEncryptionKey',privEncryptionKeyWIF)
with open(appdata + 'keys.dat', 'wb') as configfile:
config.write(configfile)
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Done generating address')
self.emit(SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.label,address,str(self.streamNumber))
else: #There is something in the deterministicPassphrase variable thus we are going to do this deterministically.
statusbar = 'Generating '+numberOfAddressesToMake + ' new addresses.'
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar)
elif self.addressVersionNumber == 1:
statusbar = 'Generating new ' + str(config.getint('bitmessagesettings', 'bitstrength')) + ' bit RSA key. This takes a minute on average. If you want to generate multiple addresses now, you can; they will queue.'
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),statusbar)
(pubkey, privkey) = rsa.newkeys(config.getint('bitmessagesettings', 'bitstrength'))
print privkey['n']
print privkey['e']
print privkey['d']
print privkey['p']
print privkey['q']
sha = hashlib.new('sha512')
#sha.update(str(pubkey.n)+str(pubkey.e))
sha.update(convertIntToString(pubkey.n)+convertIntToString(pubkey.e))
ripe = hashlib.new('ripemd160')
ripe.update(sha.digest())
address = encodeAddress(1,self.streamNumber,ripe.digest())
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Finished generating address. Writing to keys.dat')
config.add_section(address)
config.set(address,'label',self.label)
config.set(address,'enabled','true')
config.set(address,'decoy','false')
config.set(address,'n',str(privkey['n']))
config.set(address,'e',str(privkey['e']))
config.set(address,'d',str(privkey['d']))
config.set(address,'p',str(privkey['p']))
config.set(address,'q',str(privkey['q']))
with open(appdata + 'keys.dat', 'wb') as configfile:
config.write(configfile)
self.emit(SIGNAL("updateStatusBar(PyQt_PyObject)"),'Done generating address')
self.emit(SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"),self.label,address,str(self.streamNumber))
def pointMult(self,secret):
#passphrase += 'a'
#secret = hashlib.sha256(passphrase.encode('utf8')).digest()
#if secret starts with too many FF's, continue
ctx = OpenSSL.BN_CTX_new()
#secret = OpenSSL.rand(32)
k = OpenSSL.EC_KEY_new_by_curve_name(OpenSSL.get_curve('secp256k1'))
priv_key = OpenSSL.BN_bin2bn(secret, 32, 0)
group = OpenSSL.EC_KEY_get0_group(k)
pub_key = OpenSSL.EC_POINT_new(group)
OpenSSL.EC_POINT_mul(group, pub_key, priv_key, None, None, ctx)
OpenSSL.EC_KEY_set_private_key(k, priv_key)
OpenSSL.EC_KEY_set_public_key(k, pub_key)
#print 'priv_key',priv_key
#print 'pub_key',pub_key
size = OpenSSL.i2o_ECPublicKey(k, 0)
mb = ctypes.create_string_buffer(size)
OpenSSL.i2o_ECPublicKey(k, ctypes.byref(ctypes.pointer(mb)))
#print 'mb.raw', mb.raw.encode('hex'), 'length:', len(mb.raw)
#print 'mb.raw', mb.raw, 'length:', len(mb.raw)
#ripe = hashlib.new('ripemd160')
#sha = hashlib.new('sha512')
#sha.update(mb.raw)
#ripe.update(sha.digest())
OpenSSL.EC_POINT_free(pub_key)
OpenSSL.BN_CTX_free(ctx)
OpenSSL.BN_free(priv_key)
OpenSSL.EC_KEY_free(k)
return mb.raw
class iconGlossaryDialog(QtGui.QDialog): class iconGlossaryDialog(QtGui.QDialog):
def __init__(self,parent): def __init__(self,parent):
@ -2231,8 +2344,8 @@ class NewSubscriptionDialog(QtGui.QDialog):
class NewAddressDialog(QtGui.QDialog): class NewAddressDialog(QtGui.QDialog):
def __init__(self, parent): def __init__(self, parent):
QtGui.QWidget.__init__(self, parent) QtGui.QWidget.__init__(self, parent)
self.ui = Ui_NewAddressDialog() #Jonathan changed this line self.ui = Ui_NewAddressDialog()
self.ui.setupUi(self) #Jonathan left this line alone self.ui.setupUi(self)
self.parent = parent self.parent = parent
row = 1 row = 1
while self.parent.ui.tableWidgetYourIdentities.item(row-1,1): while self.parent.ui.tableWidgetYourIdentities.item(row-1,1):
@ -2240,8 +2353,8 @@ class NewAddressDialog(QtGui.QDialog):
#print self.parent.ui.tableWidgetYourIdentities.item(row-1,1).text() #print self.parent.ui.tableWidgetYourIdentities.item(row-1,1).text()
self.ui.comboBoxExisting.addItem(self.parent.ui.tableWidgetYourIdentities.item(row-1,1).text()) self.ui.comboBoxExisting.addItem(self.parent.ui.tableWidgetYourIdentities.item(row-1,1).text())
row += 1 row += 1
#QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self)) self.ui.groupBoxDeterministic.setHidden(True)
QtGui.QWidget.resize(self,QtGui.QWidget.sizeHint(self))
class MyForm(QtGui.QMainWindow): class MyForm(QtGui.QMainWindow):
@ -2541,7 +2654,7 @@ class MyForm(QtGui.QMainWindow):
queryreturn = sqlReturnQueue.get() queryreturn = sqlReturnQueue.get()
for row in queryreturn: for row in queryreturn:
ackdata, = row ackdata, = row
print 'Watching for ackdata', repr(ackdata) print 'Watching for ackdata', ackdata.encode('hex')
ackdataForWhichImWatching[ackdata] = 0 ackdataForWhichImWatching[ackdata] = 0
QtCore.QObject.connect(self.ui.tableWidgetYourIdentities, QtCore.SIGNAL("itemChanged(QTableWidgetItem *)"), self.tableWidgetYourIdentitiesItemChanged) QtCore.QObject.connect(self.ui.tableWidgetYourIdentities, QtCore.SIGNAL("itemChanged(QTableWidgetItem *)"), self.tableWidgetYourIdentitiesItemChanged)
@ -3225,31 +3338,36 @@ class MyForm(QtGui.QMainWindow):
def click_NewAddressDialog(self): def click_NewAddressDialog(self):
print 'click_buttondialog'
self.dialog = NewAddressDialog(self) self.dialog = NewAddressDialog(self)
# For Modal dialogs # For Modal dialogs
if self.dialog.exec_(): if self.dialog.exec_():
self.dialog.ui.buttonBox.enabled = False #self.dialog.ui.buttonBox.enabled = False
if self.dialog.ui.radioButtonMostAvailable.isChecked(): if self.dialog.ui.radioButtonRandomAddress.isChecked():
#self.generateAndStoreAnAddress(1) if self.dialog.ui.radioButtonMostAvailable.isChecked():
streamNumberForAddress = 1 streamNumberForAddress = 1
else:
#User selected 'Use the same stream as an existing address.'
streamNumberForAddress = addressStream(self.dialog.ui.comboBoxExisting.currentText())
self.addressGenerator = addressGenerator()
self.addressGenerator.setup(2,streamNumberForAddress,str(self.dialog.ui.newaddresslabel.text().toUtf8()),1,"",self.dialog.ui.checkBoxEighteenByteRipe.isChecked())
QtCore.QObject.connect(self.addressGenerator, SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable)
QtCore.QObject.connect(self.addressGenerator, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
self.addressGenerator.start()
else: else:
#User selected 'Use the same stream as an existing address.' if self.dialog.ui.lineEditPassphrase.text() != self.dialog.ui.lineEditPassphraseAgain.text():
streamNumberForAddress = addressStream(self.dialog.ui.comboBoxExisting.currentText()) QMessageBox.about(self, "Passphrase mismatch", "The passphrase you entered twice doesn\'t match. Try again.")
elif self.dialog.ui.lineEditPassphrase.text() == "":
self.addressGenerator = addressGenerator() QMessageBox.about(self, "Choose a passphrase", "You really do need a passphrase.")
self.addressGenerator.setup(streamNumberForAddress,str(self.dialog.ui.newaddresslabel.text().toUtf8())) else:
streamNumberForAddress = 1 #this will eventually have to be replaced by logic to determine the most available stream number.
QtCore.QObject.connect(self.addressGenerator, SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable) self.addressGenerator = addressGenerator()
QtCore.QObject.connect(self.addressGenerator, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar) self.addressGenerator.setup(2,streamNumberForAddress,"unused address",self.dialog.ui.spinBoxNumberOfAddressesToMake.value(),self.dialog.ui.lineEditPassphrase.text().toUtf8(),self.dialog.ui.checkBoxEighteenByteRipe.isChecked())
QtCore.QObject.connect(self.addressGenerator, SIGNAL("writeNewAddressToTable(PyQt_PyObject,PyQt_PyObject,PyQt_PyObject)"), self.writeNewAddressToTable)
QtCore.QObject.connect(self.addressGenerator, QtCore.SIGNAL("updateStatusBar(PyQt_PyObject)"), self.updateStatusBar)
self.addressGenerator.start() self.addressGenerator.start()
else: else:
print 'rejected' print 'new address dialog box rejected'
def closeEvent(self, event): def closeEvent(self, event):
broadcastToSendDataQueues((0, 'shutdown', 'all')) broadcastToSendDataQueues((0, 'shutdown', 'all'))

View File

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'newaddressdialog.ui' # Form implementation generated from reading ui file 'newaddressdialog.ui'
# #
# Created: Wed Dec 19 15:55:07 2012 # Created: Tue Jan 15 15:21:33 2013
# by: PyQt4 UI code generator 4.9.4 # by: PyQt4 UI code generator 4.9.4
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
@ -17,57 +17,154 @@ except AttributeError:
class Ui_NewAddressDialog(object): class Ui_NewAddressDialog(object):
def setupUi(self, NewAddressDialog): def setupUi(self, NewAddressDialog):
NewAddressDialog.setObjectName(_fromUtf8("NewAddressDialog")) NewAddressDialog.setObjectName(_fromUtf8("NewAddressDialog"))
NewAddressDialog.resize(383, 258) NewAddressDialog.resize(723, 704)
self.buttonBox = QtGui.QDialogButtonBox(NewAddressDialog) self.formLayout = QtGui.QFormLayout(NewAddressDialog)
self.buttonBox.setGeometry(QtCore.QRect(160, 220, 201, 32)) self.formLayout.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.formLayout.setObjectName(_fromUtf8("formLayout"))
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
self.label = QtGui.QLabel(NewAddressDialog) self.label = QtGui.QLabel(NewAddressDialog)
self.label.setGeometry(QtCore.QRect(10, 0, 361, 41))
self.label.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft) self.label.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft)
self.label.setWordWrap(True) self.label.setWordWrap(True)
self.label.setObjectName(_fromUtf8("label")) self.label.setObjectName(_fromUtf8("label"))
self.label_2 = QtGui.QLabel(NewAddressDialog) self.formLayout.setWidget(0, QtGui.QFormLayout.SpanningRole, self.label)
self.label_2.setGeometry(QtCore.QRect(20, 50, 301, 20)) self.label_5 = QtGui.QLabel(NewAddressDialog)
self.label_5.setWordWrap(True)
self.label_5.setObjectName(_fromUtf8("label_5"))
self.formLayout.setWidget(2, QtGui.QFormLayout.SpanningRole, self.label_5)
self.line = QtGui.QFrame(NewAddressDialog)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.line.sizePolicy().hasHeightForWidth())
self.line.setSizePolicy(sizePolicy)
self.line.setMinimumSize(QtCore.QSize(100, 2))
self.line.setFrameShape(QtGui.QFrame.HLine)
self.line.setFrameShadow(QtGui.QFrame.Sunken)
self.line.setObjectName(_fromUtf8("line"))
self.formLayout.setWidget(4, QtGui.QFormLayout.SpanningRole, self.line)
self.radioButtonRandomAddress = QtGui.QRadioButton(NewAddressDialog)
self.radioButtonRandomAddress.setChecked(True)
self.radioButtonRandomAddress.setObjectName(_fromUtf8("radioButtonRandomAddress"))
self.formLayout.setWidget(5, QtGui.QFormLayout.SpanningRole, self.radioButtonRandomAddress)
self.radioButtonDeterministicAddress = QtGui.QRadioButton(NewAddressDialog)
self.radioButtonDeterministicAddress.setObjectName(_fromUtf8("radioButtonDeterministicAddress"))
self.formLayout.setWidget(6, QtGui.QFormLayout.LabelRole, self.radioButtonDeterministicAddress)
self.checkBoxEighteenByteRipe = QtGui.QCheckBox(NewAddressDialog)
self.checkBoxEighteenByteRipe.setObjectName(_fromUtf8("checkBoxEighteenByteRipe"))
self.formLayout.setWidget(9, QtGui.QFormLayout.SpanningRole, self.checkBoxEighteenByteRipe)
self.groupBoxDeterministic = QtGui.QGroupBox(NewAddressDialog)
self.groupBoxDeterministic.setObjectName(_fromUtf8("groupBoxDeterministic"))
self.gridLayout = QtGui.QGridLayout(self.groupBoxDeterministic)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.label_6 = QtGui.QLabel(self.groupBoxDeterministic)
self.label_6.setObjectName(_fromUtf8("label_6"))
self.gridLayout.addWidget(self.label_6, 0, 0, 1, 4)
self.lineEditPassphrase = QtGui.QLineEdit(self.groupBoxDeterministic)
self.lineEditPassphrase.setInputMethodHints(QtCore.Qt.ImhHiddenText|QtCore.Qt.ImhNoAutoUppercase|QtCore.Qt.ImhNoPredictiveText)
self.lineEditPassphrase.setEchoMode(QtGui.QLineEdit.Password)
self.lineEditPassphrase.setObjectName(_fromUtf8("lineEditPassphrase"))
self.gridLayout.addWidget(self.lineEditPassphrase, 1, 0, 1, 7)
self.label_7 = QtGui.QLabel(self.groupBoxDeterministic)
self.label_7.setObjectName(_fromUtf8("label_7"))
self.gridLayout.addWidget(self.label_7, 2, 0, 1, 4)
self.lineEditPassphraseAgain = QtGui.QLineEdit(self.groupBoxDeterministic)
self.lineEditPassphraseAgain.setEchoMode(QtGui.QLineEdit.Password)
self.lineEditPassphraseAgain.setObjectName(_fromUtf8("lineEditPassphraseAgain"))
self.gridLayout.addWidget(self.lineEditPassphraseAgain, 3, 0, 1, 7)
self.label_8 = QtGui.QLabel(self.groupBoxDeterministic)
self.label_8.setObjectName(_fromUtf8("label_8"))
self.gridLayout.addWidget(self.label_8, 4, 0, 1, 7)
self.label_9 = QtGui.QLabel(self.groupBoxDeterministic)
self.label_9.setObjectName(_fromUtf8("label_9"))
self.gridLayout.addWidget(self.label_9, 5, 0, 1, 1)
spacerItem = QtGui.QSpacerItem(73, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem, 5, 1, 1, 1)
self.label_10 = QtGui.QLabel(self.groupBoxDeterministic)
self.label_10.setObjectName(_fromUtf8("label_10"))
self.gridLayout.addWidget(self.label_10, 5, 3, 1, 1)
spacerItem1 = QtGui.QSpacerItem(42, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem1, 5, 4, 1, 2)
self.label_11 = QtGui.QLabel(self.groupBoxDeterministic)
self.label_11.setObjectName(_fromUtf8("label_11"))
self.gridLayout.addWidget(self.label_11, 6, 0, 1, 5)
self.spinBoxNumberOfAddressesToMake = QtGui.QSpinBox(self.groupBoxDeterministic)
self.spinBoxNumberOfAddressesToMake.setMinimum(1)
self.spinBoxNumberOfAddressesToMake.setProperty("value", 8)
self.spinBoxNumberOfAddressesToMake.setObjectName(_fromUtf8("spinBoxNumberOfAddressesToMake"))
self.gridLayout.addWidget(self.spinBoxNumberOfAddressesToMake, 6, 5, 1, 2)
self.formLayout.setWidget(8, QtGui.QFormLayout.LabelRole, self.groupBoxDeterministic)
self.groupBox = QtGui.QGroupBox(NewAddressDialog)
self.groupBox.setObjectName(_fromUtf8("groupBox"))
self.gridLayout_2 = QtGui.QGridLayout(self.groupBox)
self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
self.label_2 = QtGui.QLabel(self.groupBox)
self.label_2.setObjectName(_fromUtf8("label_2")) self.label_2.setObjectName(_fromUtf8("label_2"))
self.newaddresslabel = QtGui.QLineEdit(NewAddressDialog) self.gridLayout_2.addWidget(self.label_2, 0, 0, 1, 2)
self.newaddresslabel.setGeometry(QtCore.QRect(20, 70, 351, 20)) self.newaddresslabel = QtGui.QLineEdit(self.groupBox)
self.newaddresslabel.setObjectName(_fromUtf8("newaddresslabel")) self.newaddresslabel.setObjectName(_fromUtf8("newaddresslabel"))
self.radioButtonMostAvailable = QtGui.QRadioButton(NewAddressDialog) self.gridLayout_2.addWidget(self.newaddresslabel, 1, 0, 1, 2)
self.radioButtonMostAvailable.setGeometry(QtCore.QRect(20, 110, 401, 16)) self.radioButtonMostAvailable = QtGui.QRadioButton(self.groupBox)
self.radioButtonMostAvailable.setChecked(True) self.radioButtonMostAvailable.setChecked(False)
self.radioButtonMostAvailable.setObjectName(_fromUtf8("radioButtonMostAvailable")) self.radioButtonMostAvailable.setObjectName(_fromUtf8("radioButtonMostAvailable"))
self.radioButtonExisting = QtGui.QRadioButton(NewAddressDialog) self.gridLayout_2.addWidget(self.radioButtonMostAvailable, 2, 0, 1, 2)
self.radioButtonExisting.setGeometry(QtCore.QRect(20, 150, 351, 18)) self.label_3 = QtGui.QLabel(self.groupBox)
self.radioButtonExisting.setChecked(False)
self.radioButtonExisting.setObjectName(_fromUtf8("radioButtonExisting"))
self.label_3 = QtGui.QLabel(NewAddressDialog)
self.label_3.setGeometry(QtCore.QRect(35, 127, 351, 20))
self.label_3.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) self.label_3.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.label_3.setObjectName(_fromUtf8("label_3")) self.label_3.setObjectName(_fromUtf8("label_3"))
self.label_4 = QtGui.QLabel(NewAddressDialog) self.gridLayout_2.addWidget(self.label_3, 3, 1, 1, 1)
self.label_4.setGeometry(QtCore.QRect(37, 167, 351, 21)) self.radioButtonExisting = QtGui.QRadioButton(self.groupBox)
self.radioButtonExisting.setChecked(False)
self.radioButtonExisting.setObjectName(_fromUtf8("radioButtonExisting"))
self.gridLayout_2.addWidget(self.radioButtonExisting, 4, 0, 1, 2)
self.label_4 = QtGui.QLabel(self.groupBox)
self.label_4.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) self.label_4.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.label_4.setObjectName(_fromUtf8("label_4")) self.label_4.setObjectName(_fromUtf8("label_4"))
self.comboBoxExisting = QtGui.QComboBox(NewAddressDialog) self.gridLayout_2.addWidget(self.label_4, 5, 1, 1, 1)
spacerItem2 = QtGui.QSpacerItem(13, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout_2.addItem(spacerItem2, 6, 0, 1, 1)
self.comboBoxExisting = QtGui.QComboBox(self.groupBox)
self.comboBoxExisting.setEnabled(False) self.comboBoxExisting.setEnabled(False)
self.comboBoxExisting.setGeometry(QtCore.QRect(40, 190, 331, 22))
self.comboBoxExisting.setEditable(True) self.comboBoxExisting.setEditable(True)
self.comboBoxExisting.setObjectName(_fromUtf8("comboBoxExisting")) self.comboBoxExisting.setObjectName(_fromUtf8("comboBoxExisting"))
self.gridLayout_2.addWidget(self.comboBoxExisting, 6, 1, 1, 1)
self.formLayout.setWidget(7, QtGui.QFormLayout.LabelRole, self.groupBox)
self.buttonBox = QtGui.QDialogButtonBox(NewAddressDialog)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.buttonBox.sizePolicy().hasHeightForWidth())
self.buttonBox.setSizePolicy(sizePolicy)
self.buttonBox.setMinimumSize(QtCore.QSize(160, 0))
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
self.formLayout.setWidget(10, QtGui.QFormLayout.SpanningRole, self.buttonBox)
self.retranslateUi(NewAddressDialog) self.retranslateUi(NewAddressDialog)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), NewAddressDialog.accept) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), NewAddressDialog.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), NewAddressDialog.reject) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), NewAddressDialog.reject)
QtCore.QObject.connect(self.radioButtonExisting, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.comboBoxExisting.setEnabled) QtCore.QObject.connect(self.radioButtonExisting, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.comboBoxExisting.setEnabled)
QtCore.QObject.connect(self.radioButtonDeterministicAddress, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.groupBoxDeterministic.setShown)
QtCore.QObject.connect(self.radioButtonRandomAddress, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.groupBox.setShown)
QtCore.QMetaObject.connectSlotsByName(NewAddressDialog) QtCore.QMetaObject.connectSlotsByName(NewAddressDialog)
def retranslateUi(self, NewAddressDialog): def retranslateUi(self, NewAddressDialog):
NewAddressDialog.setWindowTitle(QtGui.QApplication.translate("NewAddressDialog", "Create new Address", None, QtGui.QApplication.UnicodeUTF8)) NewAddressDialog.setWindowTitle(QtGui.QApplication.translate("NewAddressDialog", "Create new Address", None, QtGui.QApplication.UnicodeUTF8))
self.label.setText(QtGui.QApplication.translate("NewAddressDialog", "Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged.", None, QtGui.QApplication.UnicodeUTF8)) self.label.setText(QtGui.QApplication.translate("NewAddressDialog", "Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged. You may generate addresses by using either random numbers or by using a passphrase. If you use a passphrase, the address is called a \"deterministic\" address.\n"
"The \'Random Number\' option is selected by default but deterministic addresses have several pros and cons:", None, QtGui.QApplication.UnicodeUTF8))
self.label_5.setText(QtGui.QApplication.translate("NewAddressDialog", "<html><head/><body><p><span style=\" font-weight:600;\">Pros:<br/></span>You can recreate your addresses on any computer from memory. <br/>You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. <br/><span style=\" font-weight:600;\">Cons:<br/></span>You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. <br/>You must remember the address version number and the stream number along with your passphrase. <br/>If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.</p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
self.radioButtonRandomAddress.setText(QtGui.QApplication.translate("NewAddressDialog", "Use a random number generator to make an address", None, QtGui.QApplication.UnicodeUTF8))
self.radioButtonDeterministicAddress.setText(QtGui.QApplication.translate("NewAddressDialog", "Use a passpharase to make addresses", None, QtGui.QApplication.UnicodeUTF8))
self.checkBoxEighteenByteRipe.setText(QtGui.QApplication.translate("NewAddressDialog", "Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter", None, QtGui.QApplication.UnicodeUTF8))
self.groupBoxDeterministic.setTitle(QtGui.QApplication.translate("NewAddressDialog", "Make deterministic addresses", None, QtGui.QApplication.UnicodeUTF8))
self.label_6.setText(QtGui.QApplication.translate("NewAddressDialog", "Passphrase", None, QtGui.QApplication.UnicodeUTF8))
self.label_7.setText(QtGui.QApplication.translate("NewAddressDialog", "Retype passphrase", None, QtGui.QApplication.UnicodeUTF8))
self.label_8.setText(QtGui.QApplication.translate("NewAddressDialog", "In addition to your passphrase, you must remember these numbers:", None, QtGui.QApplication.UnicodeUTF8))
self.label_9.setText(QtGui.QApplication.translate("NewAddressDialog", "Address version number: 2", None, QtGui.QApplication.UnicodeUTF8))
self.label_10.setText(QtGui.QApplication.translate("NewAddressDialog", "Stream number: 1", None, QtGui.QApplication.UnicodeUTF8))
self.label_11.setText(QtGui.QApplication.translate("NewAddressDialog", "Number of addresses to make based on your passphrase:", None, QtGui.QApplication.UnicodeUTF8))
self.groupBox.setTitle(QtGui.QApplication.translate("NewAddressDialog", "Randomly generate address", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("NewAddressDialog", "Label (not shown to anyone except you)", None, QtGui.QApplication.UnicodeUTF8)) self.label_2.setText(QtGui.QApplication.translate("NewAddressDialog", "Label (not shown to anyone except you)", None, QtGui.QApplication.UnicodeUTF8))
self.radioButtonMostAvailable.setText(QtGui.QApplication.translate("NewAddressDialog", "Use the most available stream", None, QtGui.QApplication.UnicodeUTF8)) self.radioButtonMostAvailable.setText(QtGui.QApplication.translate("NewAddressDialog", "Use the most available stream", None, QtGui.QApplication.UnicodeUTF8))
self.radioButtonExisting.setText(QtGui.QApplication.translate("NewAddressDialog", "Use the same stream as an existing address", None, QtGui.QApplication.UnicodeUTF8))
self.label_3.setText(QtGui.QApplication.translate("NewAddressDialog", " (best if this is the first of many addresses you will create)", None, QtGui.QApplication.UnicodeUTF8)) self.label_3.setText(QtGui.QApplication.translate("NewAddressDialog", " (best if this is the first of many addresses you will create)", None, QtGui.QApplication.UnicodeUTF8))
self.radioButtonExisting.setText(QtGui.QApplication.translate("NewAddressDialog", "Use the same stream as an existing address", None, QtGui.QApplication.UnicodeUTF8))
self.label_4.setText(QtGui.QApplication.translate("NewAddressDialog", "(saves you some bandwidth and processing power)", None, QtGui.QApplication.UnicodeUTF8)) self.label_4.setText(QtGui.QApplication.translate("NewAddressDialog", "(saves you some bandwidth and processing power)", None, QtGui.QApplication.UnicodeUTF8))

View File

@ -6,151 +6,301 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>383</width> <width>723</width>
<height>258</height> <height>704</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Create new Address</string> <string>Create new Address</string>
</property> </property>
<widget class="QDialogButtonBox" name="buttonBox"> <layout class="QFormLayout" name="formLayout">
<property name="geometry"> <property name="fieldGrowthPolicy">
<rect> <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
<x>160</x>
<y>220</y>
<width>201</width>
<height>32</height>
</rect>
</property> </property>
<property name="orientation"> <item row="0" column="0" colspan="2">
<enum>Qt::Horizontal</enum> <widget class="QLabel" name="label">
</property> <property name="text">
<property name="standardButtons"> <string>Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged. You may generate addresses by using either random numbers or by using a passphrase. If you use a passphrase, the address is called a &quot;deterministic&quot; address.
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> The 'Random Number' option is selected by default but deterministic addresses have several pros and cons:</string>
</property> </property>
</widget> <property name="alignment">
<widget class="QLabel" name="label"> <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
<property name="geometry"> </property>
<rect> <property name="wordWrap">
<x>10</x> <bool>true</bool>
<y>0</y> </property>
<width>361</width> </widget>
<height>41</height> </item>
</rect> <item row="2" column="0" colspan="2">
</property> <widget class="QLabel" name="label_5">
<property name="text"> <property name="text">
<string>Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged.</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Pros:&lt;br/&gt;&lt;/span&gt;You can recreate your addresses on any computer from memory. &lt;br/&gt;You need-not worry about backing up your keys.dat file as long as you can remember your passphrase. &lt;br/&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Cons:&lt;br/&gt;&lt;/span&gt;You must remember (or write down) your passphrase if you expect to be able to recreate your keys if they are lost. &lt;br/&gt;You must remember the address version number and the stream number along with your passphrase. &lt;br/&gt;If you choose a weak passphrase and someone on the Internet can brute-force it, they can read your messages and send messages as you.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="alignment"> <property name="wordWrap">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set> <bool>true</bool>
</property> </property>
<property name="wordWrap"> </widget>
<bool>true</bool> </item>
</property> <item row="4" column="0" colspan="2">
</widget> <widget class="Line" name="line">
<widget class="QLabel" name="label_2"> <property name="sizePolicy">
<property name="geometry"> <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<rect> <horstretch>0</horstretch>
<x>20</x> <verstretch>0</verstretch>
<y>50</y> </sizepolicy>
<width>301</width> </property>
<height>20</height> <property name="minimumSize">
</rect> <size>
</property> <width>100</width>
<property name="text"> <height>2</height>
<string>Label (not shown to anyone except you)</string> </size>
</property> </property>
</widget> <property name="orientation">
<widget class="QLineEdit" name="newaddresslabel"> <enum>Qt::Horizontal</enum>
<property name="geometry"> </property>
<rect> </widget>
<x>20</x> </item>
<y>70</y> <item row="5" column="0" colspan="2">
<width>351</width> <widget class="QRadioButton" name="radioButtonRandomAddress">
<height>20</height> <property name="text">
</rect> <string>Use a random number generator to make an address</string>
</property> </property>
</widget> <property name="checked">
<widget class="QRadioButton" name="radioButtonMostAvailable"> <bool>true</bool>
<property name="geometry"> </property>
<rect> </widget>
<x>20</x> </item>
<y>110</y> <item row="6" column="0">
<width>401</width> <widget class="QRadioButton" name="radioButtonDeterministicAddress">
<height>16</height> <property name="text">
</rect> <string>Use a passpharase to make addresses</string>
</property> </property>
<property name="text"> </widget>
<string>Use the most available stream</string> </item>
</property> <item row="9" column="0" colspan="2">
<property name="checked"> <widget class="QCheckBox" name="checkBoxEighteenByteRipe">
<bool>true</bool> <property name="text">
</property> <string>Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter</string>
</widget> </property>
<widget class="QRadioButton" name="radioButtonExisting"> </widget>
<property name="geometry"> </item>
<rect> <item row="8" column="0">
<x>20</x> <widget class="QGroupBox" name="groupBoxDeterministic">
<y>150</y> <property name="title">
<width>351</width> <string>Make deterministic addresses</string>
<height>18</height> </property>
</rect> <layout class="QGridLayout" name="gridLayout">
</property> <item row="0" column="0" colspan="4">
<property name="text"> <widget class="QLabel" name="label_6">
<string>Use the same stream as an existing address</string> <property name="text">
</property> <string>Passphrase</string>
<property name="checked"> </property>
<bool>false</bool> </widget>
</property> </item>
</widget> <item row="1" column="0" colspan="7">
<widget class="QLabel" name="label_3"> <widget class="QLineEdit" name="lineEditPassphrase">
<property name="geometry"> <property name="inputMethodHints">
<rect> <set>Qt::ImhHiddenText|Qt::ImhNoAutoUppercase|Qt::ImhNoPredictiveText</set>
<x>35</x> </property>
<y>127</y> <property name="echoMode">
<width>351</width> <enum>QLineEdit::Password</enum>
<height>20</height> </property>
</rect> </widget>
</property> </item>
<property name="text"> <item row="2" column="0" colspan="4">
<string> (best if this is the first of many addresses you will create)</string> <widget class="QLabel" name="label_7">
</property> <property name="text">
<property name="alignment"> <string>Retype passphrase</string>
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> </property>
</property> </widget>
</widget> </item>
<widget class="QLabel" name="label_4"> <item row="3" column="0" colspan="7">
<property name="geometry"> <widget class="QLineEdit" name="lineEditPassphraseAgain">
<rect> <property name="echoMode">
<x>37</x> <enum>QLineEdit::Password</enum>
<y>167</y> </property>
<width>351</width> </widget>
<height>21</height> </item>
</rect> <item row="4" column="0" colspan="7">
</property> <widget class="QLabel" name="label_8">
<property name="text"> <property name="text">
<string>(saves you some bandwidth and processing power)</string> <string>In addition to your passphrase, you must remember these numbers:</string>
</property> </property>
<property name="alignment"> </widget>
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> </item>
</property> <item row="5" column="0">
</widget> <widget class="QLabel" name="label_9">
<widget class="QComboBox" name="comboBoxExisting"> <property name="text">
<property name="enabled"> <string>Address version number: 2</string>
<bool>false</bool> </property>
</property> </widget>
<property name="geometry"> </item>
<rect> <item row="5" column="1">
<x>40</x> <spacer name="horizontalSpacer">
<y>190</y> <property name="orientation">
<width>331</width> <enum>Qt::Horizontal</enum>
<height>22</height> </property>
</rect> <property name="sizeHint" stdset="0">
</property> <size>
<property name="editable"> <width>73</width>
<bool>true</bool> <height>20</height>
</property> </size>
</widget> </property>
</spacer>
</item>
<item row="5" column="3">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Stream number: 1</string>
</property>
</widget>
</item>
<item row="5" column="4" colspan="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>42</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="6" column="0" colspan="5">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Number of addresses to make based on your passphrase:</string>
</property>
</widget>
</item>
<item row="6" column="5" colspan="2">
<widget class="QSpinBox" name="spinBoxNumberOfAddressesToMake">
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>8</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="7" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Randomly generate address</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Label (not shown to anyone except you)</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLineEdit" name="newaddresslabel"/>
</item>
<item row="2" column="0" colspan="2">
<widget class="QRadioButton" name="radioButtonMostAvailable">
<property name="text">
<string>Use the most available stream</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_3">
<property name="text">
<string> (best if this is the first of many addresses you will create)</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QRadioButton" name="radioButtonExisting">
<property name="text">
<string>Use the same stream as an existing address</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string>(saves you some bandwidth and processing power)</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="6" column="0">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>13</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="comboBoxExisting">
<property name="enabled">
<bool>false</bool>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
<zorder>comboBoxExisting</zorder>
<zorder>label_3</zorder>
<zorder>radioButtonExisting</zorder>
<zorder>newaddresslabel</zorder>
<zorder>label_4</zorder>
<zorder>radioButtonMostAvailable</zorder>
<zorder>label_2</zorder>
<zorder>horizontalSpacer_3</zorder>
</widget>
</item>
<item row="10" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>160</width>
<height>0</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget> </widget>
<resources/> <resources/>
<connections> <connections>
@ -161,8 +311,8 @@
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>360</x> <x>580</x>
<y>234</y> <y>644</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>157</x> <x>157</x>
@ -177,8 +327,8 @@
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>360</x> <x>580</x>
<y>240</y> <y>650</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>286</x> <x>286</x>
@ -193,12 +343,44 @@
<slot>setEnabled(bool)</slot> <slot>setEnabled(bool)</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>30</x> <x>60</x>
<y>158</y> <y>349</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>99</x> <x>148</x>
<y>199</y> <y>394</y>
</hint>
</hints>
</connection>
<connection>
<sender>radioButtonDeterministicAddress</sender>
<signal>toggled(bool)</signal>
<receiver>groupBoxDeterministic</receiver>
<slot>setShown(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>92</x>
<y>213</y>
</hint>
<hint type="destinationlabel">
<x>277</x>
<y>601</y>
</hint>
</hints>
</connection>
<connection>
<sender>radioButtonRandomAddress</sender>
<signal>toggled(bool)</signal>
<receiver>groupBox</receiver>
<slot>setShown(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>72</x>
<y>189</y>
</hint>
<hint type="destinationlabel">
<x>68</x>
<y>268</y>
</hint> </hint>
</hints> </hints>
</connection> </connection>

17
pyelliptic/__init__.py Normal file
View File

@ -0,0 +1,17 @@
# Copyright (C) 2010
# Author: Yann GUIBET
# Contact: <yannguibet@gmail.com>
__version__ = '1.3'
__all__ = [
'OpenSSL',
'ecc',
'cipher',
'hash',
]
from .openssl import OpenSSL
from .ecc import ECC
from .cipher import Cipher
from .hash import hmac_sha256, hmac_sha512, pbkdf2

103
pyelliptic/arithmetic.py Normal file
View File

@ -0,0 +1,103 @@
import hashlib, re
P = 2**256-2**32-2**9-2**8-2**7-2**6-2**4-1
A = 0
Gx = 55066263022277343669578718895168534326250603453777594175500187360389116729240
Gy = 32670510020758816978083085130507043184471273380659243275938904335757337482424
G = (Gx,Gy)
def inv(a,n):
lm, hm = 1,0
low, high = a%n,n
while low > 1:
r = high/low
nm, new = hm-lm*r, high-low*r
lm, low, hm, high = nm, new, lm, low
return lm % n
def get_code_string(base):
if base == 2: return '01'
elif base == 10: return '0123456789'
elif base == 16: return "0123456789abcdef"
elif base == 58: return "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
elif base == 256: return ''.join([chr(x) for x in range(256)])
else: raise ValueError("Invalid base!")
def encode(val,base,minlen=0):
code_string = get_code_string(base)
result = ""
while val > 0:
result = code_string[val % base] + result
val /= base
if len(result) < minlen:
result = code_string[0]*(minlen-len(result))+result
return result
def decode(string,base):
code_string = get_code_string(base)
result = 0
if base == 16: string = string.lower()
while len(string) > 0:
result *= base
result += code_string.find(string[0])
string = string[1:]
return result
def changebase(string,frm,to,minlen=0):
return encode(decode(string,frm),to,minlen)
def base10_add(a,b):
if a == None: return b[0],b[1]
if b == None: return a[0],a[1]
if a[0] == b[0]:
if a[1] == b[1]: return base10_double(a[0],a[1])
else: return None
m = ((b[1]-a[1]) * inv(b[0]-a[0],P)) % P
x = (m*m-a[0]-b[0]) % P
y = (m*(a[0]-x)-a[1]) % P
return (x,y)
def base10_double(a):
if a == None: return None
m = ((3*a[0]*a[0]+A)*inv(2*a[1],P)) % P
x = (m*m-2*a[0]) % P
y = (m*(a[0]-x)-a[1]) % P
return (x,y)
def base10_multiply(a,n):
if n == 0: return G
if n == 1: return a
if (n%2) == 0: return base10_double(base10_multiply(a,n/2))
if (n%2) == 1: return base10_add(base10_double(base10_multiply(a,n/2)),a)
def hex_to_point(h): return (decode(h[2:34],16),decode(h[34:],16))
def point_to_hex(p): return '04'+encode(p[0],16,32)+encode(p[1],16,32)
def multiply(privkey,pubkey):
return point_to_hex(base10_multiply(hex_to_point(pubkey),decode(privkey,16)))
def privtopub(privkey):
return point_to_hex(base10_multiply(G,decode(privkey,16)))
def add(p1,p2):
if (len(p1)==32):
return encode(decode(p1,16) + decode(p2,16) % P,16,32)
else:
return point_to_hex(base10_add(hex_to_point(p1),hex_to_point(p2)))
def hash160(string):
intermed = hashlib.sha256(string).digest()
return hashlib.new('ripemd160').update(intermed).digest()
def dbl_sha256(string):
return hashlib.sha256(hashlib.sha256(string).digest()).digest()
def bin_to_b58check(inp):
inp_fmtd = '\x00' + inp
leadingzbytes = len(re.match('^\x00*',inp_fmtd).group(0))
checksum = dbl_sha256(inp_fmtd)[:4]
return '1' * leadingzbytes + changebase(inp_fmtd+checksum,256,58)
def pubkey_to_address(pubkey):
return bin_to_b58check(hash_160(changebase(pubkey,16,256)))

81
pyelliptic/cipher.py Normal file
View File

@ -0,0 +1,81 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2011 Yann GUIBET <yannguibet@gmail.com>
# See LICENSE for details.
from pyelliptic.openssl import OpenSSL
class Cipher:
"""
Symmetric encryption
import pyelliptic
iv = pyelliptic.Cipher.gen_IV('aes-256-cfb')
ctx = pyelliptic.Cipher("secretkey", iv, 1, ciphername='aes-256-cfb')
ciphertext = ctx.update('test1')
ciphertext += ctx.update('test2')
ciphertext += ctx.final()
ctx2 = pyelliptic.Cipher("secretkey", iv, 0, ciphername='aes-256-cfb')
print ctx2.ciphering(ciphertext)
"""
def __init__(self, key, iv, do, ciphername='aes-256-cbc'):
"""
do == 1 => Encrypt; do == 0 => Decrypt
"""
self.cipher = OpenSSL.get_cipher(ciphername)
self.ctx = OpenSSL.EVP_CIPHER_CTX_new()
if do == 1 or do == 0:
k = OpenSSL.malloc(key, len(key))
IV = OpenSSL.malloc(iv, len(iv))
OpenSSL.EVP_CipherInit_ex(
self.ctx, self.cipher.get_pointer(), 0, k, IV, do)
else:
raise Exception("RTFM ...")
@staticmethod
def get_all_cipher():
"""
static method, returns all ciphers available
"""
return OpenSSL.cipher_algo.keys()
@staticmethod
def get_blocksize(ciphername):
cipher = OpenSSL.get_cipher(ciphername)
return cipher.get_blocksize()
@staticmethod
def gen_IV(ciphername):
cipher = OpenSSL.get_cipher(ciphername)
return OpenSSL.rand(cipher.get_blocksize())
def update(self, input):
i = OpenSSL.c_int(0)
buffer = OpenSSL.malloc(b"", len(input) + self.cipher.get_blocksize())
inp = OpenSSL.malloc(input, len(input))
if OpenSSL.EVP_CipherUpdate(self.ctx, OpenSSL.byref(buffer),
OpenSSL.byref(i), inp, len(input)) == 0:
raise Exception("[OpenSSL] EVP_CipherUpdate FAIL ...")
return buffer.raw[0:i.value]
def final(self):
i = OpenSSL.c_int(0)
buffer = OpenSSL.malloc(b"", self.cipher.get_blocksize())
if (OpenSSL.EVP_CipherFinal_ex(self.ctx, OpenSSL.byref(buffer),
OpenSSL.byref(i))) == 0:
raise Exception("[OpenSSL] EVP_CipherFinal_ex FAIL ...")
return buffer.raw[0:i.value]
def ciphering(self, input):
"""
Do update and final in one method
"""
buff = self.update(input)
return buff + self.final()
def __del__(self):
OpenSSL.EVP_CIPHER_CTX_cleanup(self.ctx)
OpenSSL.EVP_CIPHER_CTX_free(self.ctx)

460
pyelliptic/ecc.py Normal file
View File

@ -0,0 +1,460 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2011 Yann GUIBET <yannguibet@gmail.com>
# See LICENSE for details.
from hashlib import sha512
from pyelliptic.openssl import OpenSSL
from pyelliptic.cipher import Cipher
from pyelliptic.hash import hmac_sha256
from struct import pack, unpack
class ECC:
"""
Asymmetric encryption with Elliptic Curve Cryptography (ECC)
ECDH, ECDSA and ECIES
import pyelliptic
alice = pyelliptic.ECC() # default curve: sect283r1
bob = pyelliptic.ECC(curve='sect571r1')
ciphertext = alice.encrypt("Hello Bob", bob.get_pubkey())
print bob.decrypt(ciphertext)
signature = bob.sign("Hello Alice")
# alice's job :
print pyelliptic.ECC(
pubkey=bob.get_pubkey()).verify(signature, "Hello Alice")
# ERROR !!!
try:
key = alice.get_ecdh_key(bob.get_pubkey())
except: print("For ECDH key agreement,\
the keys must be defined on the same curve !")
alice = pyelliptic.ECC(curve='sect571r1')
print alice.get_ecdh_key(bob.get_pubkey()).encode('hex')
print bob.get_ecdh_key(alice.get_pubkey()).encode('hex')
"""
def __init__(self, pubkey=None, privkey=None, pubkey_x=None,
pubkey_y=None, raw_privkey=None, curve='sect283r1'):
"""
For a normal and High level use, specifie pubkey,
privkey (if you need) and the curve
"""
if type(curve) == str:
self.curve = OpenSSL.get_curve(curve)
else:
self.curve = curve
if pubkey_x is not None and pubkey_y is not None:
self._set_keys(pubkey_x, pubkey_y, raw_privkey)
elif pubkey is not None:
curve, pubkey_x, pubkey_y, i = ECC._decode_pubkey(pubkey)
if privkey is not None:
curve2, raw_privkey, i = ECC._decode_privkey(privkey)
if curve != curve2:
raise Exception("Bad ECC keys ...")
self.curve = curve
self._set_keys(pubkey_x, pubkey_y, raw_privkey)
else:
self.privkey, self.pubkey_x, self.pubkey_y = self._generate()
def _set_keys(self, pubkey_x, pubkey_y, privkey):
if self.raw_check_key(privkey, pubkey_x, pubkey_y) < 0:
self.pubkey_x = None
self.pubkey_y = None
self.privkey = None
raise Exception("Bad ECC keys ...")
else:
self.pubkey_x = pubkey_x
self.pubkey_y = pubkey_y
self.privkey = privkey
@staticmethod
def get_curves():
"""
static method, returns the list of all the curves available
"""
return OpenSSL.curves.keys()
def get_curve(self):
return OpenSSL.get_curve_by_id(self.curve)
def get_curve_id(self):
return self.curve
def get_pubkey(self):
"""
High level function which returns :
curve(2) + len_of_pubkeyX(2) + pubkeyX + len_of_pubkeyY + pubkeyY
"""
return b''.join((pack('!H', self.curve),
pack('!H', len(self.pubkey_x)),
self.pubkey_x,
pack('!H', len(self.pubkey_y)),
self.pubkey_y
))
def get_privkey(self):
"""
High level function which returns
curve(2) + len_of_privkey(2) + privkey
"""
return b''.join((pack('!H', self.curve),
pack('!H', len(self.privkey)),
self.privkey
))
@staticmethod
def _decode_pubkey(pubkey):
i = 0
curve = unpack('!H', pubkey[i:i + 2])[0]
i += 2
tmplen = unpack('!H', pubkey[i:i + 2])[0]
i += 2
pubkey_x = pubkey[i:i + tmplen]
i += tmplen
tmplen = unpack('!H', pubkey[i:i + 2])[0]
i += 2
pubkey_y = pubkey[i:i + tmplen]
i += tmplen
return curve, pubkey_x, pubkey_y, i
@staticmethod
def _decode_privkey(privkey):
i = 0
curve = unpack('!H', privkey[i:i + 2])[0]
i += 2
tmplen = unpack('!H', privkey[i:i + 2])[0]
i += 2
privkey = privkey[i:i + tmplen]
i += tmplen
return curve, privkey, i
def _generate(self):
try:
pub_key_x = OpenSSL.BN_new()
pub_key_y = OpenSSL.BN_new()
key = OpenSSL.EC_KEY_new_by_curve_name(self.curve)
if key == 0:
raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...")
if (OpenSSL.EC_KEY_generate_key(key)) == 0:
raise Exception("[OpenSSL] EC_KEY_generate_key FAIL ...")
if (OpenSSL.EC_KEY_check_key(key)) == 0:
raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...")
priv_key = OpenSSL.EC_KEY_get0_private_key(key)
group = OpenSSL.EC_KEY_get0_group(key)
pub_key = OpenSSL.EC_KEY_get0_public_key(key)
if (OpenSSL.EC_POINT_get_affine_coordinates_GFp(group, pub_key,
pub_key_x,
pub_key_y, 0
)) == 0:
raise Exception(
"[OpenSSL] EC_POINT_get_affine_coordinates_GFp FAIL ...")
privkey = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(priv_key))
pubkeyx = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(pub_key_x))
pubkeyy = OpenSSL.malloc(0, OpenSSL.BN_num_bytes(pub_key_y))
OpenSSL.BN_bn2bin(priv_key, privkey)
privkey = privkey.raw
OpenSSL.BN_bn2bin(pub_key_x, pubkeyx)
pubkeyx = pubkeyx.raw
OpenSSL.BN_bn2bin(pub_key_y, pubkeyy)
pubkeyy = pubkeyy.raw
self.raw_check_key(privkey, pubkeyx, pubkeyy)
return privkey, pubkeyx, pubkeyy
finally:
OpenSSL.EC_KEY_free(key)
OpenSSL.BN_free(pub_key_x)
OpenSSL.BN_free(pub_key_y)
def get_ecdh_key(self, pubkey):
"""
High level function. Compute public key with the local private key
and returns a 512bits shared key
"""
curve, pubkey_x, pubkey_y, i = ECC._decode_pubkey(pubkey)
if curve != self.curve:
raise Exception("ECC keys must be from the same curve !")
return sha512(self.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest()
def raw_get_ecdh_key(self, pubkey_x, pubkey_y):
try:
ecdh_keybuffer = OpenSSL.malloc(0, 32)
other_key = OpenSSL.EC_KEY_new_by_curve_name(self.curve)
if other_key == 0:
raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...")
other_pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), 0)
other_pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), 0)
other_group = OpenSSL.EC_KEY_get0_group(other_key)
other_pub_key = OpenSSL.EC_POINT_new(other_group)
if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(other_group,
other_pub_key,
other_pub_key_x,
other_pub_key_y,
0)) == 0:
raise Exception(
"[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ...")
if (OpenSSL.EC_KEY_set_public_key(other_key, other_pub_key)) == 0:
raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ...")
if (OpenSSL.EC_KEY_check_key(other_key)) == 0:
raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...")
own_key = OpenSSL.EC_KEY_new_by_curve_name(self.curve)
if own_key == 0:
raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...")
own_priv_key = OpenSSL.BN_bin2bn(
self.privkey, len(self.privkey), 0)
if (OpenSSL.EC_KEY_set_private_key(own_key, own_priv_key)) == 0:
raise Exception("[OpenSSL] EC_KEY_set_private_key FAIL ...")
OpenSSL.ECDH_set_method(own_key, OpenSSL.ECDH_OpenSSL())
ecdh_keylen = OpenSSL.ECDH_compute_key(
ecdh_keybuffer, 32, other_pub_key, own_key, 0)
if ecdh_keylen != 32:
raise Exception("[OpenSSL] ECDH keylen FAIL ...")
return ecdh_keybuffer.raw
finally:
OpenSSL.EC_KEY_free(other_key)
OpenSSL.BN_free(other_pub_key_x)
OpenSSL.BN_free(other_pub_key_y)
OpenSSL.EC_POINT_free(other_pub_key)
OpenSSL.EC_KEY_free(own_key)
OpenSSL.BN_free(own_priv_key)
def check_key(self, privkey, pubkey):
"""
Check the public key and the private key.
The private key is optional (replace by None)
"""
curve, pubkey_x, pubkey_y, i = ECC._decode_pubkey(pubkey)
if privkey is None:
raw_privkey = None
curve2 = curve
else:
curve2, raw_privkey, i = ECC._decode_privkey(privkey)
if curve != curve2:
raise Exception("Bad public and private key")
return self.raw_check_key(raw_privkey, pubkey_x, pubkey_y, curve)
def raw_check_key(self, privkey, pubkey_x, pubkey_y, curve=None):
if curve is None:
curve = self.curve
elif type(curve) == str:
curve = OpenSSL.get_curve(curve)
else:
curve = curve
try:
key = OpenSSL.EC_KEY_new_by_curve_name(curve)
if key == 0:
raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...")
if privkey is not None:
priv_key = OpenSSL.BN_bin2bn(privkey, len(privkey), 0)
pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), 0)
pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), 0)
if privkey is not None:
if (OpenSSL.EC_KEY_set_private_key(key, priv_key)) == 0:
raise Exception(
"[OpenSSL] EC_KEY_set_private_key FAIL ...")
group = OpenSSL.EC_KEY_get0_group(key)
pub_key = OpenSSL.EC_POINT_new(group)
if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, pub_key,
pub_key_x,
pub_key_y,
0)) == 0:
raise Exception(
"[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ...")
if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0:
raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ...")
if (OpenSSL.EC_KEY_check_key(key)) == 0:
raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...")
return 0
finally:
OpenSSL.EC_KEY_free(key)
OpenSSL.BN_free(pub_key_x)
OpenSSL.BN_free(pub_key_y)
OpenSSL.EC_POINT_free(pub_key)
if privkey is not None:
OpenSSL.BN_free(priv_key)
def sign(self, inputb):
"""
Sign the input with ECDSA method and returns the signature
"""
try:
size = len(inputb)
buff = OpenSSL.malloc(inputb, size)
digest = OpenSSL.malloc(0, 64)
md_ctx = OpenSSL.EVP_MD_CTX_create()
dgst_len = OpenSSL.pointer(OpenSSL.c_int(0))
siglen = OpenSSL.pointer(OpenSSL.c_int(0))
sig = OpenSSL.malloc(0, 151)
key = OpenSSL.EC_KEY_new_by_curve_name(self.curve)
if key == 0:
raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...")
priv_key = OpenSSL.BN_bin2bn(self.privkey, len(self.privkey), 0)
pub_key_x = OpenSSL.BN_bin2bn(self.pubkey_x, len(self.pubkey_x), 0)
pub_key_y = OpenSSL.BN_bin2bn(self.pubkey_y, len(self.pubkey_y), 0)
if (OpenSSL.EC_KEY_set_private_key(key, priv_key)) == 0:
raise Exception("[OpenSSL] EC_KEY_set_private_key FAIL ...")
group = OpenSSL.EC_KEY_get0_group(key)
pub_key = OpenSSL.EC_POINT_new(group)
if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, pub_key,
pub_key_x,
pub_key_y,
0)) == 0:
raise Exception(
"[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ...")
if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0:
raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ...")
if (OpenSSL.EC_KEY_check_key(key)) == 0:
raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...")
OpenSSL.EVP_MD_CTX_init(md_ctx)
OpenSSL.EVP_DigestInit(md_ctx, OpenSSL.EVP_ecdsa())
if (OpenSSL.EVP_DigestUpdate(md_ctx, buff, size)) == 0:
raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ...")
OpenSSL.EVP_DigestFinal(md_ctx, digest, dgst_len)
OpenSSL.ECDSA_sign(0, digest, dgst_len.contents, sig, siglen, key)
if (OpenSSL.ECDSA_verify(0, digest, dgst_len.contents, sig,
siglen.contents, key)) != 1:
raise Exception("[OpenSSL] ECDSA_verify FAIL ...")
return sig.raw[:siglen.contents.value]
finally:
OpenSSL.EC_KEY_free(key)
OpenSSL.BN_free(pub_key_x)
OpenSSL.BN_free(pub_key_y)
OpenSSL.BN_free(priv_key)
OpenSSL.EC_POINT_free(pub_key)
OpenSSL.EVP_MD_CTX_destroy(md_ctx)
def verify(self, sig, inputb):
"""
Verify the signature with the input and the local public key.
Returns a boolean
"""
try:
bsig = OpenSSL.malloc(sig, len(sig))
binputb = OpenSSL.malloc(inputb, len(inputb))
digest = OpenSSL.malloc(0, 64)
dgst_len = OpenSSL.pointer(OpenSSL.c_int(0))
md_ctx = OpenSSL.EVP_MD_CTX_create()
key = OpenSSL.EC_KEY_new_by_curve_name(self.curve)
if key == 0:
raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...")
pub_key_x = OpenSSL.BN_bin2bn(self.pubkey_x, len(self.pubkey_x), 0)
pub_key_y = OpenSSL.BN_bin2bn(self.pubkey_y, len(self.pubkey_y), 0)
group = OpenSSL.EC_KEY_get0_group(key)
pub_key = OpenSSL.EC_POINT_new(group)
if (OpenSSL.EC_POINT_set_affine_coordinates_GFp(group, pub_key,
pub_key_x,
pub_key_y,
0)) == 0:
raise Exception(
"[OpenSSL] EC_POINT_set_affine_coordinates_GFp FAIL ...")
if (OpenSSL.EC_KEY_set_public_key(key, pub_key)) == 0:
raise Exception("[OpenSSL] EC_KEY_set_public_key FAIL ...")
if (OpenSSL.EC_KEY_check_key(key)) == 0:
raise Exception("[OpenSSL] EC_KEY_check_key FAIL ...")
OpenSSL.EVP_MD_CTX_init(md_ctx)
OpenSSL.EVP_DigestInit(md_ctx, OpenSSL.EVP_ecdsa())
if (OpenSSL.EVP_DigestUpdate(md_ctx, binputb, len(inputb))) == 0:
raise Exception("[OpenSSL] EVP_DigestUpdate FAIL ...")
OpenSSL.EVP_DigestFinal(md_ctx, digest, dgst_len)
ret = OpenSSL.ECDSA_verify(
0, digest, dgst_len.contents, bsig, len(sig), key)
if ret == -1:
return False # Fail to Check
else:
if ret == 0:
return False # Bad signature !
else:
return True # Good
return False
finally:
OpenSSL.EC_KEY_free(key)
OpenSSL.BN_free(pub_key_x)
OpenSSL.BN_free(pub_key_y)
OpenSSL.EC_POINT_free(pub_key)
OpenSSL.EVP_MD_CTX_destroy(md_ctx)
@staticmethod
def encrypt(data, pubkey, ephemcurve=None, ciphername='aes-256-cbc'):
"""
Encrypt data with ECIES method using the public key of the recipient.
"""
curve, pubkey_x, pubkey_y, i = ECC._decode_pubkey(pubkey)
return ECC.raw_encrypt(data, pubkey_x, pubkey_y, curve=curve,
ephemcurve=ephemcurve, ciphername=ciphername)
@staticmethod
def raw_encrypt(data, pubkey_x, pubkey_y, curve='sect283r1',
ephemcurve=None, ciphername='aes-256-cbc'):
if ephemcurve is None:
ephemcurve = curve
ephem = ECC(curve=ephemcurve)
key = sha512(ephem.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest()
key_e, key_m = key[:32], key[32:]
pubkey = ephem.get_pubkey()
iv = OpenSSL.rand(OpenSSL.get_cipher(ciphername).get_blocksize())
ctx = Cipher(key_e, iv, 1, ciphername)
ciphertext = ctx.ciphering(data)
mac = hmac_sha256(key_m, ciphertext)
return iv + pubkey + ciphertext + mac
def decrypt(self, data, ciphername='aes-256-cbc'):
"""
Decrypt data with ECIES method using the local private key
"""
blocksize = OpenSSL.get_cipher(ciphername).get_blocksize()
iv = data[:blocksize]
i = blocksize
curve, pubkey_x, pubkey_y, i2 = ECC._decode_pubkey(data[i:])
i += i2
ciphertext = data[i:len(data)-32]
i += len(ciphertext)
mac = data[i:]
key = sha512(self.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest()
key_e, key_m = key[:32], key[32:]
if hmac_sha256(key_m, ciphertext) != mac:
raise RuntimeError("Fail to verify data")
ctx = Cipher(key_e, iv, 0, ciphername)
return ctx.ciphering(ciphertext)

43
pyelliptic/hash.py Normal file
View File

@ -0,0 +1,43 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2011 Yann GUIBET <yannguibet@gmail.com>
# See LICENSE for details.
from pyelliptic.openssl import OpenSSL
def hmac_sha256(k, m):
"""
Compute the key and the message with HMAC SHA5256
"""
key = OpenSSL.malloc(k, len(k))
d = OpenSSL.malloc(m, len(m))
md = OpenSSL.malloc(0, 32)
i = OpenSSL.pointer(OpenSSL.c_int(0))
OpenSSL.HMAC(OpenSSL.EVP_sha256(), key, len(k), d, len(m), md, i)
return md.raw
def hmac_sha512(k, m):
"""
Compute the key and the message with HMAC SHA512
"""
key = OpenSSL.malloc(k, len(k))
d = OpenSSL.malloc(m, len(m))
md = OpenSSL.malloc(0, 64)
i = OpenSSL.pointer(OpenSSL.c_int(0))
OpenSSL.HMAC(OpenSSL.EVP_sha512(), key, len(k), d, len(m), md, i)
return md.raw
def pbkdf2(password, salt=None, i=10000, keylen=64):
if salt is None:
salt = OpenSSL.rand(8)
p_password = OpenSSL.malloc(password, len(password))
p_salt = OpenSSL.malloc(salt, len(salt))
output = OpenSSL.malloc(0, keylen)
OpenSSL.PKCS5_PBKDF2_HMAC(p_password, len(password), p_salt,
len(p_salt), i, OpenSSL.EVP_sha256(),
keylen, output)
return salt, output.raw

View File

@ -0,0 +1,33 @@
import pyelliptic
import arithmetic as a
def makeCryptor(privkey):
privkey_bin = '\x02\xca\x00 '+a.changebase(privkey,16,256,minlen=32)
pubkey = a.changebase(a.privtopub(privkey),16,256,minlen=65)[1:]
pubkey_bin = '\x02\xca\x00 '+pubkey[:32]+'\x00 '+pubkey[32:]
cryptor = pyelliptic.ECC(curve='secp256k1',privkey=privkey_bin,pubkey=pubkey_bin)
return cryptor
def hexToPubkey(pubkey):
pubkey_raw = a.changebase(pubkey[2:],16,256,minlen=64)
pubkey_bin = '\x02\xca\x00 '+pubkey_raw[:32]+'\x00 '+pubkey_raw[32:]
return pubkey_bin
def makePubCryptor(pubkey):
pubkey_bin = hexToPubkey(pubkey)
return pyelliptic.ECC(curve='secp256k1',pubkey=pubkey_bin)
# Converts hex private key into hex public key
def privToPub(privkey):
return a.privtopub(privkey)
# Encrypts message with hex public key
def encrypt(msg,hexPubkey):
return pyelliptic.ECC(curve='secp256k1').encrypt(msg,hexToPubkey(hexPubkey))
# Decrypts message with hex private key
def decrypt(msg,hexPrivkey):
return makeCryptor(hexPrivkey).decrypt(msg)
# Decrypts message with an existing pyelliptic.ecc.ECC object
def decryptFast(msg,cryptor):
return cryptor.decrypt(msg)
# Signs with hex private key
def sign(msg,hexPrivkey):
return makeCryptor(hexPrivkey).sign(msg)
# Verifies with hex public key
def verify(msg,sig,hexPubkey):
return makePubCryptor(hexPubkey).verify(sig,msg)

422
pyelliptic/openssl.py Normal file
View File

@ -0,0 +1,422 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2011 Yann GUIBET <yannguibet@gmail.com>
# See LICENSE for details.
#
# Software slightly changed by Jonathan Warren <bitmessage at-symbol jonwarren.org>
import sys
import ctypes
OpenSSL = None
class CipherName:
def __init__(self, name, pointer, blocksize):
self._name = name
self._pointer = pointer
self._blocksize = blocksize
def __str__(self):
return "Cipher : " + self._name + " | Blocksize : " + str(self._blocksize) + " | Fonction pointer : " + str(self._pointer)
def get_pointer(self):
return self._pointer()
def get_name(self):
return self._name
def get_blocksize(self):
return self._blocksize
class _OpenSSL:
"""
Wrapper for OpenSSL using ctypes
"""
def __init__(self, library):
"""
Build the wrapper
"""
self._lib = ctypes.CDLL(library)
self.pointer = ctypes.pointer
self.c_int = ctypes.c_int
self.byref = ctypes.byref
self.create_string_buffer = ctypes.create_string_buffer
self.BN_new = self._lib.BN_new
self.BN_new.restype = ctypes.c_void_p
self.BN_new.argtypes = []
self.BN_free = self._lib.BN_free
self.BN_free.restype = None
self.BN_free.argtypes = [ctypes.c_void_p]
self.BN_num_bits = self._lib.BN_num_bits
self.BN_num_bits.restype = ctypes.c_int
self.BN_num_bits.argtypes = [ctypes.c_void_p]
self.BN_bn2bin = self._lib.BN_bn2bin
self.BN_bn2bin.restype = ctypes.c_int
self.BN_bn2bin.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
self.BN_bin2bn = self._lib.BN_bin2bn
self.BN_bin2bn.restype = ctypes.c_void_p
self.BN_bin2bn.argtypes = [ctypes.c_void_p, ctypes.c_int,
ctypes.c_void_p]
self.EC_KEY_free = self._lib.EC_KEY_free
self.EC_KEY_free.restype = None
self.EC_KEY_free.argtypes = [ctypes.c_void_p]
self.EC_KEY_new_by_curve_name = self._lib.EC_KEY_new_by_curve_name
self.EC_KEY_new_by_curve_name.restype = ctypes.c_void_p
self.EC_KEY_new_by_curve_name.argtypes = [ctypes.c_int]
self.EC_KEY_generate_key = self._lib.EC_KEY_generate_key
self.EC_KEY_generate_key.restype = ctypes.c_int
self.EC_KEY_generate_key.argtypes = [ctypes.c_void_p]
self.EC_KEY_check_key = self._lib.EC_KEY_check_key
self.EC_KEY_check_key.restype = ctypes.c_int
self.EC_KEY_check_key.argtypes = [ctypes.c_void_p]
self.EC_KEY_get0_private_key = self._lib.EC_KEY_get0_private_key
self.EC_KEY_get0_private_key.restype = ctypes.c_void_p
self.EC_KEY_get0_private_key.argtypes = [ctypes.c_void_p]
self.EC_KEY_get0_public_key = self._lib.EC_KEY_get0_public_key
self.EC_KEY_get0_public_key.restype = ctypes.c_void_p
self.EC_KEY_get0_public_key.argtypes = [ctypes.c_void_p]
self.EC_KEY_get0_group = self._lib.EC_KEY_get0_group
self.EC_KEY_get0_group.restype = ctypes.c_void_p
self.EC_KEY_get0_group.argtypes = [ctypes.c_void_p]
self.EC_POINT_get_affine_coordinates_GFp = self._lib.EC_POINT_get_affine_coordinates_GFp
self.EC_POINT_get_affine_coordinates_GFp.restype = ctypes.c_int
self.EC_POINT_get_affine_coordinates_GFp.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
self.EC_KEY_set_private_key = self._lib.EC_KEY_set_private_key
self.EC_KEY_set_private_key.restype = ctypes.c_int
self.EC_KEY_set_private_key.argtypes = [ctypes.c_void_p,
ctypes.c_void_p]
self.EC_KEY_set_public_key = self._lib.EC_KEY_set_public_key
self.EC_KEY_set_public_key.restype = ctypes.c_int
self.EC_KEY_set_public_key.argtypes = [ctypes.c_void_p,
ctypes.c_void_p]
self.EC_KEY_set_group = self._lib.EC_KEY_set_group
self.EC_KEY_set_group.restype = ctypes.c_int
self.EC_KEY_set_group.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
self.EC_POINT_set_affine_coordinates_GFp = self._lib.EC_POINT_set_affine_coordinates_GFp
self.EC_POINT_set_affine_coordinates_GFp.restype = ctypes.c_int
self.EC_POINT_set_affine_coordinates_GFp.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
self.EC_POINT_new = self._lib.EC_POINT_new
self.EC_POINT_new.restype = ctypes.c_void_p
self.EC_POINT_new.argtypes = [ctypes.c_void_p]
self.EC_POINT_free = self._lib.EC_POINT_free
self.EC_POINT_free.restype = None
self.EC_POINT_free.argtypes = [ctypes.c_void_p]
self.BN_CTX_free = self._lib.BN_CTX_free
self.BN_CTX_free.restype = None
self.BN_CTX_free.argtypes = [ctypes.c_void_p]
self.EC_POINT_mul = self._lib.EC_POINT_mul
self.EC_POINT_mul.restype = None
self.EC_POINT_mul.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
self.EC_KEY_set_private_key = self._lib.EC_KEY_set_private_key
self.EC_KEY_set_private_key.restype = ctypes.c_int
self.EC_KEY_set_private_key.argtypes = [ctypes.c_void_p,
ctypes.c_void_p]
self.ECDH_OpenSSL = self._lib.ECDH_OpenSSL
self._lib.ECDH_OpenSSL.restype = ctypes.c_void_p
self._lib.ECDH_OpenSSL.argtypes = []
self.BN_CTX_new = self._lib.BN_CTX_new
self._lib.BN_CTX_new.restype = ctypes.c_void_p
self._lib.BN_CTX_new.argtypes = []
self.ECDH_set_method = self._lib.ECDH_set_method
self._lib.ECDH_set_method.restype = ctypes.c_int
self._lib.ECDH_set_method.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
self.ECDH_compute_key = self._lib.ECDH_compute_key
self.ECDH_compute_key.restype = ctypes.c_int
self.ECDH_compute_key.argtypes = [ctypes.c_void_p,
ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p]
self.EVP_CipherInit_ex = self._lib.EVP_CipherInit_ex
self.EVP_CipherInit_ex.restype = ctypes.c_int
self.EVP_CipherInit_ex.argtypes = [ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_void_p]
self.EVP_CIPHER_CTX_new = self._lib.EVP_CIPHER_CTX_new
self.EVP_CIPHER_CTX_new.restype = ctypes.c_void_p
self.EVP_CIPHER_CTX_new.argtypes = []
# Cipher
self.EVP_aes_128_cfb128 = self._lib.EVP_aes_128_cfb128
self.EVP_aes_128_cfb128.restype = ctypes.c_void_p
self.EVP_aes_128_cfb128.argtypes = []
self.EVP_aes_256_cfb128 = self._lib.EVP_aes_256_cfb128
self.EVP_aes_256_cfb128.restype = ctypes.c_void_p
self.EVP_aes_256_cfb128.argtypes = []
self.EVP_aes_128_cbc = self._lib.EVP_aes_128_cbc
self.EVP_aes_128_cbc.restype = ctypes.c_void_p
self.EVP_aes_128_cbc.argtypes = []
self.EVP_aes_256_cbc = self._lib.EVP_aes_256_cbc
self.EVP_aes_256_cbc.restype = ctypes.c_void_p
self.EVP_aes_256_cbc.argtypes = []
self.EVP_aes_128_ctr = self._lib.EVP_aes_128_ctr
self.EVP_aes_128_ctr.restype = ctypes.c_void_p
self.EVP_aes_128_ctr.argtypes = []
self.EVP_aes_256_ctr = self._lib.EVP_aes_256_ctr
self.EVP_aes_256_ctr.restype = ctypes.c_void_p
self.EVP_aes_256_ctr.argtypes = []
self.EVP_aes_128_ofb = self._lib.EVP_aes_128_ofb
self.EVP_aes_128_ofb.restype = ctypes.c_void_p
self.EVP_aes_128_ofb.argtypes = []
self.EVP_aes_256_ofb = self._lib.EVP_aes_256_ofb
self.EVP_aes_256_ofb.restype = ctypes.c_void_p
self.EVP_aes_256_ofb.argtypes = []
self.EVP_bf_cbc = self._lib.EVP_bf_cbc
self.EVP_bf_cbc.restype = ctypes.c_void_p
self.EVP_bf_cbc.argtypes = []
self.EVP_bf_cfb64 = self._lib.EVP_bf_cfb64
self.EVP_bf_cfb64.restype = ctypes.c_void_p
self.EVP_bf_cfb64.argtypes = []
self.EVP_rc4 = self._lib.EVP_rc4
self.EVP_rc4.restype = ctypes.c_void_p
self.EVP_rc4.argtypes = []
self.EVP_CIPHER_CTX_cleanup = self._lib.EVP_CIPHER_CTX_cleanup
self.EVP_CIPHER_CTX_cleanup.restype = ctypes.c_int
self.EVP_CIPHER_CTX_cleanup.argtypes = [ctypes.c_void_p]
self.EVP_CIPHER_CTX_free = self._lib.EVP_CIPHER_CTX_free
self.EVP_CIPHER_CTX_free.restype = None
self.EVP_CIPHER_CTX_free.argtypes = [ctypes.c_void_p]
self.EVP_CipherUpdate = self._lib.EVP_CipherUpdate
self.EVP_CipherUpdate.restype = ctypes.c_int
self.EVP_CipherUpdate.argtypes = [ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int]
self.EVP_CipherFinal_ex = self._lib.EVP_CipherFinal_ex
self.EVP_CipherFinal_ex.restype = ctypes.c_int
self.EVP_CipherFinal_ex.argtypes = [ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_void_p]
self.EVP_DigestInit = self._lib.EVP_DigestInit
self.EVP_DigestInit.restype = ctypes.c_int
self._lib.EVP_DigestInit.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
self.EVP_DigestUpdate = self._lib.EVP_DigestUpdate
self.EVP_DigestUpdate.restype = ctypes.c_int
self.EVP_DigestUpdate.argtypes = [ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_int]
self.EVP_DigestFinal = self._lib.EVP_DigestFinal
self.EVP_DigestFinal.restype = ctypes.c_int
self.EVP_DigestFinal.argtypes = [ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_void_p]
self.EVP_ecdsa = self._lib.EVP_ecdsa
self._lib.EVP_ecdsa.restype = ctypes.c_void_p
self._lib.EVP_ecdsa.argtypes = []
self.ECDSA_sign = self._lib.ECDSA_sign
self.ECDSA_sign.restype = ctypes.c_int
self.ECDSA_sign.argtypes = [ctypes.c_int, ctypes.c_void_p,
ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
self.ECDSA_verify = self._lib.ECDSA_verify
self.ECDSA_verify.restype = ctypes.c_int
self.ECDSA_verify.argtypes = [ctypes.c_int, ctypes.c_void_p,
ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p]
self.EVP_MD_CTX_create = self._lib.EVP_MD_CTX_create
self.EVP_MD_CTX_create.restype = ctypes.c_void_p
self.EVP_MD_CTX_create.argtypes = []
self.EVP_MD_CTX_init = self._lib.EVP_MD_CTX_init
self.EVP_MD_CTX_init.restype = None
self.EVP_MD_CTX_init.argtypes = [ctypes.c_void_p]
self.EVP_MD_CTX_destroy = self._lib.EVP_MD_CTX_destroy
self.EVP_MD_CTX_destroy.restype = None
self.EVP_MD_CTX_destroy.argtypes = [ctypes.c_void_p]
self.RAND_bytes = self._lib.RAND_bytes
self.RAND_bytes.restype = None
self.RAND_bytes.argtypes = [ctypes.c_void_p, ctypes.c_int]
self.EVP_sha256 = self._lib.EVP_sha256
self.EVP_sha256.restype = ctypes.c_void_p
self.EVP_sha256.argtypes = []
self.i2o_ECPublicKey = self._lib.i2o_ECPublicKey
self.i2o_ECPublicKey.restype = ctypes.c_void_p
self.i2o_ECPublicKey.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
self.EVP_sha512 = self._lib.EVP_sha512
self.EVP_sha512.restype = ctypes.c_void_p
self.EVP_sha512.argtypes = []
self.HMAC = self._lib.HMAC
self.HMAC.restype = ctypes.c_void_p
self.HMAC.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int,
ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p]
self.PKCS5_PBKDF2_HMAC = self._lib.PKCS5_PBKDF2_HMAC
self.PKCS5_PBKDF2_HMAC.restype = ctypes.c_int
self.PKCS5_PBKDF2_HMAC.argtypes = [ctypes.c_void_p, ctypes.c_int,
ctypes.c_void_p, ctypes.c_int,
ctypes.c_int, ctypes.c_void_p,
ctypes.c_int, ctypes.c_void_p]
self._set_ciphers()
self._set_curves()
def _set_ciphers(self):
self.cipher_algo = {
'aes-128-cbc': CipherName('aes-128-cbc', self.EVP_aes_128_cbc, 16),
'aes-256-cbc': CipherName('aes-256-cbc', self.EVP_aes_256_cbc, 16),
'aes-128-cfb': CipherName('aes-128-cfb', self.EVP_aes_128_cfb128, 16),
'aes-256-cfb': CipherName('aes-256-cfb', self.EVP_aes_256_cfb128, 16),
'aes-128-ofb': CipherName('aes-128-ofb', self._lib.EVP_aes_128_ofb, 16),
'aes-256-ofb': CipherName('aes-256-ofb', self._lib.EVP_aes_256_ofb, 16),
'aes-128-ctr': CipherName('aes-128-ctr', self._lib.EVP_aes_128_ctr, 16),
'aes-256-ctr': CipherName('aes-256-ctr', self._lib.EVP_aes_256_ctr, 16),
'bf-cfb': CipherName('bf-cfb', self.EVP_bf_cfb64, 8),
'bf-cbc': CipherName('bf-cbc', self.EVP_bf_cbc, 8),
'rc4': CipherName('rc4', self.EVP_rc4, 128), # 128 is the initialisation size not block size
}
def _set_curves(self):
self.curves = {
'secp112r1': 704,
'secp112r2': 705,
'secp128r1': 706,
'secp128r2': 707,
'secp160k1': 708,
'secp160r1': 709,
'secp160r2': 710,
'secp192k1': 711,
'secp224k1': 712,
'secp224r1': 713,
'secp256k1': 714,
'secp384r1': 715,
'secp521r1': 716,
'sect113r1': 717,
'sect113r2': 718,
'sect131r1': 719,
'sect131r2': 720,
'sect163k1': 721,
'sect163r1': 722,
'sect163r2': 723,
'sect193r1': 724,
'sect193r2': 725,
'sect233k1': 726,
'sect233r1': 727,
'sect239k1': 728,
'sect283k1': 729,
'sect283r1': 730,
'sect409k1': 731,
'sect409r1': 732,
'sect571k1': 733,
'sect571r1': 734,
}
def BN_num_bytes(self, x):
"""
returns the length of a BN (OpenSSl API)
"""
return int((self.BN_num_bits(x) + 7) / 8)
def get_cipher(self, name):
"""
returns the OpenSSL cipher instance
"""
if name not in self.cipher_algo:
raise Exception("Unknown cipher")
return self.cipher_algo[name]
def get_curve(self, name):
"""
returns the id of a elliptic curve
"""
if name not in self.curves:
raise Exception("Unknown curve")
return self.curves[name]
def get_curve_by_id(self, id):
"""
returns the name of a elliptic curve with his id
"""
res = None
for i in self.curves:
if self.curves[i] == id:
res = i
break
if res is None:
raise Exception("Unknown curve")
return res
def rand(self, size):
"""
OpenSSL random function
"""
buffer = self.malloc(0, size)
self.RAND_bytes(buffer, size)
return buffer.raw
def malloc(self, data, size):
"""
returns a create_string_buffer (ctypes)
"""
buffer = None
if data != 0:
if sys.version_info.major == 3 and isinstance(data, type('')):
data = data.encode()
buffer = self.create_string_buffer(data, size)
else:
buffer = self.create_string_buffer(size)
return buffer
try:
OpenSSL = _OpenSSL('libcrypto.so')
except:
try:
OpenSSL = _OpenSSL('libeay32.dll')
except:
try:
OpenSSL = _OpenSSL('libcrypto.dylib')
except:
try:
from os import path
lib_path = path.join(sys._MEIPASS, "libeay32.dll")
OpenSSL = _OpenSSL(lib_path)
except:
raise Exception("Couldn't load the OpenSSL library. You must install it.")