示例#1
0
class TestChunkEncryption(object):
	# Setup
	uncrypted_chunk = get_random_bytes(1013)
	private_handle = encryption.getPrivateHandle()
	signing_key, verifying_key = encryption.getKeypair(private_handle)
	encryption_key = encryption.getEncryptionKey(private_handle)

	# Actually encrypt the chunk
	encrypted_chunk, nonce, tag = encryption.encryptAES(uncrypted_chunk, encryption_key)

	def test_length_encrypted_is_equal_to_length_uncrypted(self):
		assert len(self.encrypted_chunk) == len(self.uncrypted_chunk)
	
	def test_nonce_and_tag_lengths_are_16_bytes(self):
		assert len(self.nonce) == 16 and type(self.nonce) is bytes
		assert len(self.tag) == 16 and type(self.tag) is bytes

	def test_decryption_without_verification(self):
		completed_chunk = b''.join([self.encrypted_chunk, self.nonce])
		decrypted_chunk = encryption.decryptAES(completed_chunk, self.encryption_key)
		assert decrypted_chunk == self.uncrypted_chunk

	def test_decryption_with_verification(self):
		completed_chunk = b''.join([self.encrypted_chunk, self.nonce, self.tag])
		decrypted_chunk = encryption.decryptAndVerifyAES(completed_chunk, self.encryption_key)
		assert decrypted_chunk == self.uncrypted_chunk

	def test_chunk_signing_and_validation(self):
		signature = encryption.signChunk(self.uncrypted_chunk, self.signing_key)
		assert len(signature) == 64
		assert type(signature) is bytes
		
		encryption.verifyChunk(self.uncrypted_chunk, signature, self.verifying_key.hex())
示例#2
0
def prepareMetadataChunks(metadataTuple, privateHandle):
    """Encrypts, signs and adds the necessary flags to the metadata chunks.
	
	Arguments:
		metadataTuple {tuple of {bytes}} -- Output of squashAndSplitMetadataChunk(), where every element of the tuple is a metadata chunk.
		privateHandle {bytes} -- Self-explanatory.
	
	Returns:
		list -- List of metadata chunks - in order - ready to be encoded into trytes and sent in an iota tx.
	"""

    encryptionKey = encryption.getEncryptionKey(privateHandle)
    signingKey, verifyingKey = encryption.getKeypair(privateHandle)
    metadataChunkList = []

    address_gen = datamap.createDatamapGenerator(verifyingKey,
                                                 len(metadataTuple) + 2)
    next(
        address_gen
    )  # first address is the treasure chunk's so we don't need it right now

    for i, metadataChunk in enumerate(metadataTuple):
        encryptedChunk, nonce, _ = encryption.encryptAES(
            metadataChunk, encryptionKey)
        preparedChunk = encryptedChunk + nonce
        address = iota_utils.trytesToBytes(next(address_gen)[:-1])
        if i == 0:
            preparedChunk = addMetadataFlags(preparedChunk, len(metadataTuple))
        signature = encryption.signChunk(preparedChunk + address, signingKey)
        finalMetadataChunk = b"".join([preparedChunk, signature])
        metadataChunkList.append(finalMetadataChunk)

    return metadataChunkList
示例#3
0
class TestChunkingFunctionsWithoutPassword(object):
    _path = "testfile_4"
    initialize_file(_path)
    privateHandle = encryption.getPrivateHandle()
    _, genesisHash = encryption.getKeypair(privateHandle)

    raw_file = read_binary_file(_path)
    chunkList = fileprocessor.fileToChunks(_path, privateHandle, genesisHash)

    def test_verify_chunk_signatures(self):
        _, verifyingKey = encryption.getKeypair(self.privateHandle)
        address_gen = datamap.createDatamapGenerator(verifyingKey,
                                                     len(self.chunkList) + 1)
        for chunk in self.chunkList:
            datachunk, signature = encryption.splitChunkAndSignature(chunk)
            address = iota_utils.trytesToBytes(next(address_gen)[:-1])
            encryption.verifyChunk(datachunk + address, signature,
                                   verifyingKey.hex())
        assert True

    def test_decrypting_chunked_file(self):
        encryptionKey = encryption.getEncryptionKey(self.privateHandle)
        decrypted_path = self._path + "_decrypted"
        assert fileprocessor.chunksToFile(self.chunkList, encryptionKey,
                                          decrypted_path)

        decrypted_file = read_binary_file(decrypted_path)
        assert decrypted_file == self.raw_file

    #! Put functions here

    def test_clean_file(self):
        cleanup()
