Ejemplo n.º 1
0
    def _login_common(self, res, password):
        if res in (-2, -9):
            raise MegaIncorrectPasswordExcetion(
                "Incorrect e-mail and/or password.")

        enc_master_key = base64_to_a32(res['k'])
        self.master_key = decrypt_key(enc_master_key, password)
        if 'tsid' in res:
            tsid = base64urldecode(res['tsid'])
            key_encrypted = a32_to_str(
                encrypt_key(str_to_a32(tsid[:16]), self.master_key))
            if key_encrypted == tsid[-16:]:
                self.sid = res['tsid']
        elif 'csid' in res:
            enc_rsa_priv_key = base64_to_a32(res['privk'])
            rsa_priv_key = decrypt_key(enc_rsa_priv_key, self.master_key)

            privk = a32_to_str(rsa_priv_key)
            self.rsa_priv_key = [0, 0, 0, 0]

            for i in range(4):
                l = ((privk[0] * 256 + privk[1] + 7) // 8) + 2
                self.rsa_priv_key[i] = mpi2int(privk[:l])
                privk = privk[l:]

            enc_sid = mpi2int(base64urldecode(res['csid']))
            decrypter = RSA.construct(
                (self.rsa_priv_key[0] * self.rsa_priv_key[1], 0,
                 self.rsa_priv_key[2], self.rsa_priv_key[0],
                 self.rsa_priv_key[1]))
            sid = '%x' % decrypter.key._decrypt(enc_sid)
            sid = binascii.unhexlify('0' + sid if len(sid) % 2 else sid)
            self.sid = base64urlencode(sid[:43])
Ejemplo n.º 2
0
 def get_files(self):
     files_data = self.api_req({'a': 'f', 'c': 1})
     for file in files_data['f']:
         if file['t'] in (0, 1):
             key = file['k'].split(':')[1]
             key = decrypt_key(base64_to_a32(key), self.master_key)
             # file
             if file['t'] == 0:
                 k = (key[0] ^ key[4], key[1] ^ key[5], key[2] ^ key[6],
                      key[3] ^ key[7])
             # directory
             else:
                 k = key
             attributes = base64urldecode(file['a'])
             attributes = dec_attr(attributes, k)
             file['a'] = attributes
             file['k'] = key
         # Root ("Cloud Drive")
         elif file['t'] == 2:
             self.root_id = file['h']
         # Inbox
         elif file['t'] == 3:
             self.inbox_id = file['h']
         # Trash Bin
         elif file['t'] == 4:
             self.trashbin_id = file['h']
     return files_data
Ejemplo n.º 3
0
    def download_file(self, file_id, file_key, public=False, store_path=None):
        if public:
            file_key = base64_to_a32(file_key)
            file_data = self.api_req({'a': 'g', 'g': 1, 'p': file_id})
        else:
            file_data = self.api_req({'a': 'g', 'g': 1, 'n': file_id})

        k = (file_key[0] ^ file_key[4], file_key[1] ^ file_key[5],
             file_key[2] ^ file_key[6], file_key[3] ^ file_key[7])
        iv = file_key[4:6] + (0, 0)
        meta_mac = file_key[6:8]

        file_url = file_data['g']
        file_size = file_data['s']
        attributes = base64urldecode(file_data['at'])
        attributes = dec_attr(attributes, k)
        file_name = attributes['n']

        infile = requests.get(file_url, stream=True).raw
        if store_path:
            file_name = os.path.join(store_path, file_name)
        outfile = open(file_name, 'wb')

        counter = Counter.new(128, initial_value=((iv[0] << 32) + iv[1]) << 64)
        decryptor = AES.new(a32_to_str(k), AES.MODE_CTR, counter=counter)

        file_mac = (0, 0, 0, 0)
        for chunk_start, chunk_size in sorted(get_chunks(file_size).items()):
            chunk = infile.read(chunk_size)
            chunk = decryptor.decrypt(chunk)
            outfile.write(chunk)

            chunk_mac = [iv[0], iv[1], iv[0], iv[1]]
            for i in range(0, len(chunk), 16):
                block = chunk[i:i + 16]
                if len(block) % 16:
                    block += b'\0' * (16 - (len(block) % 16))
                block = str_to_a32(block)
                chunk_mac = [
                    chunk_mac[0] ^ block[0], chunk_mac[1] ^ block[1],
                    chunk_mac[2] ^ block[2], chunk_mac[3] ^ block[3]
                ]
                chunk_mac = aes_cbc_encrypt_a32(chunk_mac, k)

            file_mac = [
                file_mac[0] ^ chunk_mac[0], file_mac[1] ^ chunk_mac[1],
                file_mac[2] ^ chunk_mac[2], file_mac[3] ^ chunk_mac[3]
            ]
            file_mac = aes_cbc_encrypt_a32(file_mac, k)

        outfile.close()

        # Integrity check
        if (file_mac[0] ^ file_mac[1], file_mac[2] ^ file_mac[3]) != meta_mac:
            raise ValueError('MAC mismatch')

        return file_name
Ejemplo n.º 4
0
def getfileinfo(file_id, file_key):
  key = base64_to_a32(file_key)
  k = (key[0] ^ key[4], key[1] ^ key[5], key[2] ^ key[6], key[3] ^ key[7])
  iv = key[4:6] + (0, 0)
  meta_mac = key[6:8]

  try:
    file = m.api_req({'a': 'g', 'g': 1, 'p': file_id})
    
    dl_url = file['g']
    size = file['s']
    attributes = base64urldecode(file['at']) 
    attributes = dec_attr(attributes, k)
   
    print "ALIVE: %s (size: %d)" % (attributes['n'], size)

    return [attributes['n'], size, True]

  except:
    print "DEAD: %s" % (file_id)
    return ["", "", False]