Ejemplo n.º 1
0
def _salsa_encrypt(plaintext, dict_key):
	if(type(dict_key) == str):
		dict_key = dict_key.encode("utf8")
	assert(type(dict_key) == bytes)
	assert(type(plaintext) == bytes)
	encrypt_key = ripemd128(dict_key)
	s20 = Salsa20(key=encrypt_key,IV=b"\x00"*8,rounds=8)
	return s20.encryptBytes(plaintext)
Ejemplo n.º 2
0
    def parse(self, xml):
        if xml == None:
            self.status['error'] = 3
            return None

        xml_root = ET.fromstring(xml)

        salsa_buffer = bytearray()
        iv = bytes([0xE8, 0x30, 0x09, 0x4B, 0x97, 0x20, 0x5D, 0x2A])

        key = hashlib.sha256(
            self.database.header['protected_stream_key']).digest()

        salsa = Salsa20(key, iv)
        salsa.setCounter(0)

        for xml_entry in xml_root.iter('Entry'):
            need_decryption = False
            entry = {}
            entry['uid'] = xml_entry[0].text
            data = {}
            for child in xml_entry:
                if child.tag == "String" and child[1].text != None:
                    data[child[0].text] = child[1].text

                    if len(child[1].attrib
                           ) > 0 and child[1].attrib['Protected'] != None:
                        # Salsa20
                        if self.database.header['inner_random_stream_id'] == 2:

                            encoded = base64.b64decode(child[1].text)
                            length = len(encoded)

                            # Assure we have an enought buffer for the value
                            while length > len(salsa_buffer):
                                new_salsa = salsa.encryptBytes(
                                    bytes(bytearray(64)))
                                salsa_buffer.extend(new_salsa)

                            # xor the encoded value with
                            result = bytearray()
                            for a, b in zip(bytearray(encoded),
                                            bytearray(salsa_buffer[:length])):
                                result.append(a ^ b)

                            # Replace the existing value with the decoded one
                            data[child[0].text] = result.decode('utf-8')

                            del salsa_buffer[:length]

            entry['data'] = data

            self.entries.append(entry)

        return self.entries
Ejemplo n.º 3
0
    def __init__(self, unprotect=True):
        self._salsa_buffer = bytearray()
        self.salsa = Salsa20(sha256(self.header.ProtectedStreamKey),
                             KDB4_SALSA20_IV)

        self.in_buffer.seek(0)
        # self.tree = objectify.parse(self.in_buffer)
        # self.obj_root = self.tree.getroot()
        self.obj_root = ElementTree.fromstring(self.in_buffer.read())

        if unprotect:
            self.unprotect()
Ejemplo n.º 4
0
def encrypt_key(dict_key, email):
	"""
	Generates a hexadecimal key for use with the official MDict program.
	
	dict_key and email should be of type bytes (representing ascii strings), and outfile should be a file
	open for writing in text mode.
	
	Returns a string of 32 hexadecimal digits. This should be placed in a file of its own, with
	the same name and location as the mdx file but the extension changed to '.key'. """
	
	email_digest = ripemd128(email)
	dict_key_digest = ripemd128(dict_key)
	
	s20 = Salsa20(key=email_digest,IV=b"\x00"*8,rounds=8)
	output_key = s20.encryptBytes(dict_key_digest)
	return _hexdump(output_key)
Ejemplo n.º 5
0
def encrypt_key(dict_key, **kwargs):
    """
	Generates a hexadecimal key for use with the official MDict program.

	Parameters:
	  dict_key: a bytes object, representing the dictionary password.

	Keyword parameters:
	  Exactly one of email and device_id should be specified. They should be unicode strings,
	  representing either the user's email address, or the device ID of the machine on which
	  the dictionary is to be opened.
	
	Return value:
	  a string of 32 hexadecimal digits. This should be placed in a file of its own,
	  with the same name and location as the mdx file but the extension changed to '.key'.

	Example usage:
		key = encrypt_key(b"password", email="*****@*****.**")

		key = encrypt_key(b"password", device_id="12345678-9012-3456-7890-1234")
	"""

    if (("email" not in kwargs and "device_id" not in kwargs)
            or ("email" in kwargs and "device_id" in kwargs)):
        raise ParameterError(
            "Expected exactly one of email and device_id as keyword argument")

    if "email" in kwargs:
        owner_info_digest = ripemd128(kwargs["email"].encode("ascii"))
    else:
        owner_info_digest = ripemd128(kwargs["device_id"].encode("ascii"))

    dict_key_digest = ripemd128(dict_key)

    s20 = Salsa20(key=owner_info_digest, IV=b"\x00" * 8, rounds=8)
    output_key = s20.encryptBytes(dict_key_digest)
    return _hexdump(output_key)
Ejemplo n.º 6
0
def _decrypt_regcode_by_email(reg_code, email):
    email_digest = ripemd128(email.decode().encode('utf-16-le'))
    s20 = Salsa20(key=email_digest, IV=b"\x00" * 8, rounds=8)
    encrypt_key = s20.encryptBytes(reg_code)
    return encrypt_key
Ejemplo n.º 7
0
def _decrypt_regcode_by_deviceid(reg_code, deviceid):
    deviceid_digest = ripemd128(deviceid)
    s20 = Salsa20(key=deviceid_digest, IV=b"\x00" * 8, rounds=8)
    encrypt_key = s20.encryptBytes(reg_code)
    return encrypt_key
Ejemplo n.º 8
0
def _salsa_decrypt(ciphertext, encrypt_key):
    s20 = Salsa20(key=encrypt_key, IV=b"\x00" * 8, rounds=8)
    return s20.encryptBytes(ciphertext)
Ejemplo n.º 9
0
def _salsa_decrypt(ciphertext, dict_key):
    assert (type(ciphertext) == bytes)
    assert (type(dict_key) == bytes)
    decrypt_key = ripemd128(dict_key)
    s20 = Salsa20(key=decrypt_key, IV=b"\x00" * 8, rounds=8)
    return s20.encryptBytes(ciphertext)