示例#1
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
示例#2
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
示例#3
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()
示例#4
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
示例#5
0
	def test_bytes_to_trytes_to_bytes(self):
		byte_string = iota_utils.trytesToBytes(self.trytes)
		
		assert byte_string == self.message