diff --git a/src/addresses.py b/src/addresses.py
index e48873a1..885c1f64 100644
--- a/src/addresses.py
+++ b/src/addresses.py
@@ -2,11 +2,16 @@
 Operations with addresses
 """
 # pylint: disable=inconsistent-return-statements
-import hashlib
+
 import logging
 from binascii import hexlify, unhexlify
 from struct import pack, unpack
 
+try:
+    from highlevelcrypto import double_sha512
+except ImportError:
+    from .highlevelcrypto import double_sha512
+
 
 logger = logging.getLogger('default')
 
@@ -134,15 +139,6 @@ def decodeVarint(data):
         return (encodedValue, 9)
 
 
-def calculateInventoryHash(data):
-    """Calculate inventory hash from object data"""
-    sha = hashlib.new('sha512')
-    sha2 = hashlib.new('sha512')
-    sha.update(data)
-    sha2.update(sha.digest())
-    return sha2.digest()[0:32]
-
-
 def encodeAddress(version, stream, ripe):
     """Convert ripe to address"""
     if version >= 2 and version < 4:
@@ -166,12 +162,7 @@ def encodeAddress(version, stream, ripe):
     storedBinaryData = encodeVarint(version) + encodeVarint(stream) + ripe
 
     # Generate the checksum
-    sha = hashlib.new('sha512')
-    sha.update(storedBinaryData)
-    currentHash = sha.digest()
-    sha = hashlib.new('sha512')
-    sha.update(currentHash)
-    checksum = sha.digest()[0:4]
+    checksum = double_sha512(storedBinaryData)[0:4]
 
     # FIXME: encodeBase58 should take binary data, to reduce conversions
     # encodeBase58(storedBinaryData + checksum)
@@ -207,13 +198,7 @@ def decodeAddress(address):
     data = unhexlify(hexdata)
     checksum = data[-4:]
 
-    sha = hashlib.new('sha512')
-    sha.update(data[:-4])
-    currentHash = sha.digest()
-    sha = hashlib.new('sha512')
-    sha.update(currentHash)
-
-    if checksum != sha.digest()[0:4]:
+    if checksum != double_sha512(data[:-4])[0:4]:
         status = 'checksumfailed'
         return status, 0, 0, ''
 
diff --git a/src/api.py b/src/api.py
index de220cc4..536768e8 100644
--- a/src/api.py
+++ b/src/api.py
@@ -71,6 +71,8 @@ from binascii import hexlify, unhexlify
 from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler, SimpleXMLRPCServer
 from struct import pack
 
+from six.moves import queue
+
 import defaults
 import helper_inbox
 import helper_sent
@@ -82,17 +84,17 @@ import shutdown
 import state
 from addresses import (
     addBMIfNotPresent,
-    calculateInventoryHash,
     decodeAddress,
     decodeVarint,
     varintDecodeError
 )
 from bmconfigparser import BMConfigParser
 from debug import logger
-from helper_sql import SqlBulkExecute, sqlExecute, sqlQuery, sqlStoredProcedure, sql_ready
+from helper_sql import (
+    SqlBulkExecute, sqlExecute, sqlQuery, sql_ready, sqlStoredProcedure)
+from highlevelcrypto import calculateInventoryHash
 from inventory import Inventory
 from network.threads import StoppableThread
-from six.moves import queue
 from version import softwareVersion
 
 try:  # TODO: write tests for XML vulnerabilities
diff --git a/src/class_addressGenerator.py b/src/class_addressGenerator.py
index 25b0c5df..06ca16d4 100644
--- a/src/class_addressGenerator.py
+++ b/src/class_addressGenerator.py
@@ -15,8 +15,6 @@ from addresses import decodeAddress, encodeAddress, encodeVarint
 from bmconfigparser import BMConfigParser
 from fallback import RIPEMD160Hash
 from network import StoppableThread
-from pyelliptic import arithmetic
-from pyelliptic.openssl import OpenSSL
 from six.moves import configparser, queue
 
 
@@ -129,17 +127,13 @@ class addressGenerator(StoppableThread):
                 # the \x00 or \x00\x00 bytes thus making the address shorter.
                 startTime = time.time()
                 numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0
-                potentialPrivSigningKey = OpenSSL.rand(32)
-                potentialPubSigningKey = highlevelcrypto.pointMult(
-                    potentialPrivSigningKey)
+                privSigningKey, pubSigningKey = highlevelcrypto.random_keys()
                 while True:
                     numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1
-                    potentialPrivEncryptionKey = OpenSSL.rand(32)
-                    potentialPubEncryptionKey = highlevelcrypto.pointMult(
-                        potentialPrivEncryptionKey)
+                    potentialPrivEncryptionKey, potentialPubEncryptionKey = \
+                        highlevelcrypto.random_keys()
                     sha = hashlib.new('sha512')
-                    sha.update(
-                        potentialPubSigningKey + potentialPubEncryptionKey)
+                    sha.update(pubSigningKey + potentialPubEncryptionKey)
                     ripe = RIPEMD160Hash(sha.digest()).digest()
                     if (
                         ripe[:numberOfNullBytesDemandedOnFrontOfRipeHash]
@@ -163,20 +157,10 @@ class addressGenerator(StoppableThread):
                 address = encodeAddress(
                     addressVersionNumber, streamNumber, ripe)
 
-                # An excellent way for us to store our keys
-                # is in Wallet Import Format. Let us convert now.
-                # https://en.bitcoin.it/wiki/Wallet_import_format
-                privSigningKey = b'\x80' + potentialPrivSigningKey
-                checksum = hashlib.sha256(hashlib.sha256(
-                    privSigningKey).digest()).digest()[0:4]
-                privSigningKeyWIF = arithmetic.changebase(
-                    privSigningKey + checksum, 256, 58)
-
-                privEncryptionKey = b'\x80' + potentialPrivEncryptionKey
-                checksum = hashlib.sha256(hashlib.sha256(
-                    privEncryptionKey).digest()).digest()[0:4]
-                privEncryptionKeyWIF = arithmetic.changebase(
-                    privEncryptionKey + checksum, 256, 58)
+                privSigningKeyWIF = highlevelcrypto.encodeWalletImportFormat(
+                    privSigningKey)
+                privEncryptionKeyWIF = highlevelcrypto.encodeWalletImportFormat(
+                    potentialPrivEncryptionKey)
 
                 BMConfigParser().add_section(address)
                 BMConfigParser().set(address, 'label', label)
@@ -246,18 +230,15 @@ class addressGenerator(StoppableThread):
                     numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix = 0
                     while True:
                         numberOfAddressesWeHadToMakeBeforeWeFoundOneWithTheCorrectRipePrefix += 1
-                        potentialPrivSigningKey = hashlib.sha512(
-                            deterministicPassphrase
-                            + encodeVarint(signingKeyNonce)
-                        ).digest()[:32]
-                        potentialPrivEncryptionKey = hashlib.sha512(
-                            deterministicPassphrase
-                            + encodeVarint(encryptionKeyNonce)
-                        ).digest()[:32]
-                        potentialPubSigningKey = highlevelcrypto.pointMult(
-                            potentialPrivSigningKey)
-                        potentialPubEncryptionKey = highlevelcrypto.pointMult(
-                            potentialPrivEncryptionKey)
+                        potentialPrivSigningKey, potentialPubSigningKey = \
+                            highlevelcrypto.deterministic_keys(
+                                deterministicPassphrase,
+                                encodeVarint(signingKeyNonce))
+                        potentialPrivEncryptionKey, potentialPubEncryptionKey = \
+                            highlevelcrypto.deterministic_keys(
+                                deterministicPassphrase,
+                                encodeVarint(encryptionKeyNonce))
+
                         signingKeyNonce += 2
                         encryptionKeyNonce += 2
                         sha = hashlib.new('sha512')
@@ -300,21 +281,12 @@ class addressGenerator(StoppableThread):
                         saveAddressToDisk = False
 
                     if saveAddressToDisk and live:
-                        # An excellent way for us to store our keys is
-                        # in Wallet Import Format. Let us convert now.
-                        # https://en.bitcoin.it/wiki/Wallet_import_format
-                        privSigningKey = b'\x80' + potentialPrivSigningKey
-                        checksum = hashlib.sha256(hashlib.sha256(
-                            privSigningKey).digest()).digest()[0:4]
-                        privSigningKeyWIF = arithmetic.changebase(
-                            privSigningKey + checksum, 256, 58)
-
-                        privEncryptionKey = b'\x80' + \
-                            potentialPrivEncryptionKey
-                        checksum = hashlib.sha256(hashlib.sha256(
-                            privEncryptionKey).digest()).digest()[0:4]
-                        privEncryptionKeyWIF = arithmetic.changebase(
-                            privEncryptionKey + checksum, 256, 58)
+                        privSigningKeyWIF = \
+                            highlevelcrypto.encodeWalletImportFormat(
+                                potentialPrivSigningKey)
+                        privEncryptionKeyWIF = \
+                            highlevelcrypto.encodeWalletImportFormat(
+                                potentialPrivEncryptionKey)
 
                         try:
                             BMConfigParser().add_section(address)
@@ -367,10 +339,10 @@ class addressGenerator(StoppableThread):
                                 highlevelcrypto.makeCryptor(
                                     hexlify(potentialPrivEncryptionKey))
                             shared.myAddressesByHash[ripe] = address
-                            tag = hashlib.sha512(hashlib.sha512(
+                            tag = highlevelcrypto.double_sha512(
                                 encodeVarint(addressVersionNumber)
                                 + encodeVarint(streamNumber) + ripe
-                            ).digest()).digest()[32:]
+                            )[32:]
                             shared.myAddressesByTag[tag] = address
                             if addressVersionNumber == 3:
                                 # If this is a chan address,
diff --git a/src/class_objectProcessor.py b/src/class_objectProcessor.py
index 1bacf639..86ed2bcc 100644
--- a/src/class_objectProcessor.py
+++ b/src/class_objectProcessor.py
@@ -23,7 +23,7 @@ import queues
 import shared
 import state
 from addresses import (
-    calculateInventoryHash, decodeAddress, decodeVarint,
+    decodeAddress, decodeVarint,
     encodeAddress, encodeVarint, varintDecodeError
 )
 from bmconfigparser import BMConfigParser
@@ -450,7 +450,7 @@ class objectProcessor(threading.Thread):
         streamNumberAsClaimedByMsg, streamNumberAsClaimedByMsgLength = \
             decodeVarint(data[readPosition:readPosition + 9])
         readPosition += streamNumberAsClaimedByMsgLength
-        inventoryHash = calculateInventoryHash(data)
+        inventoryHash = highlevelcrypto.calculateInventoryHash(data)
         initialDecryptionSuccessful = False
 
         # This is not an acknowledgement bound for me. See if it is a message
@@ -580,8 +580,7 @@ class objectProcessor(threading.Thread):
                 helper_bitcoin.calculateTestnetAddressFromPubkey(pubSigningKey)
             )
         # Used to detect and ignore duplicate messages in our inbox
-        sigHash = hashlib.sha512(
-            hashlib.sha512(signature).digest()).digest()[32:]
+        sigHash = highlevelcrypto.double_sha512(signature)[32:]
 
         # calculate the fromRipe.
         sha = hashlib.new('sha512')
@@ -751,7 +750,7 @@ class objectProcessor(threading.Thread):
         state.numberOfBroadcastsProcessed += 1
         queues.UISignalQueue.put((
             'updateNumberOfBroadcastsProcessed', 'no data'))
-        inventoryHash = calculateInventoryHash(data)
+        inventoryHash = highlevelcrypto.calculateInventoryHash(data)
         readPosition = 20  # bypass the nonce, time, and object type
         broadcastVersion, broadcastVersionLength = decodeVarint(
             data[readPosition:readPosition + 9])
@@ -885,10 +884,10 @@ class objectProcessor(threading.Thread):
                     ' itself. Ignoring message.'
                 )
         elif broadcastVersion == 5:
-            calculatedTag = hashlib.sha512(hashlib.sha512(
+            calculatedTag = highlevelcrypto.double_sha512(
                 encodeVarint(sendersAddressVersion)
                 + encodeVarint(sendersStream) + calculatedRipe
-            ).digest()).digest()[32:]
+            )[32:]
             if calculatedTag != embeddedTag:
                 return logger.debug(
                     'The tag and encryption key used to encrypt this'
@@ -918,8 +917,7 @@ class objectProcessor(threading.Thread):
             return
         logger.debug('ECDSA verify passed')
         # Used to detect and ignore duplicate messages in our inbox
-        sigHash = hashlib.sha512(
-            hashlib.sha512(signature).digest()).digest()[32:]
+        sigHash = highlevelcrypto.double_sha512(signature)[32:]
 
         fromAddress = encodeAddress(
             sendersAddressVersion, sendersStream, calculatedRipe)
@@ -993,10 +991,10 @@ class objectProcessor(threading.Thread):
         # Let us create the tag from the address and see if we were waiting
         # for it.
         elif addressVersion >= 4:
-            tag = hashlib.sha512(hashlib.sha512(
+            tag = highlevelcrypto.double_sha512(
                 encodeVarint(addressVersion) + encodeVarint(streamNumber)
                 + ripe
-            ).digest()).digest()[32:]
+            )[32:]
             if tag in state.neededPubkeys:
                 del state.neededPubkeys[tag]
                 self.sendMessages(address)
diff --git a/src/class_singleWorker.py b/src/class_singleWorker.py
index fea842ea..c3230107 100644
--- a/src/class_singleWorker.py
+++ b/src/class_singleWorker.py
@@ -25,9 +25,7 @@ import queues
 import shared
 import state
 import tr
-from addresses import (
-    calculateInventoryHash, decodeAddress, decodeVarint, encodeVarint
-)
+from addresses import decodeAddress, decodeVarint, encodeVarint
 from bmconfigparser import BMConfigParser
 from helper_sql import sqlExecute, sqlQuery
 from inventory import Inventory
@@ -50,6 +48,8 @@ class singleWorker(StoppableThread):
 
     def __init__(self):
         super(singleWorker, self).__init__(name="singleWorker")
+        self.digestAlg = BMConfigParser().safeGet(
+            'bitmessagesettings', 'digestalg', 'sha256')
         proofofwork.init()
 
     def stopThread(self):
@@ -73,18 +73,16 @@ class singleWorker(StoppableThread):
         queryreturn = sqlQuery(
             '''SELECT DISTINCT toaddress FROM sent'''
             ''' WHERE (status='awaitingpubkey' AND folder='sent')''')
-        for row in queryreturn:
-            toAddress, = row
-            # toStatus
-            _, toAddressVersionNumber, toStreamNumber, toRipe = \
-                decodeAddress(toAddress)
+        for toAddress, in queryreturn:
+            toAddressVersionNumber, toStreamNumber, toRipe = \
+                decodeAddress(toAddress)[1:]
             if toAddressVersionNumber <= 3:
                 state.neededPubkeys[toAddress] = 0
             elif toAddressVersionNumber >= 4:
-                doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(
+                doubleHashOfAddressData = highlevelcrypto.double_sha512(
                     encodeVarint(toAddressVersionNumber)
                     + encodeVarint(toStreamNumber) + toRipe
-                ).digest()).digest()
+                )
                 # Note that this is the first half of the sha512 hash.
                 privEncryptionKey = doubleHashOfAddressData[:32]
                 tag = doubleHashOfAddressData[32:]
@@ -195,15 +193,20 @@ class singleWorker(StoppableThread):
         self.logger.info("Quitting...")
 
     def _getKeysForAddress(self, address):
-        privSigningKeyBase58 = BMConfigParser().get(
-            address, 'privsigningkey')
-        privEncryptionKeyBase58 = BMConfigParser().get(
-            address, 'privencryptionkey')
+        try:
+            privSigningKeyBase58 = BMConfigParser().get(
+                address, 'privsigningkey')
+            privEncryptionKeyBase58 = BMConfigParser().get(
+                address, 'privencryptionkey')
+        except (configparser.NoSectionError, configparser.NoOptionError):
+            self.logger.error(
+                'Could not read or decode privkey for address %s', address)
+            raise ValueError
 
-        privSigningKeyHex = hexlify(shared.decodeWalletImportFormat(
-            privSigningKeyBase58))
-        privEncryptionKeyHex = hexlify(shared.decodeWalletImportFormat(
-            privEncryptionKeyBase58))
+        privSigningKeyHex = hexlify(
+            highlevelcrypto.decodeWalletImportFormat(privSigningKeyBase58))
+        privEncryptionKeyHex = hexlify(
+            highlevelcrypto.decodeWalletImportFormat(privEncryptionKeyBase58))
 
         # The \x04 on the beginning of the public keys are not sent.
         # This way there is only one acceptable way to encode
@@ -254,9 +257,7 @@ class singleWorker(StoppableThread):
         message once it is done with the POW"""
         # Look up my stream number based on my address hash
         myAddress = shared.myAddressesByHash[adressHash]