示例#4
0
def fileToChunks(filename, privateHandle, startingHash, password=None):
    """Takes a filename and returns the file converted to rev2 compliant chunks, already signed.
	
	Arguments:
		filename {str} -- Self-explanatory. Also needs to include the extension.
		privateHandle {bytes} -- Bytestring to use as the private handle. Can and should be generated using encryption.getPrivateHandle().
		startingHash {bytes} -- Hash on the main hashchain corresponding to the position of the first chunk of the file on the datamap.
	
	Keyword Arguments:
		password {str} -- Optional argument. Use it to password protect a particular file in a multi-file upload (default: {None})
	
	Returns:
		list -- Every element is a chunk, in the same order as the bytes are read from the file. 
	"""

    signingKey, _ = encryption.getKeypair(privateHandle)
    encryptionKey = encryption.getEncryptionKey(privateHandle)

    f = open(filename, mode="rb")
    filesize = os.path.getsize(filename)
    chunksize = 1013
    numberOfChunks = math.ceil(filesize / chunksize)

    fileList = []

    if password is not None:
        encryptionKey = encryption.getEncryptionKey(encryptionKey +
                                                    password.encode("utf-8"))
        numberOfChunks = math.ceil((filesize - 997) / chunksize) + 1
        chunksize = 997

    address_gen = datamap.createDatamapGenerator(startingHash,
                                                 numberOfChunks + 1)

    for i in range(0, numberOfChunks):
        chunk = f.read(chunksize)
        encrypted_chunk, nonce, tag = encryption.encryptAES(
            chunk, encryptionKey)
        address_trytes = next(
            address_gen
        )[:
          -1]  #the real address is 81 chars, but the byte conversion only works with even numbers, so we use the first 80 chars of the address to sign and check
        address_bytes = iota_utils.trytesToBytes(address_trytes)

        if password is not None and i == 0:
            unsigned_chunk = b"".join([encrypted_chunk, nonce, tag])
            chunksize = 1013
        else:
            unsigned_chunk = b"".join([encrypted_chunk, nonce])

        signature = encryption.signChunk(unsigned_chunk + address_bytes,
                                         signingKey)
        completed_chunk = unsigned_chunk + signature
        fileList.append(completed_chunk)

    f.close()

    return fileList
示例#5
0
def test_End_to_End():
	number_of_files = random.randint(4, 10)

	filenameList = ["testfile_" + str(i+1) for i in range(number_of_files)]
	initialize_multiple_files(filenameList)
	passwordFlagList = [bool(random.getrandbits(1)) for i in filenameList]
	passwordDict = {filename:"oyster" for filename, flag in zip(filenameList, passwordFlagList) if flag}

	privateHandle = encryption.getPrivateHandle()
	_, verifyingKey = encryption.getKeypair(privateHandle)
	encryptionKey = encryption.getEncryptionKey(privateHandle)

	rawMetadataChunk = fileprocessor.makeMetadataChunk(filenameList, passwordFlagList, verifyingKey)
	metadataChunkTuple = fileprocessor.squashAndSplitMetadataChunk(rawMetadataChunk)

	allChunksList = [b"TreasureChunkHere"] + fileprocessor.prepareMetadataChunks(metadataChunkTuple, privateHandle)

	for filename in filenameList:
		offsetHash = bytes.fromhex(rawMetadataChunk[filename]["offsetHash"])
		if filename in passwordDict: # This statement is only True if filename has been added to the keys in the dict, which means it has a password
			fileChunks = fileprocessor.fileToChunks(filename, privateHandle, offsetHash, password=passwordDict[filename])
		else:
			fileChunks = fileprocessor.fileToChunks(filename, privateHandle, offsetHash)
		allChunksList += fileChunks

	firstMetadataChunk = allChunksList[1]
	metadataChunkNumberFlag_bytes, _ = fileprocessor.stripMetadataFlags(firstMetadataChunk)
	numberFlag = int(np.fromstring(metadataChunkNumberFlag_bytes, dtype='uint8'))

	metadataArray = allChunksList[1:numberFlag+1]
	metadataJSON = fileprocessor.unpackMetadata(metadataArray, encryptionKey)

	decrypted_filenameList = list(metadataJSON.keys())

	for filename in decrypted_filenameList:
		startIdx = metadataJSON[filename]["startIdx"]
		endIdx = startIdx + metadataJSON[filename]["chunkCount"]
		passwordFlag = bool(metadataJSON[filename]["password"])
		decrypted_filename = "decrypted_"+filename
				
		fileList = allChunksList[startIdx:endIdx]
		if passwordFlag:
			fileprocessor.chunksToFile(fileList, encryptionKey, decrypted_filename, password=passwordDict[filename])
		else:
			fileprocessor.chunksToFile(fileList, encryptionKey, decrypted_filename)

		assert read_binary_file(filename) == read_binary_file(decrypted_filename)

		assert SHA256.new(read_binary_file(filename)).digest() == SHA256.new(read_binary_file(decrypted_filename)).digest()
	
	address_gen = datamap.createDatamapGenerator(verifyingKey, None, 1)
	for chunk in allChunksList[1:]: #first chunk is the protocol chunk and doesn't get signed when doing local simulations
		data_chunk, signature = encryption.splitChunkAndSignature(chunk)
		address = iota_utils.trytesToBytes(next(address_gen)[:-1])
		encryption.verifyChunk(data_chunk + address, signature, verifyingKey.hex())
	assert True

	cleanup()
示例#6
0
class TestEd25519Keys(object):
	signing_key, verifying_key = encryption.getKeypair(encryption.getPrivateHandle())

	def test_keys_are_bytes(self):
		assert type(self.signing_key) is bytes
		assert type(self.verifying_key) is bytes

	def test_signing_key_is_32_bytes(self):
		assert len(self.signing_key) == 32
