lib/rmega/nodes/node.rb in rmega-0.1.7 vs lib/rmega/nodes/node.rb in rmega-0.2.0
- old
+ new
@@ -1,36 +1,28 @@
-require 'rmega/loggable'
-require 'rmega/utils'
-require 'rmega/crypto/crypto'
-require 'rmega/nodes/traversable'
-
module Rmega
module Nodes
class Node
+ include NotInspectable
include Loggable
include Traversable
+ include Crypto
attr_reader :data, :session
- delegate :storage, :request, :shared_keys, :rsa_privk, :to => :session
+ delegate :request, :shared_keys, :rsa_privk, :master_key, :storage, :to => :session
+ TYPES = {0 => :file, 1 => :folder, 2 => :root, 3 => :inbox, 4 => :trash}
+
def initialize(session, data)
@session = session
@data = data
end
def public_url
- @public_url ||= begin
- b64_dec_key = Utils.a32_to_base64(decrypted_file_key[0..7])
- "https://mega.co.nz/#!#{public_handle}!#{b64_dec_key}"
- end
+ @public_url ||= "https://mega.co.nz/#!#{public_handle}!#{Utils.base64urlencode(decrypted_file_key)}"
end
- def public_url=(url)
- @public_url = url
- end
-
def public_handle
@public_handle ||= request(a: 'l', n: handle)
end
def handle
@@ -49,17 +41,18 @@
return {} unless data['k']
pairs = data['k'].split('/')
pairs.inject({}) do |hash, pair|
h, k = pair.split(':')
- hash[h] = k
+ hash[h] = Utils.base64urldecode(k)
hash
end
end
def file_key
- file_keys.values.first
+ k = file_keys.values.first
+ return k ? k : nil
end
def shared_root?
data['su'] && data['sk'] && data['k']
end
@@ -71,40 +64,70 @@
sk = data['sk']
return unless sk
shared_key = if sk.size > 22
- sk = Rmega::Utils.mpi2b(Rmega::Utils.base64urldecode(sk))
- dec_sk = Rmega::Crypto::Rsa.decrypt(sk, rsa_privk)
- Utils.str_to_a32(Rmega::Utils.b2s(dec_sk)[0..15])
+ # Decrypt sk
+ sk = Utils.base64_mpi_to_bn(sk)
+ sk = rsa_decrypt(sk, rsa_privk)
+ sk = sk.to_s(16)
+ sk = '0' + sk if sk.size % 2 > 0
+ Utils.hexstr_to_bstr(sk)[0..15]
else
- Crypto.decrypt_key session.master_key, Utils.base64_to_a32(data['sk'])
+ aes_ecb_decrypt(master_key, Utils.base64urldecode(sk))
end
shared_keys[handle] = shared_key
[handle, shared_key]
end
+ def self.each_chunk(size, &block)
+ start, p = 0, 0
+
+ return if size <= 0
+
+ loop do
+ offset = p < 8 ? (131072 * (p += 1)) : 1048576
+ next_start = offset + start
+
+ if next_start >= size
+ yield(start, size - start)
+ break
+ else
+ yield(start, offset)
+ start = next_start
+ end
+ end
+ end
+
+ def each_chunk(&block)
+ self.class.each_chunk(filesize, &block)
+ end
+
def decrypted_file_key
h, shared_key = *process_shared_key
if shared_key
- Crypto.decrypt_key(shared_key, Utils.base64_to_a32(file_keys[h]))
+ aes_ecb_decrypt(shared_key, file_keys[h])
elsif file_key
- Crypto.decrypt_key(session.master_key, Utils.base64_to_a32(file_key))
+ aes_ecb_decrypt(master_key, file_key)
else
- Utils.base64_to_a32(public_url.split('!').last)
+ Utils.base64urldecode(public_url.split('!').last)
end
end
def attributes
encrypted = data['a'] || data['at']
return if !encrypted or encrypted.empty?
- Crypto.decrypt_attributes(decrypted_file_key, encrypted)
+ node_key = NodeKey.load(decrypted_file_key)
+ encrypted = Utils.base64urldecode(encrypted)
+ encrypted.strip! if encrypted.size % 16 != 0 # Fix possible errors
+ json = aes_cbc_decrypt(node_key.aes_key, encrypted)
+ JSON.parse json.gsub(/^MEGA/, '').rstrip
end
def type
- Factory.type(data['t'])
+ TYPES[data['t']]
end
end
end
end