-        # status
-        _, addressVersionNumber, streamNumber, adressHash = (
-            decodeAddress(myAddress))
+        addressVersionNumber, streamNumber = decodeAddress(myAddress)[1:3]
 
         # 28 days from now plus or minus five minutes
         TTL = int(28 * 24 * 60 * 60 + helper_random.randomrandrange(-300, 300))
@@ -269,18 +270,15 @@ class singleWorker(StoppableThread):
         payload += protocol.getBitfield(myAddress)
 
         try:
-            # privSigningKeyHex, privEncryptionKeyHex
-            _, _, pubSigningKey, pubEncryptionKey = \
-                self._getKeysForAddress(myAddress)
-        except (configparser.NoSectionError, configparser.NoOptionError) as err:
-            self.logger.warning("Section or Option did not found: %s", err)
-        except Exception as err:
-            self.logger.error(
+            pubSigningKey, pubEncryptionKey = self._getKeysForAddress(
+                myAddress)[2:]
+        except ValueError:
+            return
+        except Exception:
+            return self.logger.error(
                 'Error within doPOWForMyV2Pubkey. Could not read'
                 ' the keys from the keys.dat file for a requested'
-                ' address. %s\n', err
-            )
-            return
+                ' address. %s\n', exc_info=True)
 
         payload += pubSigningKey + pubEncryptionKey
 