示例#7
0
 def test_verify_chunk_signatures(self):
     _, verifyingKey = encryption.getKeypair(self.privateHandle)
     address_gen = datamap.createDatamapGenerator(verifyingKey,
                                                  len(self.chunkList) + 1)
     for chunk in self.chunkList:
         datachunk, signature = encryption.splitChunkAndSignature(chunk)
         address = iota_utils.trytesToBytes(next(address_gen)[:-1])
         encryption.verifyChunk(datachunk + address, signature,
                                verifyingKey.hex())
     assert True
示例#8
0
import iota
from disperpy import encryption, fileprocessor, datamap, iota_utils

### IMPORTANT TEST PARAMETERS

filename = "Install.txt"  #must be in the same dir as this script
node_url = "https://piota-node.com:443"

### -------------------------

# Generate handle and keys
privateHandle = encryption.getPrivateHandle()
_, verifyingKey = encryption.getKeypair(privateHandle)
encryptionKey = encryption.getEncryptionKey(privateHandle)

# Show handle on terminal
print("Private Handle:", privateHandle.hex())

# Generate metadata chunk
rawMetadataChunk = fileprocessor.makeMetadataChunk([filename], [False],
                                                   verifyingKey)
metadataChunkTuple = fileprocessor.squashAndSplitMetadataChunk(
    rawMetadataChunk)

allChunksList = [b"Protocol Chunk Here"] + fileprocessor.prepareMetadataChunks(
    metadataChunkTuple, privateHandle)

# Split, encrypt and sign the file as chunks
offsetHash = bytes.fromhex(rawMetadataChunk[filename]["offsetHash"])
fileChunks = fileprocessor.fileToChunks(filename, privateHandle, offsetHash)
allChunksList += fileChunks
示例#9
0
def test_End_to_End():

    filenameList, passwordFlagList, _ = generate_fake_input()

    privateHandle = encryption.getPrivateHandle()
    _, verifyingKey = encryption.getKeypair(privateHandle)
    encryptionKey = encryption.getEncryptionKey(privateHandle)

    rawMetadataChunk = fileprocessor.makeMetadataChunk(filenameList,
                                                       passwordFlagList,
                                                       verifyingKey)
    metadataChunkTuple = fileprocessor.squashAndSplitMetadataChunk(
        rawMetadataChunk)

    allChunksList = [b"Protocol Chunk Here"
                     ] + fileprocessor.prepareMetadataChunks(
                         metadataChunkTuple, privateHandle)
    offsetHash = bytes.fromhex(rawMetadataChunk[filenameList[0]]["offsetHash"])
    fileChunks = fileprocessor.fileToChunks(filenameList[0], privateHandle,
                                            offsetHash)
    allChunksList += fileChunks
    """ Just use non-password files for now
	for filename in filenameList:
		offsetHash = bytes.fromhex(rawMetadataChunk[filename]["offsetHash"])
		if filename in passwordDict: # This statement is only True if filename has been added to the keys in the dict, which means it has a password
			fileChunks = fileprocessor.fileToChunks(filename, privateHandle, offsetHash, password=passwordDict[filename])
		else:
			fileChunks = fileprocessor.fileToChunks(filename, privateHandle, offsetHash)
		allChunksList += fileChunks
	"""
    ### Now the file is prepared to be sent. Every element in allChunksList is the message part of an iota tx in bytes

    #Initialize iota api and generate a random seed.
    api = iota.Iota(node_url)

    # Check node connection
    try:
        api.get_node_info()
    except:
        print("Connection to node failed:", node_url)
        exit
    else:
        print("Connection to node established:", node_url)

    # Send chunked file to the Tangle
    iota_utils.send_file(api, verifyingKey, allChunksList)

    # Wait 5s to give the node time to publish the tx
    time.sleep(5)

    # Retrieve transactions
    metadataJSON = iota_utils.retrieve_metadata(api, verifyingKey,
                                                encryptionKey)
    filename = list(metadataJSON.keys())[0]
    chunk_list = iota_utils.retrieve_file(api, metadataJSON[filename])

    # Decrypt and rebuild file
    decrypted_filename = "decrypted_" + filename
    fileprocessor.chunksToFile(chunk_list, encryptionKey, decrypted_filename)

    # Asserts
    assert read_binary_file(filename) == read_binary_file(decrypted_filename)

    assert SHA256.new(read_binary_file(filename)).digest() == SHA256.new(
        read_binary_file(decrypted_filename)).digest()
    """ Just a single file for now
	for filename in list(metadata.keys()):
		decrypted_filename = "decrypted_"+filename
		fileList = iota_utils.retrieve_file(api, metadata[filename])
		passwordFlag = bool(metadata[filename]["password"])
		
		if passwordFlag:
			fileprocessor.chunksToFile(fileList, encryptionKey, decrypted_filename, password=passwordDict[filename])
		else:
			fileprocessor.chunksToFile(fileList, encryptionKey, decrypted_filename)

		print(read_binary_file(filename) == read_binary_file(decrypted_filename))
	"""
    cleanup()