@@ -288,7 +286,7 @@ class singleWorker(StoppableThread):
         payload = self._doPOWDefaults(
             payload, TTL, log_prefix='(For pubkey message)')
 
-        inventoryHash = calculateInventoryHash(payload)
+        inventoryHash = highlevelcrypto.calculateInventoryHash(payload)
         objectType = 1
         Inventory()[inventoryHash] = (
             objectType, streamNumber, payload, embeddedTime, '')
@@ -318,9 +316,8 @@ class singleWorker(StoppableThread):
         try:
             myAddress = shared.myAddressesByHash[adressHash]
         except KeyError:
-            # The address has been deleted.
-            self.logger.warning("Can't find %s in myAddressByHash", hexlify(adressHash))
-            return
+            return self.logger.warning(  # The address has been deleted.
+                "Can't find %s in myAddressByHash", hexlify(adressHash))
         if BMConfigParser().safeGetBoolean(myAddress, 'chan'):
             self.logger.info('This is a chan address. Not sending pubkey.')
             return
@@ -351,15 +348,13 @@ class singleWorker(StoppableThread):
             # , privEncryptionKeyHex
             privSigningKeyHex, _, pubSigningKey, pubEncryptionKey = \
                 self._getKeysForAddress(myAddress)
-        except (configparser.NoSectionError, configparser.NoOptionError) as err:
-            self.logger.warning("Section or Option did not found: %s", err)
-        except Exception as err:
-            self.logger.error(
+        except ValueError:
+            return
+        except Exception:
+            return self.logger.error(
                 'Error within sendOutOrStoreMyV3Pubkey. Could not read'
                 ' the keys from the keys.dat file for a requested'
-                ' address. %s\n', err
-            )
-            return
+                ' address. %s\n', exc_info=True)
 
         payload += pubSigningKey + pubEncryptionKey
 
@@ -368,7 +363,8 @@ class singleWorker(StoppableThread):
         payload += encodeVarint(BMConfigParser().getint(
             myAddress, 'payloadlengthextrabytes'))
 
-        signature = highlevelcrypto.sign(payload, privSigningKeyHex)
+        signature = highlevelcrypto.sign(
+            payload, privSigningKeyHex, self.digestAlg)
         payload += encodeVarint(len(signature))
         payload += signature
 
@@ -376,7 +372,7 @@ class singleWorker(StoppableThread):
         payload = self._doPOWDefaults(
             payload, TTL, log_prefix='(For pubkey message)')
 
-        inventoryHash = calculateInventoryHash(payload)
+        inventoryHash = highlevelcrypto.calculateInventoryHash(payload)
         objectType = 1
         Inventory()[inventoryHash] = (
             objectType, streamNumber, payload, embeddedTime, '')
@@ -425,15 +421,13 @@ class singleWorker(StoppableThread):
             # , privEncryptionKeyHex
             privSigningKeyHex, _, pubSigningKey, pubEncryptionKey = \
                 self._getKeysForAddress(myAddress)
-        except (configparser.NoSectionError, configparser.NoOptionError) as err:
-            self.logger.warning("Section or Option did not found: %s", err)
-        except Exception as err:
-            self.logger.error(
+        except ValueError:
+            return
+        except Exception:
+            return self.logger.error(
                 'Error within sendOutOrStoreMyV4Pubkey. Could not read'
                 ' the keys from the keys.dat file for a requested'
-                ' address. %s\n', err
-            )
-            return
+                ' address. %s\n', exc_info=True)
 
         dataToEncrypt += pubSigningKey + pubEncryptionKey
 
@@ -449,14 +443,13 @@ class singleWorker(StoppableThread):
         # unencrypted, the pubkey with part of the hash so that nodes
         # know which pubkey object to try to decrypt
         # when they want to send a message.
-        doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(
+        doubleHashOfAddressData = highlevelcrypto.double_sha512(
             encodeVarint(addressVersionNumber)
             + encodeVarint(streamNumber) + addressHash
-        ).digest()).digest()
+        )
         payload += doubleHashOfAddressData[32:]  # the tag
         signature = highlevelcrypto.sign(
-            payload + dataToEncrypt, privSigningKeyHex
-        )
+            payload + dataToEncrypt, privSigningKeyHex, self.digestAlg)
         dataToEncrypt += encodeVarint(len(signature))
         dataToEncrypt += signature
 
@@ -469,7 +462,7 @@ class singleWorker(StoppableThread):
         payload = self._doPOWDefaults(
             payload, TTL, log_prefix='(For pubkey message)')
 
-        inventoryHash = calculateInventoryHash(payload)
+        inventoryHash = highlevelcrypto.calculateInventoryHash(payload)
         objectType = 1
         Inventory()[inventoryHash] = (
             objectType, streamNumber, payload, embeddedTime,
@@ -505,7 +498,7 @@ class singleWorker(StoppableThread):
         objectType = protocol.OBJECT_ONIONPEER
         # FIXME: ideally the objectPayload should be signed
         objectPayload = encodeVarint(peer.port) + protocol.encodeHost(peer.host)
-        tag = calculateInventoryHash(objectPayload)
+        tag = highlevelcrypto.calculateInventoryHash(objectPayload)
 
         if Inventory().by_type_and_tag(objectType, tag):
             return  # not expired
@@ -519,7 +512,7 @@ class singleWorker(StoppableThread):
         payload = self._doPOWDefaults(
             payload, TTL, log_prefix='(For onionpeer object)')
 
-        inventoryHash = calculateInventoryHash(payload)
+        inventoryHash = highlevelcrypto.calculateInventoryHash(payload)
         Inventory()[inventoryHash] = (
             objectType, streamNumber, buffer(payload),
             embeddedTime, buffer(tag)
@@ -613,10 +606,10 @@ class singleWorker(StoppableThread):
 
             payload += encodeVarint(streamNumber)
             if addressVersionNumber >= 4:
-                doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(
+                doubleHashOfAddressData = highlevelcrypto.double_sha512(
                     encodeVarint(addressVersionNumber)
                     + encodeVarint(streamNumber) + ripe
-                ).digest()).digest()
+                )
                 tag = doubleHashOfAddressData[32:]
                 payload += tag
             else:
@@ -641,7 +634,7 @@ class singleWorker(StoppableThread):
             dataToSign = payload + dataToEncrypt
 
             signature = highlevelcrypto.sign(
-                dataToSign, privSigningKeyHex)
+                dataToSign, privSigningKeyHex, self.digestAlg)
             dataToEncrypt += encodeVarint(len(signature))
             dataToEncrypt += signature
 
@@ -686,7 +679,7 @@ class singleWorker(StoppableThread):
                 )
                 continue
 
-            inventoryHash = calculateInventoryHash(payload)
+            inventoryHash = highlevelcrypto.calculateInventoryHash(payload)
             objectType = 3
             Inventory()[inventoryHash] = (
                 objectType, streamNumber, payload, embeddedTime, tag)
@@ -795,10 +788,10 @@ class singleWorker(StoppableThread):
                     if toAddressVersionNumber <= 3:
                         toTag = ''
                     else:
-                        toTag = hashlib.sha512(hashlib.sha512(
+                        toTag = highlevelcrypto.double_sha512(
                             encodeVarint(toAddressVersionNumber)
                             + encodeVarint(toStreamNumber) + toRipe
-                        ).digest()).digest()[32:]
+                        )[32:]
                     if toaddress in state.neededPubkeys or \
                             toTag in state.neededPubkeys:
                         # We already sent a request for the pubkey
@@ -832,11 +825,11 @@ class singleWorker(StoppableThread):
                         # already contains the toAddress and cryptor
                         # object associated with the tag for this toAddress.
                         if toAddressVersionNumber >= 4:
-                            doubleHashOfToAddressData = hashlib.sha512(
-                                hashlib.sha512(
-                                    encodeVarint(toAddressVersionNumber) + encodeVarint(toStreamNumber) + toRipe
-                                ).digest()
-                            ).digest()
+                            doubleHashOfToAddressData = \
+                                highlevelcrypto.double_sha512(
+                                    encodeVarint(toAddressVersionNumber)
+                                    + encodeVarint(toStreamNumber) + toRipe
+                                )
                             # The first half of the sha512 hash.
                             privEncryptionKey = doubleHashOfToAddressData[:32]
                             # The second half of the sha512 hash.
@@ -1116,8 +1109,9 @@ class singleWorker(StoppableThread):
                         ' from the keys.dat file for our own address. %s\n',
                         err)
                     continue
-                privEncryptionKeyHex = hexlify(shared.decodeWalletImportFormat(
-                    privEncryptionKeyBase58))
+                privEncryptionKeyHex = hexlify(
+                    highlevelcrypto.decodeWalletImportFormat(
+                        privEncryptionKeyBase58))
                 pubEncryptionKeyBase256 = unhexlify(highlevelcrypto.privToPub(
                     privEncryptionKeyHex))[1:]
                 requiredAverageProofOfWorkNonceTrialsPerByte = \
@@ -1223,7 +1217,8 @@ class singleWorker(StoppableThread):
             payload += fullAckPayload
             dataToSign = pack('>Q', embeddedTime) + '\x00\x00\x00\x02' + \
                 encodeVarint(1) + encodeVarint(toStreamNumber) + payload
-            signature = highlevelcrypto.sign(dataToSign, privSigningKeyHex)
+            signature = highlevelcrypto.sign(
+                dataToSign, privSigningKeyHex, self.digestAlg)
             payload += encodeVarint(len(signature))
             payload += signature
 
@@ -1301,7 +1296,7 @@ class singleWorker(StoppableThread):
                 )
                 continue
 
-            inventoryHash = calculateInventoryHash(encryptedPayload)
+            inventoryHash = highlevelcrypto.calculateInventoryHash(encryptedPayload)
             objectType = 2
             Inventory()[inventoryHash] = (
                 objectType, toStreamNumber, encryptedPayload, embeddedTime, '')
@@ -1351,8 +1346,7 @@ class singleWorker(StoppableThread):
             # the message in our own inbox.
             if BMConfigParser().has_section(toaddress):
                 # Used to detect and ignore duplicate messages in our inbox
-                sigHash = hashlib.sha512(hashlib.sha512(
-                    signature).digest()).digest()[32:]
+                sigHash = highlevelcrypto.double_sha512(signature)[32:]
                 t = (inventoryHash, toaddress, fromaddress, subject, int(
                     time.time()), message, 'inbox', encoding, 0, sigHash)
                 helper_inbox.insert(t)
@@ -1407,16 +1401,13 @@ class singleWorker(StoppableThread):
             # neededPubkeys dictionary. But if we are recovering
             # from a restart of the client then we have to put it in now.
 
-            # Note that this is the first half of the sha512 hash.
-            privEncryptionKey = hashlib.sha512(hashlib.sha512(
+            doubleHashOfAddressData = highlevelcrypto.double_sha512(
                 encodeVarint(addressVersionNumber)
                 + encodeVarint(streamNumber) + ripe
-            ).digest()).digest()[:32]
+            )
+            privEncryptionKey = doubleHashOfAddressData[:32]
             # Note that this is the second half of the sha512 hash.
-            tag = hashlib.sha512(hashlib.sha512(
-                encodeVarint(addressVersionNumber)
-                + encodeVarint(streamNumber) + ripe
-            ).digest()).digest()[32:]
+            tag = doubleHashOfAddressData[32:]
             if tag not in state.neededPubkeys:
                 # We'll need this for when we receive a pubkey reply:
                 # it will be encrypted and we'll need to decrypt it.
@@ -1459,7 +1450,7 @@ class singleWorker(StoppableThread):
 
         payload = self._doPOWDefaults(payload, TTL)
 
-        inventoryHash = calculateInventoryHash(payload)
+        inventoryHash = highlevelcrypto.calculateInventoryHash(payload)
         objectType = 1
         Inventory()[inventoryHash] = (
             objectType, streamNumber, payload, embeddedTime, '')
diff --git a/src/helper_ackPayload.py b/src/helper_ackPayload.py
index d30f4c0d..1c5ddf98 100644
--- a/src/helper_ackPayload.py
+++ b/src/helper_ackPayload.py
@@ -22,26 +22,26 @@ def genAckPayload(streamNumber=1, stealthLevel=0):
        - level 1: a getpubkey request for a (random) dummy key hash
        - level 2: a standard message, encrypted to a random pubkey
     """
-    if stealthLevel == 2:      # Generate privacy-enhanced payload
+    if stealthLevel == 2:  # Generate privacy-enhanced payload
         # Generate a dummy privkey and derive the pubkey
         dummyPubKeyHex = highlevelcrypto.privToPub(
-            hexlify(helper_random.randomBytes(32)))
+            hexlify(highlevelcrypto.randomBytes(32)))
         # Generate a dummy message of random length
         # (the smallest possible standard-formatted message is 234 bytes)
-        dummyMessage = helper_random.randomBytes(
+        dummyMessage = highlevelcrypto.randomBytes(
             helper_random.randomrandrange(234, 801))
         # Encrypt the message using standard BM encryption (ECIES)
         ackdata = highlevelcrypto.encrypt(dummyMessage, dummyPubKeyHex)
         acktype = 2  # message
         version = 1
 
-    elif stealthLevel == 1:    # Basic privacy payload (random getpubkey)
-        ackdata = helper_random.randomBytes(32)
+    elif stealthLevel == 1:  # Basic privacy payload (random getpubkey)
+        ackdata = highlevelcrypto.randomBytes(32)
         acktype = 0  # getpubkey
         version = 4
 
     else:            # Minimum viable payload (non stealth)
-        ackdata = helper_random.randomBytes(32)
+        ackdata = highlevelcrypto.randomBytes(32)
         acktype = 2  # message
         version = 1
 
diff --git a/src/helper_random.py b/src/helper_random.py
index 2e6a151b..e6da707e 100644
--- a/src/helper_random.py
+++ b/src/helper_random.py
@@ -1,12 +1,7 @@
 """Convenience functions for random operations. Not suitable for security / cryptography operations."""
 
-import os
 import random
 
-try:
-    from pyelliptic.openssl import OpenSSL
-except ImportError:
-    from .pyelliptic.openssl import OpenSSL
 
 NoneType = type(None)
 
@@ -16,14 +11,6 @@ def seed():
     random.seed()
 
 
-def randomBytes(n):
-    """Method randomBytes."""
-    try:
-        return os.urandom(n)
-    except NotImplementedError:
-        return OpenSSL.rand(n)
-
-
 def randomshuffle(population):
     """Method randomShuffle.
 
diff --git a/src/highlevelcrypto.py b/src/highlevelcrypto.py
index 82743acf..cd105763 100644
--- a/src/highlevelcrypto.py
+++ b/src/highlevelcrypto.py
@@ -7,17 +7,85 @@ High level cryptographic functions based on `.pyelliptic` OpenSSL bindings.
   `More discussion. <https://github.com/yann2192/pyelliptic/issues/32>`_
 """
 
+import hashlib
+import os
 from binascii import hexlify
 
 import pyelliptic
 from pyelliptic import OpenSSL
 from pyelliptic import arithmetic as a
 
-from bmconfigparser import BMConfigParser
 
 __all__ = ['encrypt', 'makeCryptor', 'pointMult', 'privToPub', 'sign', 'verify']
 
 
+# Hashes
+
+def double_sha512(data):
+    """Binary double SHA512 digest"""
+    return hashlib.sha512(hashlib.sha512(data).digest()).digest()
+
+
+def calculateInventoryHash(data):
+    """Calculate inventory hash from object data"""
+    return double_sha512(data)[:32]
+
+
+# WIF (uses arithmetic ):
+def decodeWalletImportFormat(WIFstring):
+    """
+    Convert private key from base58 that's used in the config file to
+    8-bit binary string.
+    """
+    fullString = a.changebase(WIFstring, 58, 256)
+    privkey = fullString[:-4]
+    if fullString[-4:] != \
+       hashlib.sha256(hashlib.sha256(privkey).digest()).digest()[:4]:
+        raise ValueError('Checksum failed')
+    elif privkey[0:1] == b'\x80':  # checksum passed
+        return privkey[1:]
+
+    raise ValueError('No hex 80 prefix')
+
+
+# An excellent way for us to store our keys
+# is in Wallet Import Format. Let us convert now.
+# https://en.bitcoin.it/wiki/Wallet_import_format
+def encodeWalletImportFormat(privKey):
+    """
+    Convert private key from binary 8-bit string into base58check WIF string.
+    """
+    privKey = b'\x80' + privKey
+    checksum = hashlib.sha256(hashlib.sha256(privKey).digest()).digest()[0:4]
+    return a.changebase(privKey + checksum, 256, 58)
+
+
+# Random
+
+def randomBytes(n):
+    """Get n random bytes"""
+    try:
+        return os.urandom(n)
+    except NotImplementedError:
+        return OpenSSL.rand(n)
+
+
+# Keys
+
+def random_keys():
+    """Return a pair of keys, private and public"""
+    priv = randomBytes(32)
+    pub = pointMult(priv)
+    return priv, pub
+
+
+def deterministic_keys(passphrase, nonce):
+    """Generate keys from *passphrase* and *nonce* (encoded as varint)"""
+    priv = hashlib.sha512(passphrase + nonce).digest()[:32]
+    pub = pointMult(priv)
+    return priv, pub
+
+
 def makeCryptor(privkey):
     """Return a private `.pyelliptic.ECC` instance"""
     private_key = a.changebase(privkey, 16, 256, minlen=32)
@@ -67,22 +135,17 @@ def decryptFast(msg, cryptor):
     return cryptor.decrypt(msg)
 
 
-def sign(msg, hexPrivkey):
+def sign(msg, hexPrivkey, digestAlg="sha256"):
     """
     Signs with hex private key using SHA1 or SHA256 depending on
-    "digestalg" setting
+    *digestAlg* keyword.
     """
-    digestAlg = BMConfigParser().safeGet(
-        'bitmessagesettings', 'digestalg', 'sha256')
-    if digestAlg == "sha1":
-        # SHA1, this will eventually be deprecated
-        return makeCryptor(hexPrivkey).sign(
-            msg, digest_alg=OpenSSL.digest_ecdsa_sha1)
-    elif digestAlg == "sha256":
-        # SHA256. Eventually this will become the default
-        return makeCryptor(hexPrivkey).sign(msg, digest_alg=OpenSSL.EVP_sha256)
-    else:
+    if digestAlg not in ("sha1", "sha256"):
         raise ValueError("Unknown digest algorithm %s" % digestAlg)
+    # SHA1, this will eventually be deprecated
+    return makeCryptor(hexPrivkey).sign(
+        msg, digest_alg=OpenSSL.digest_ecdsa_sha1
+        if digestAlg == "sha1" else OpenSSL.EVP_sha256)
 
 
 def verify(msg, sig, hexPubkey):
diff --git a/src/network/bmobject.py b/src/network/bmobject.py
index 12b997d7..49e3c2de 100644
--- a/src/network/bmobject.py
+++ b/src/network/bmobject.py
@@ -6,7 +6,7 @@ import time
 
 import protocol
 import state
-from addresses import calculateInventoryHash
+from highlevelcrypto import calculateInventoryHash
 from inventory import Inventory
 from network.dandelion import Dandelion
 
diff --git a/src/network/tcp.py b/src/network/tcp.py
index ff778378..77e8ba65 100644
--- a/src/network/tcp.py
+++ b/src/network/tcp.py
@@ -17,7 +17,7 @@ import knownnodes
 import protocol
 import state
 from bmconfigparser import BMConfigParser
-from helper_random import randomBytes
+from highlevelcrypto import randomBytes
 from inventory import Inventory
 from network.advanceddispatcher import AdvancedDispatcher
 from network.assemble import assemble_addr
diff --git a/src/proofofwork.py b/src/proofofwork.py
index 148d6734..69b04e2d 100644
--- a/src/proofofwork.py
+++ b/src/proofofwork.py
@@ -4,7 +4,6 @@ Proof of work calculation
 """
 
 import ctypes
-import hashlib
 import os
 import sys
 import tempfile
@@ -12,6 +11,7 @@ import time
 from struct import pack, unpack
 from subprocess import call
 
+import highlevelcrypto
 import openclpow
 import paths
 import queues
@@ -87,13 +87,20 @@ def _set_idle():
             pass
 
 
+def trial_value(nonce, initialHash):
+    """Calculate PoW trial value"""
+    trialValue, = unpack(
+        '>Q', highlevelcrypto.double_sha512(
+            pack('>Q', nonce) + initialHash)[0:8])
+    return trialValue
+
+
 def _pool_worker(nonce, initialHash, target, pool_size):
     _set_idle()
     trialValue = float('inf')
     while trialValue > target:
         nonce += pool_size
-        trialValue, = unpack('>Q', hashlib.sha512(hashlib.sha512(
-            pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
+        trialValue = trial_value(nonce, initialHash)
     return [trialValue, nonce]
 
 
@@ -103,10 +110,9 @@ def _doSafePoW(target, initialHash):
     trialValue = float('inf')
     while trialValue > target and state.shutdown == 0:
         nonce += 1
-        trialValue, = unpack('>Q', hashlib.sha512(hashlib.sha512(
-            pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
+        trialValue = trial_value(nonce, initialHash)
     if state.shutdown != 0:
-        raise StopIteration("Interrupted")  # pylint: misplaced-bare-raise
+        raise StopIteration("Interrupted")
     logger.debug("Safe PoW done")
     return [trialValue, nonce]
 
@@ -163,7 +169,7 @@ def _doCPoW(target, initialHash):
         logger.debug("C PoW start")
         nonce = bmpow(out_h, out_m)
 
-    trialValue, = unpack('>Q', hashlib.sha512(hashlib.sha512(pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
+    trialValue = trial_value(nonce, initialHash)
     if state.shutdown != 0:
         raise StopIteration("Interrupted")
     logger.debug("C PoW done")
@@ -173,7 +179,7 @@ def _doCPoW(target, initialHash):
 def _doGPUPoW(target, initialHash):
     logger.debug("GPU PoW start")
     nonce = openclpow.do_opencl_pow(initialHash.encode("hex"), target)
-    trialValue, = unpack('>Q', hashlib.sha512(hashlib.sha512(pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
+    trialValue = trial_value(nonce, initialHash)
     if trialValue > target:
         deviceNames = ", ".join(gpu.name for gpu in openclpow.enabledGpus)
         queues.UISignalQueue.put((
diff --git a/src/protocol.py b/src/protocol.py
index 1934d9cc..ac00c1e2 100644
--- a/src/protocol.py
+++ b/src/protocol.py
@@ -269,12 +269,11 @@ def isProofOfWorkSufficient(
     if payloadLengthExtraBytes < defaults.networkDefaultPayloadLengthExtraBytes:
         payloadLengthExtraBytes = defaults.networkDefaultPayloadLengthExtraBytes
     endOfLifeTime, = unpack('>Q', data[8:16])
-    TTL = endOfLifeTime - (int(recvTime) if recvTime else int(time.time()))
+    TTL = endOfLifeTime - int(recvTime if recvTime else time.time())
     if TTL < 300:
         TTL = 300
-    POW, = unpack('>Q', hashlib.sha512(hashlib.sha512(
-        data[:8] + hashlib.sha512(data[8:]).digest()
-    ).digest()).digest()[0:8])
+    POW, = unpack('>Q', highlevelcrypto.double_sha512(
+        data[:8] + hashlib.sha512(data[8:]).digest())[0:8])
     return POW <= 2 ** 64 / (
         nonceTrialsPerByte * (
             len(data) + payloadLengthExtraBytes
diff --git a/src/pyelliptic/tests/test_arithmetic.py b/src/pyelliptic/tests/test_arithmetic.py
index 7b5c59b1..dbbceeda 100644
--- a/src/pyelliptic/tests/test_arithmetic.py
+++ b/src/pyelliptic/tests/test_arithmetic.py
@@ -23,6 +23,12 @@ sample_privsigningkey = \
 sample_privencryptionkey = \
     b'4b0b73a54e19b059dc274ab69df095fe699f43b17397bca26fdf40f4d7400a3a'
 
+# [chan] bitmessage
+sample_wif_privsigningkey = \
+    b'a2e8b841a531c1c558ee0680c396789c7a2ea3ac4795ae3f000caf9fe367d144'
+sample_wif_privencryptionkey = \
+    b'114ec0e2dca24a826a0eed064b0405b0ac148abc3b1d52729697f4d7b873fdc6'
+
 sample_factor = \
     66858749573256452658262553961707680376751171096153613379801854825275240965733
 # G * sample_factor
@@ -40,6 +46,38 @@ class TestArithmetic(unittest.TestCase):
             sample_point,
             arithmetic.base10_multiply(arithmetic.G, sample_factor))
 
+    def test_base58(self):
+        """Test encoding/decoding base58 using arithmetic functions"""
+        self.assertEqual(
+            arithmetic.decode(arithmetic.changebase(
+                b'2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK', 58, 256), 256),
+            25152821841976547050350277460563089811513157529113201589004)
+        self.assertEqual(
+            arithmetic.decode(arithmetic.changebase(
+                b'2DBPTgeSawWYZceFD69AbDT5q4iUWtj1ZN', 58, 256), 256),
+            18875720106589866286514488037355423395410802084648916523381)
+        self.assertEqual(
+            arithmetic.changebase(arithmetic.encode(
+                25152821841976547050350277460563089811513157529113201589004,
+                256), 256, 58), b'2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK')
+        self.assertEqual(
+            arithmetic.changebase(arithmetic.encode(
+                18875720106589866286514488037355423395410802084648916523381,
+                256), 256, 58), b'2DBPTgeSawWYZceFD69AbDT5q4iUWtj1ZN')
+
+    def test_wif(self):
+        """Decode WIFs of [chan] bitmessage and check the keys"""
+        self.assertEqual(
+            sample_wif_privsigningkey,
+            arithmetic.changebase(arithmetic.changebase(
+                b'5K42shDERM5g7Kbi3JT5vsAWpXMqRhWZpX835M2pdSoqQQpJMYm', 58, 256
+            )[1:-4], 256, 16))
+        self.assertEqual(
+            sample_wif_privencryptionkey,
+            arithmetic.changebase(arithmetic.changebase(
+                b'5HwugVWm31gnxtoYcvcK7oywH2ezYTh6Y4tzRxsndAeMi6NHqpA', 58, 256
+            )[1:-4], 256, 16))
+
     def test_decode(self):
         """Decode sample privsigningkey from hex to int and compare to factor"""
         self.assertEqual(
diff --git a/src/pyelliptic/tests/test_openssl.py b/src/pyelliptic/tests/test_openssl.py
index cb789277..ef411ef6 100644
--- a/src/pyelliptic/tests/test_openssl.py
+++ b/src/pyelliptic/tests/test_openssl.py
@@ -4,9 +4,10 @@ Test if OpenSSL is working correctly
 import unittest
 
 try:
+    from pyelliptic.ecc import ECC
     from pyelliptic.openssl import OpenSSL
 except ImportError:
-    from pybitmessage.pyelliptic import OpenSSL
+    from pybitmessage.pyelliptic import ECC, OpenSSL
 
 try:
     OpenSSL.BN_bn2binpad
@@ -55,3 +56,10 @@ class TestOpenSSL(unittest.TestCase):
             if b.raw != c.raw.rjust(OpenSSL.BN_num_bytes(n), b'\x00'):
                 bad += 1
         self.assertEqual(bad, 0)
+
+    def test_random_keys(self):
+        """A dummy test for random keys in ECC object"""
+        eccobj = ECC(curve='secp256k1')
+        self.assertEqual(len(eccobj.privkey), 32)
+        pubkey = eccobj.get_pubkey()
+        self.assertEqual(pubkey[:4], b'\x02\xca\x00\x20')
diff --git a/src/shared.py b/src/shared.py
index 4a654932..3ac49199 100644
--- a/src/shared.py
+++ b/src/shared.py
@@ -23,8 +23,6 @@ from bmconfigparser import BMConfigParser
 from debug import logger
 from helper_sql import sqlQuery
 
-from pyelliptic import arithmetic
-
 
 myECCryptorObjects = {}
 MyECSubscriptionCryptorObjects = {}
@@ -76,35 +74,6 @@ def isAddressInMyAddressBookSubscriptionsListOrWhitelist(address):
     return False
 
 
-def decodeWalletImportFormat(WIFstring):
-    # pylint: disable=inconsistent-return-statements
-    """
-    Convert private key from base58 that's used in the config file to
-    8-bit binary string
-    """
-    fullString = arithmetic.changebase(WIFstring, 58, 256)
-    privkey = fullString[:-4]
-    if fullString[-4:] != \
-       hashlib.sha256(hashlib.sha256(privkey).digest()).digest()[:4]:
-        logger.critical(
-            'Major problem! When trying to decode one of your'
-            ' private keys, the checksum failed. Here are the first'
-            ' 6 characters of the PRIVATE key: %s',
-            str(WIFstring)[:6]
-        )
-        os._exit(0)  # pylint: disable=protected-access
-        # return ""
-    elif privkey[0] == '\x80':  # checksum passed
-        return privkey[1:]
-
-    logger.critical(
-        'Major problem! When trying to decode one of your  private keys,'
-        ' the checksum passed but the key doesn\'t begin with hex 80.'
-        ' Here is the PRIVATE key: %s', WIFstring
-    )
-    os._exit(0)  # pylint: disable=protected-access
-
-
 def reloadMyAddressHashes():
     """Reload keys for user's addresses from the config file"""
     logger.debug('reloading keys from keys.dat file')
@@ -118,29 +87,39 @@ def reloadMyAddressHashes():
     hasEnabledKeys = False
     for addressInKeysFile in BMConfigParser().addresses():
         isEnabled = BMConfigParser().getboolean(addressInKeysFile, 'enabled')
-        if isEnabled:
-            hasEnabledKeys = True
-            # status
-            addressVersionNumber, streamNumber, hashobj = decodeAddress(addressInKeysFile)[1:]
-            if addressVersionNumber in (2, 3, 4):
-                # Returns a simple 32 bytes of information encoded
-                # in 64 Hex characters, or null if there was an error.
-                privEncryptionKey = hexlify(decodeWalletImportFormat(
-                    BMConfigParser().get(addressInKeysFile, 'privencryptionkey')))
-                # It is 32 bytes encoded as 64 hex characters
-                if len(privEncryptionKey) == 64:
-                    myECCryptorObjects[hashobj] = \
-                        highlevelcrypto.makeCryptor(privEncryptionKey)
-                    myAddressesByHash[hashobj] = addressInKeysFile
-                    tag = hashlib.sha512(hashlib.sha512(
-                        encodeVarint(addressVersionNumber)
-                        + encodeVarint(streamNumber) + hashobj).digest()).digest()[32:]
-                    myAddressesByTag[tag] = addressInKeysFile
-            else:
-                logger.error(
-                    'Error in reloadMyAddressHashes: Can\'t handle'
-                    ' address versions other than 2, 3, or 4.'
-                )
+        if not isEnabled:
+            continue
+
+        hasEnabledKeys = True
+
+        addressVersionNumber, streamNumber, hashobj = decodeAddress(
+            addressInKeysFile)[1:]
+        if addressVersionNumber not in (2, 3, 4):
+            logger.error(
+                'Error in reloadMyAddressHashes: Can\'t handle'
+                ' address versions other than 2, 3, or 4.')
+            continue
+
+        # Returns a simple 32 bytes of information encoded in 64 Hex characters.
+        try:
+            privEncryptionKey = hexlify(
+                highlevelcrypto.decodeWalletImportFormat(
+                    BMConfigParser().get(addressInKeysFile, 'privencryptionkey')
+                ))
+        except ValueError:
+            logger.error(
+                'Error in reloadMyAddressHashes: failed to decode'
+                ' one of the private keys for address %s', addressInKeysFile)
+            continue
+        # It is 32 bytes encoded as 64 hex characters
+        if len(privEncryptionKey) == 64:
+            myECCryptorObjects[hashobj] = \
+                highlevelcrypto.makeCryptor(privEncryptionKey)
+            myAddressesByHash[hashobj] = addressInKeysFile
+            tag = highlevelcrypto.double_sha512(
+                encodeVarint(addressVersionNumber)
+                + encodeVarint(streamNumber) + hashobj)[32:]
+            myAddressesByTag[tag] = addressInKeysFile
 
     if not keyfileSecure:
         fixSensitiveFilePermissions(os.path.join(
@@ -174,10 +153,10 @@ def reloadBroadcastSendersForWhichImWatching():
             MyECSubscriptionCryptorObjects[hashobj] = \
                 highlevelcrypto.makeCryptor(hexlify(privEncryptionKey))
         else:
-            doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(
+            doubleHashOfAddressData = highlevelcrypto.double_sha512(
                 encodeVarint(addressVersionNumber)
                 + encodeVarint(streamNumber) + hashobj
-            ).digest()).digest()
+            )
             tag = doubleHashOfAddressData[32:]
             privEncryptionKey = doubleHashOfAddressData[:32]
             MyECSubscriptionCryptorObjects[tag] = \
diff --git a/src/tests/samples.py b/src/tests/samples.py
index e1a3e676..52607732 100644
--- a/src/tests/samples.py
+++ b/src/tests/samples.py
@@ -2,6 +2,11 @@
 
 from binascii import unhexlify
 
+# hello, page 1 of the Specification
+sample_double_sha512 = unhexlify(
+    '0592a10584ffabf96539f3d780d776828c67da1ab5b169e9e8aed838aaecc9ed36d49ff14'
+    '23c55f019e050c66c6324f53588be88894fef4dcffdb74b98e2b200')
+
 
 magic = 0xE9BEB4D9
 
@@ -28,17 +33,39 @@ sample_point = (
     94730058721143827257669456336351159718085716196507891067256111928318063085006
 )
 
-sample_seed = 'TIGER, tiger, burning bright. In the forests of the night'
-# Deterministic addresses with stream 1 and versions 3, 4
+sample_seed = b'TIGER, tiger, burning bright. In the forests of the night'
+# RIPE hash on step 22 with signing key nonce 42
 sample_deterministic_ripe = b'00cfb69416ae76f68a81c459de4e13460c7d17eb'
+# Deterministic addresses with stream 1 and versions 3, 4
 sample_deterministic_addr3 = 'BM-2DBPTgeSawWYZceFD69AbDT5q4iUWtj1ZN'
 sample_deterministic_addr4 = 'BM-2cWzSnwjJ7yRP3nLEWUV5LisTZyREWSzUK'
 sample_daddr3_512 = 18875720106589866286514488037355423395410802084648916523381
 sample_daddr4_512 = 25152821841976547050350277460563089811513157529113201589004
 
-sample_statusbar_msg = "new status bar message"
-sample_inbox_msg_ids = ['27e644765a3e4b2e973ee7ccf958ea20', '51fc5531-3989-4d69-bbb5-68d64b756f5b',
-                        '2c975c515f8b414db5eea60ba57ba455', 'bc1f2d8a-681c-4cc0-9a12-6067c7e1ac24']
-# second address in sample_test_subscription_address is for the announcement broadcast
-sample_test_subscription_address = ['BM-2cWQLCBGorT9pUGkYSuGGVr9LzE4mRnQaq', 'BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw']
+sample_statusbar_msg = 'new status bar message'
+sample_inbox_msg_ids = [
+    '27e644765a3e4b2e973ee7ccf958ea20', '51fc5531-3989-4d69-bbb5-68d64b756f5b',
+    '2c975c515f8b414db5eea60ba57ba455', 'bc1f2d8a-681c-4cc0-9a12-6067c7e1ac24']
+# second address in sample_subscription_addresses
+# is for the announcement broadcast
+sample_subscription_addresses = [
+    'BM-2cWQLCBGorT9pUGkYSuGGVr9LzE4mRnQaq',
+    'BM-GtovgYdgs7qXPkoYaRgrLFuFKz1SFpsw']
 sample_subscription_name = 'test sub'
+
+sample_msg = unhexlify(
+    '0592a10584ffabf96539f3d780d776828c67da1ab5b169e9e8aed838aaecc9ed36d49ff'
+    '1423c55f019e050c66c6324f53588be88894fef4dcffdb74b98e2b200')
+sample_sig = unhexlify(
+    '304402202302475351db6b822de15d922e29397541f10d8a19780ba2ca4a920b1035f075'
+    '02205e5bba40d5f07a24c23a89ba5f01a3828371dfbb685dd5375fa1c29095fd232b')
+sample_sig_sha1 = unhexlify(
+    '304502203b50123af78b4e40f5f819ae5b8786f48826e56d0f3e65744708a493f5b65de1'
+    '0221009ddce2981ea143c0ac70404a535327e774adce8eebbae2d35104f1d326255f9a')
+
+
+# [chan] bitmessage
+sample_wif_privsigningkey = unhexlify(
+    b'a2e8b841a531c1c558ee0680c396789c7a2ea3ac4795ae3f000caf9fe367d144')
+sample_wif_privencryptionkey = unhexlify(
+    b'114ec0e2dca24a826a0eed064b0405b0ac148abc3b1d52729697f4d7b873fdc6')
diff --git a/src/tests/test_addresses.py b/src/tests/test_addresses.py
index 8f9c283d..4c4a33d6 100644
--- a/src/tests/test_addresses.py
+++ b/src/tests/test_addresses.py
@@ -2,12 +2,13 @@
 import unittest
 from binascii import unhexlify
 
-from pybitmessage import addresses
+from pybitmessage import addresses, highlevelcrypto
 
 from .samples import (
     sample_address, sample_daddr3_512, sample_daddr4_512,
     sample_deterministic_addr4, sample_deterministic_addr3,
-    sample_deterministic_ripe, sample_ripe)
+    sample_deterministic_ripe, sample_ripe,
+    sample_wif_privsigningkey, sample_wif_privencryptionkey)
 
 sample_addr3 = sample_deterministic_addr3.split('-')[1]
 sample_addr4 = sample_deterministic_addr4.split('-')[1]
@@ -59,3 +60,26 @@ class TestAddresses(unittest.TestCase):
             sample_addr4, addresses.encodeBase58(sample_daddr4_512))
         self.assertEqual(
             sample_addr3, addresses.encodeBase58(sample_daddr3_512))
+
+    def test_wif(self):
+        """Decode WIFs of [chan] bitmessage and check the keys"""
+        self.assertEqual(
+            sample_wif_privsigningkey,
+            highlevelcrypto.decodeWalletImportFormat(
+                b'5K42shDERM5g7Kbi3JT5vsAWpXMqRhWZpX835M2pdSoqQQpJMYm'))
+        self.assertEqual(
+            sample_wif_privencryptionkey,
+            highlevelcrypto.decodeWalletImportFormat(
+                b'5HwugVWm31gnxtoYcvcK7oywH2ezYTh6Y4tzRxsndAeMi6NHqpA'))
+        self.assertEqual(
+            b'5K42shDERM5g7Kbi3JT5vsAWpXMqRhWZpX835M2pdSoqQQpJMYm',
+            highlevelcrypto.encodeWalletImportFormat(
+                sample_wif_privsigningkey))
+        self.assertEqual(
+            b'5HwugVWm31gnxtoYcvcK7oywH2ezYTh6Y4tzRxsndAeMi6NHqpA',
+            highlevelcrypto.encodeWalletImportFormat(
+                sample_wif_privencryptionkey))
+
+        with self.assertRaises(ValueError):
+            highlevelcrypto.decodeWalletImportFormat(
+                b'5HwugVWm31gnxtoYcvcK7oywH2ezYTh6Y4tzRxsndAeMi6NHq')
diff --git a/src/tests/test_api.py b/src/tests/test_api.py
index 835b4afb..41a3c911 100644
--- a/src/tests/test_api.py
+++ b/src/tests/test_api.py
@@ -12,8 +12,10 @@ from six.moves import xmlrpc_client  # nosec
 import psutil
 
 from .samples import (
-    sample_seed, sample_deterministic_addr3, sample_deterministic_addr4, sample_statusbar_msg,
-    sample_inbox_msg_ids, sample_test_subscription_address, sample_subscription_name)
+    sample_seed, sample_deterministic_addr3, sample_deterministic_addr4,
+    sample_statusbar_msg, sample_inbox_msg_ids, sample_subscription_addresses,
+    sample_subscription_name
+)
 
 from .test_process import TestProcessProto
 
@@ -263,9 +265,10 @@ class TestAPI(TestAPIProto):
 
     def test_subscriptions(self):
         """Testing the API commands related to subscriptions"""
-
         self.assertEqual(
-            self.api.addSubscription(sample_test_subscription_address[0], sample_subscription_name.encode('base64')),
+            self.api.addSubscription(
+                sample_subscription_addresses[0],
+                sample_subscription_name.encode('base64')),
             'Added subscription.'
         )
 
@@ -273,18 +276,19 @@ class TestAPI(TestAPIProto):
         # check_address
         for sub in json.loads(self.api.listSubscriptions())['subscriptions']:
             # special address, added when sqlThread starts
-            if sub['address'] == sample_test_subscription_address[0]:
+            if sub['address'] == sample_subscription_addresses[0]:
                 added_subscription = sub
                 break
 
         self.assertEqual(
-            base64.decodestring(added_subscription['label']) if added_subscription['label'] else None,
+            base64.decodestring(added_subscription['label'])
+            if added_subscription['label'] else None,
             sample_subscription_name)
         self.assertTrue(added_subscription['enabled'])
 
         for s in json.loads(self.api.listSubscriptions())['subscriptions']:
             # special address, added when sqlThread starts
-            if s['address'] == sample_test_subscription_address[1]:
+            if s['address'] == sample_subscription_addresses[1]:
                 self.assertEqual(
                     base64.decodestring(s['label']),
                     'Bitmessage new releases/announcements')
@@ -295,10 +299,10 @@ class TestAPI(TestAPIProto):
                 'Could not find Bitmessage new releases/announcements'
                 ' in subscriptions')
         self.assertEqual(
-            self.api.deleteSubscription(sample_test_subscription_address[0]),
+            self.api.deleteSubscription(sample_subscription_addresses[0]),
             'Deleted subscription if it existed.')
         self.assertEqual(
-            self.api.deleteSubscription(sample_test_subscription_address[1]),
+            self.api.deleteSubscription(sample_subscription_addresses[1]),
             'Deleted subscription if it existed.')
         self.assertEqual(
             json.loads(self.api.listSubscriptions())['subscriptions'], [])
diff --git a/src/tests/test_crypto.py b/src/tests/test_crypto.py
index 38410359..44b53e6e 100644
--- a/src/tests/test_crypto.py
+++ b/src/tests/test_crypto.py
@@ -16,8 +16,10 @@ except ImportError:
     RIPEMD = None
 
 from .samples import (
-    sample_pubsigningkey, sample_pubencryptionkey,
-    sample_privsigningkey, sample_privencryptionkey, sample_ripe
+    sample_deterministic_ripe, sample_double_sha512,
+    sample_msg, sample_pubsigningkey, sample_pubencryptionkey,
+    sample_privsigningkey, sample_privencryptionkey, sample_ripe,
+    sample_seed, sample_sig, sample_sig_sha1
 )
 
 
@@ -62,6 +64,56 @@ class TestCrypto(RIPEMD160TestCase, unittest.TestCase):
 class TestHighlevelcrypto(unittest.TestCase):
     """Test highlevelcrypto public functions"""
 
+    # def test_sign(self):
+    #     """Check the signature of the sample_msg created with sample key"""
+    #     self.assertEqual(
+    #         highlevelcrypto.sign(sample_msg, sample_privsigningkey), sample_sig)
+
+    def test_double_sha512(self):
+        """Reproduce the example on page 1 of the Specification"""
+        self.assertEqual(
+            highlevelcrypto.double_sha512(b'hello'), sample_double_sha512)
+
+    def test_randomBytes(self):
+        """Dummy checks for random bytes"""
+        for n in (8, 32, 64):
+            data = highlevelcrypto.randomBytes(n)
+            self.assertEqual(len(data), n)
+            self.assertNotEqual(len(set(data)), 1)
+            self.assertNotEqual(data, highlevelcrypto.randomBytes(n))
+
+    def test_random_keys(self):
+        """Dummy checks for random keys"""
+        priv, pub = highlevelcrypto.random_keys()
+        self.assertEqual(len(priv), 32)
+        self.assertEqual(highlevelcrypto.pointMult(priv), pub)
+
+    def test_deterministic_keys(self):
+        """Generate deterministic keys, make ripe and compare it to sample"""
+        # encodeVarint(42) = b'*'
+        sigkey = highlevelcrypto.deterministic_keys(sample_seed, b'*')[1]
+        enkey = highlevelcrypto.deterministic_keys(sample_seed, b'+')[1]
+        self.assertEqual(
+            sample_deterministic_ripe,
+            hexlify(TestHashlib._hashdigest(
+                hashlib.sha512(sigkey + enkey).digest())))
+
+    def test_verify(self):
+        """Verify sample signatures and newly generated ones"""
+        pubkey_hex = hexlify(sample_pubsigningkey)
+        # pregenerated signatures
+        self.assertTrue(
+            highlevelcrypto.verify(sample_msg, sample_sig, pubkey_hex))
+        self.assertTrue(
+            highlevelcrypto.verify(sample_msg, sample_sig_sha1, pubkey_hex))
+        # new signatures
+        sig256 = highlevelcrypto.sign(sample_msg, sample_privsigningkey)
+        sig1 = highlevelcrypto.sign(sample_msg, sample_privsigningkey, "sha1")
+        self.assertTrue(
+            highlevelcrypto.verify(sample_msg, sig256, pubkey_hex))
+        self.assertTrue(
+            highlevelcrypto.verify(sample_msg, sig1, pubkey_hex))
+
     def test_privtopub(self):
         """Generate public keys and check the result"""
         self.assertEqual(
diff --git a/src/tests/test_openclpow.py b/src/tests/test_openclpow.py
index 341beec9..4770072e 100644
--- a/src/tests/test_openclpow.py
+++ b/src/tests/test_openclpow.py
@@ -1,10 +1,10 @@
 """
 Tests for openclpow module
 """
-import hashlib
+
 import unittest
-from struct import pack, unpack
-from pybitmessage import openclpow
+
+from pybitmessage import openclpow, proofofwork
 
 
 class TestOpenClPow(unittest.TestCase):
@@ -25,7 +25,5 @@ class TestOpenClPow(unittest.TestCase):
             "b93f3ffeba0ef2fd08a8dc2f87b68ae5a0dc819ab57f22ad2c4c9c8618a43b3"
         ).decode("hex")
         nonce = openclpow.do_opencl_pow(initialHash.encode("hex"), target_)
-        trialValue, = unpack(
-            '>Q', hashlib.sha512(hashlib.sha512(
-                pack('>Q', nonce) + initialHash).digest()).digest()[0:8])
-        self.assertLess((nonce - trialValue), target_)
+        self.assertLess(
+            nonce - proofofwork.trial_value(nonce, initialHash), target_)