rmega 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .DS_Store
19
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rmega.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Daniele Molteni
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # Rmega
2
+
3
+ Ruby library for the Mega.co.nz API.
4
+ Tested using ruby 1.9.3+ (OpenSSL 0.9.8r+)
5
+
6
+ <div style="background-color: #000000; border-radius: 8px">
7
+ <img src="https://eu.static.mega.co.nz/images/mega/logo.png" />
8
+ </div>
9
+
10
+
11
+
12
+ ## Usage
13
+
14
+ ```ruby
15
+ storage = Rmega.login 'your_email', 'your_password'
16
+
17
+ # Fetch all the nodes (files, folders, ecc.)
18
+ nodes = storage.nodes
19
+
20
+ # Find all nodes which name match a regexp
21
+ nodes = storage.nodes_by_name /my.document/i
22
+
23
+ # Download a file
24
+ my_node.download '~/Download' # The name of the node is used
25
+ my_node.download '~/Download/mydocument_42.zip' # Specify a new name
26
+
27
+ # Download a file using a given url
28
+ storage.download 'https://mega.co.nz/#!cER0GYbD!ZCHruEzLghAcEZuD44Dp0k--6m5duA08Xl4a_bUZYMI', '~/Download'
29
+
30
+ # Upload a file (to the root node)
31
+ storage.upload '~/Downloads/my_file.zip'
32
+
33
+ # Upload a file to a specific folder
34
+ storage.upload '~/Downloads/my_file.zip', folder_node
35
+
36
+ # Trash a node
37
+ my_node.trash
38
+
39
+ # Gets the public url (the sharable one) of a file
40
+ my_node.public_url
41
+
42
+ # See the attributes of a node
43
+ my_node.attributes
44
+
45
+ # Find all nodes of certain type
46
+ # types are: file, dir, root, inbox, trash
47
+ files = storage.nodes_by_type :file
48
+ folders = storage.nodes_by_type :dir
49
+
50
+ ```
51
+
52
+
53
+ ## Installation
54
+
55
+ Add this line to your application's Gemfile:
56
+
57
+ gem 'rmega'
58
+
59
+ And then execute:
60
+
61
+ $ bundle
62
+
63
+ Or install it yourself as:
64
+
65
+ $ gem install rmega
66
+
67
+
68
+ ## Contributing
69
+
70
+ 1. Fork it
71
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
72
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
73
+ 4. Push to the branch (`git push origin my-new-feature`)
74
+ 5. Create new Pull Request
75
+
76
+
77
+ ## Copyright
78
+
79
+ This work is the result of a reverse engineering of the Mega's Javascript code.
80
+
81
+ Copyright (c) 2013 Daniele Molteni
82
+ MIT License
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/lib/rmega.rb ADDED
@@ -0,0 +1,50 @@
1
+ # Gem with ruby 1.9+
2
+ require "openssl"
3
+ require "json"
4
+ require "logger"
5
+ require "ostruct"
6
+
7
+ # Gems in the bundle
8
+ require "httpclient"
9
+ require "execjs"
10
+ require "ruby-progressbar"
11
+
12
+ # Require all the other files
13
+ require "rmega/version"
14
+ require "rmega/utils"
15
+ require "rmega/crypto/rsa"
16
+ require "rmega/crypto/aes"
17
+ require "rmega/crypto/aes_ctr"
18
+ require "rmega/crypto/crypto"
19
+ require "rmega/storage"
20
+ require "rmega/node"
21
+ require "rmega/session"
22
+
23
+ module Rmega
24
+ def self.logger
25
+ @logger ||= begin
26
+ logger = Logger.new $stdout
27
+ logger.formatter = Proc.new { | severity, time, progname, msg| "#{msg}\n" }
28
+ logger.level = Logger::INFO
29
+ logger
30
+ end
31
+ end
32
+
33
+ def self.login email, password
34
+ session = Session.new email, password
35
+ session.storage
36
+ end
37
+
38
+ def self.default_options
39
+ {
40
+ show_progress: true,
41
+ upload_timeout: 120,
42
+ api_request_timeout: 20,
43
+ api_url: 'https://eu.api.mega.co.nz/cs'
44
+ }
45
+ end
46
+
47
+ def self.options
48
+ @options ||= OpenStruct.new default_options
49
+ end
50
+ end
@@ -0,0 +1,33 @@
1
+ module Rmega
2
+ module Crypto
3
+ module Aes
4
+ extend self
5
+
6
+ def packing
7
+ 'l>*'
8
+ end
9
+
10
+ def cipher
11
+ @cipher ||= OpenSSL::Cipher::AES.new 128, :CBC
12
+ end
13
+
14
+ def encrypt key, data
15
+ cipher.reset
16
+ cipher.padding = 0
17
+ cipher.encrypt
18
+ cipher.key = key.pack(packing)
19
+ result = cipher.update data.pack(packing)
20
+ result.unpack packing
21
+ end
22
+
23
+ def decrypt key, data
24
+ cipher.reset
25
+ cipher.padding = 0
26
+ cipher.decrypt
27
+ cipher.key = key.pack packing
28
+ result = cipher.update data.pack(packing)
29
+ result.unpack packing
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,89 @@
1
+ module Rmega
2
+ module Crypto
3
+ module AesCtr
4
+ extend self
5
+
6
+ def decrypt key, nonce, data
7
+ raise "invalid nonce" if nonce.size != 4 or !nonce.respond_to?(:pack)
8
+ raise "invalid key" if key.size != 4 or !key.respond_to?(:pack)
9
+
10
+ mac = [nonce[0], nonce[1], nonce[0], nonce[1]]
11
+ enc = nil
12
+ a32 = Utils.str_to_a32 data
13
+ len = a32.size - 3
14
+ last_i = 0
15
+
16
+ (0..len).step(4) do |i|
17
+ enc = Aes.encrypt key, nonce
18
+ 4.times do |m|
19
+ a32[i+m] = (a32[i+m] || 0) ^ (enc[m] || 0)
20
+ mac[m] = (mac[m] || 0) ^ (a32[i+m] || 0)
21
+ end
22
+ mac = Aes.encrypt key, mac
23
+ nonce[3] += 1
24
+ nonce[2] += 1 if nonce[3] == 0
25
+ last_i = i + 4
26
+ end
27
+
28
+ if last_i < a32.size
29
+ v = [0, 0, 0, 0]
30
+ (last_i..a32.size - 1).step(1) { |m| v[m-last_i] = a32[m] || 0 }
31
+
32
+ enc = Aes.encrypt key, nonce
33
+ 4.times { |m| v[m] = v[m] ^ enc[m] }
34
+
35
+ j = data.size & 15
36
+ m = Utils.str_to_a32 Array.new(j+1).join(255.chr)+Array.new(17-j).join(0.chr)
37
+
38
+ 4.times { |x| mac[x] = mac[x] ^ (v[x] & m[x]) }
39
+
40
+ mac = Aes.encrypt key, mac
41
+
42
+ (last_i..a32.size - 1).step(1) { |j| a32[j] = v[j - last_i] || 0 }
43
+ end
44
+
45
+ decrypted_data = Utils.a32_to_str(a32, data.size)
46
+
47
+ {data: decrypted_data, mac: mac}
48
+ end
49
+
50
+ def encrypt key, nonce, data
51
+ raise "invalid nonce" if nonce.size != 4 or !nonce.respond_to?(:pack)
52
+ raise "invalid key" if key.size != 4 or !key.respond_to?(:pack)
53
+
54
+ ctr = nonce.dup
55
+ mac = [ctr[0], ctr[1], ctr[0], ctr[1]]
56
+ ab32 = Utils.str_to_a32 data
57
+ len = ab32.size - 3
58
+ enc = nil
59
+ last_i = 0
60
+
61
+ (0..len).step(4) do |i|
62
+ 4.times { |x| mac[x] = mac[x] ^ (ab32[i+x] || 0) }
63
+ mac = Aes.encrypt key, mac
64
+ enc = Aes.encrypt key, ctr
65
+ 4.times { |x| ab32[i+x] = (ab32[i+x] || 0) ^ (enc[x] || 0) }
66
+ ctr[3] += 1
67
+ ctr[2] += 1 if ctr[3].zero?
68
+ last_i = i + 4
69
+ end
70
+
71
+ i = last_i
72
+
73
+ if i < ab32.size
74
+ v = [0, 0, 0, 0]
75
+ (i..ab32.size - 1).step(1) { |j| v[j - i] = ab32[j] || 0 }
76
+ 4.times { |x| mac[x] = mac[x] ^ v[x] }
77
+ mac = Aes.encrypt key, mac
78
+ enc = Aes.encrypt key, ctr
79
+ 4.times { |x| v[x] = v[x] ^ enc[x] }
80
+ (i..ab32.size - 1).step(1) { |j| ab32[j] = v[j - i] || 0 }
81
+ end
82
+
83
+ decrypted_data = Utils.a32_to_str ab32, data.size
84
+ {data: decrypted_data, mac: mac}
85
+ end
86
+
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,94 @@
1
+ module Rmega
2
+ module Crypto
3
+ extend self
4
+
5
+ def prepare_key ary
6
+ pkey = [0x93C467E3,0x7DB0C7A4,0xD1BE3F81,0x0152CB56]
7
+ 65536.times do
8
+ 0.step(ary.size-1, 4) do |j|
9
+ key = [0,0,0,0]
10
+ 4.times do |i|
11
+ key[i] = ary[i+j] if i+j < ary.size
12
+ end
13
+ pkey = Aes.encrypt key, pkey
14
+ end
15
+ end
16
+ pkey
17
+ end
18
+
19
+ def decrypt_sid key, csid, privk
20
+ # if csid ...
21
+ t = Utils.mpi2b Utils.base64urldecode(csid)
22
+ privk = Utils.a32_to_str decrypt_key(key, Utils.base64_to_a32(privk))
23
+ rsa_privk = Array.new 4
24
+ # else if tsid (todo)
25
+
26
+ # Decompose private key
27
+ 4.times do |i|
28
+ l = ((privk[0].ord * 256 + privk[1].ord + 7) >> 3) + 2
29
+ rsa_privk[i] = Utils.mpi2b privk[0..l-1]
30
+ privk = privk[l..-1]
31
+ end
32
+
33
+ # TODO - remove execjs and build the key using the ruby lib
34
+ # rsa_key = Crypto::Rsa.build_rsa_key rsa_privk
35
+ decrypted_t = Rsa.decrypt t, rsa_privk
36
+ Utils.base64urlencode Utils.b2s(decrypted_t)[0..42]
37
+ end
38
+
39
+ def encrypt_attributes key, attributes_hash
40
+ a32key = key.dup
41
+ if a32key.size > 4
42
+ a32key = [a32key[0] ^ a32key[4], a32key[1] ^ a32key[5], a32key[2] ^ a32key[6], a32key[3] ^ a32key[7]]
43
+ end
44
+ attributes_str = "MEGA#{attributes_hash.to_json}"
45
+ attributes_str << ("\x00" * (16 - (attributes_str.size % 16)))
46
+ Crypto::Aes.encrypt a32key, Utils.str_to_a32(attributes_str)
47
+ end
48
+
49
+ def decrypt_attributes key, attributes_base64
50
+ a32key = key.dup
51
+ if a32key.size > 4
52
+ a32key = [a32key[0] ^ a32key[4], a32key[1] ^ a32key[5], a32key[2] ^ a32key[6], a32key[3] ^ a32key[7]]
53
+ end
54
+ attributes = Crypto::Aes.decrypt a32key, Utils.base64_to_a32(attributes_base64)
55
+ attributes = Utils.a32_to_str attributes
56
+ JSON.parse attributes.gsub(/^MEGA/, '').rstrip
57
+ end
58
+
59
+ def prepare_key_pw password_str
60
+ prepare_key Utils.str_to_a32(password_str)
61
+ end
62
+
63
+ def stringhash aes_key, string
64
+ s32 = Utils::str_to_a32 string
65
+ h32 = [0,0,0,0]
66
+
67
+ s32.size.times { |i| h32[i & 3] ^= s32[i] }
68
+ 16384.times { h32 = Aes.encrypt aes_key, h32 }
69
+
70
+ Utils::a32_to_base64 [h32[0],h32[2]]
71
+ end
72
+
73
+ def encrypt_key key, data
74
+ return Aes.encrypt(key, data) if data.size == 4
75
+ x = []
76
+ (0..data.size).step(4) do |i|
77
+ # cdata = [data[i] || 0, data[i+1] || 0, data[i+2] || 0, data[i+3] || 0]
78
+ cdata = [data[i] || 0, data[i+1] || 0, data[i+2], data[i+3]].compact
79
+ x.concat Crypto::Aes.encrypt(key, cdata)
80
+ end
81
+ x
82
+ end
83
+
84
+ def decrypt_key key, data
85
+ return Aes.decrypt(key, data) if data.size == 4
86
+ x = []
87
+ (0..data.size).step(4) do |i|
88
+ cdata = [data[i] || 0, data[i+1] || 0, data[i+2] || 0, data[i+3] || 0]
89
+ x.concat Crypto::Aes.decrypt(key, cdata)
90
+ end
91
+ x
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,19 @@
1
+ module Rmega
2
+ module Crypto
3
+ module Rsa
4
+ extend self
5
+
6
+ def script_path
7
+ File.join File.dirname(__FILE__), 'rsa_mega.js'
8
+ end
9
+
10
+ def context
11
+ @context ||= ExecJS.compile File.read(script_path)
12
+ end
13
+
14
+ def decrypt t, privk
15
+ context.call "RSAdecrypt", t, privk[2], privk[0], privk[1], privk[3]
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,455 @@
1
+
2
+ /* RSA public key encryption/decryption
3
+ * The following functions are (c) 2000 by John M Hanna and are
4
+ * released under the terms of the Gnu Public License.
5
+ * You must freely redistribute them with their source -- see the
6
+ * GPL for details.
7
+ * -- Latest version found at http://sourceforge.net/projects/shop-js
8
+ *
9
+ * Modifications and GnuPG multi precision integer (mpi) conversion added
10
+ * 2004 by Herbert Hanewinkel, www.haneWIN.de
11
+ */
12
+
13
+ // --- Arbitrary Precision Math ---
14
+ // badd(a,b), bsub(a,b), bsqr(a), bmul(a,b)
15
+ // bdiv(a,b), bmod(a,b), bexpmod(g,e,m), bmodexp(g,e,m)
16
+
17
+ // bs is the shift, bm is the mask
18
+ // set single precision bits to 28
19
+ var bs=28;
20
+ var bx2=1<<bs, bm=bx2-1, bx=bx2>>1, bd=bs>>1, bdm=(1<<bd)-1;
21
+
22
+ var log2=Math.log(2);
23
+
24
+ function zeros(n)
25
+ {
26
+ var r=new Array(n);
27
+
28
+ while(n-->0) r[n]=0;
29
+ return r;
30
+ }
31
+
32
+ function zclip(r)
33
+ {
34
+ var n = r.length;
35
+ if(r[n-1]) return r;
36
+ while(n>1 && r[n-1]==0) n--;
37
+ return r.slice(0,n);
38
+ }
39
+
40
+ // returns bit length of integer x
41
+ function nbits(x)
42
+ {
43
+ var n = 1, t;
44
+ if((t=x>>>16) != 0) { x = t; n += 16; }
45
+ if((t=x>>8) != 0) { x = t; n += 8; }
46
+ if((t=x>>4) != 0) { x = t; n += 4; }
47
+ if((t=x>>2) != 0) { x = t; n += 2; }
48
+ if((t=x>>1) != 0) { x = t; n += 1; }
49
+ return n;
50
+ }
51
+
52
+ function badd(a,b)
53
+ {
54
+ var al=a.length;
55
+ var bl=b.length;
56
+
57
+ if(al < bl) return badd(b,a);
58
+
59
+ var r=new Array(al);
60
+ var c=0, n=0;
61
+
62
+ for(; n<bl; n++)
63
+ {
64
+ c+=a[n]+b[n];
65
+ r[n]=c & bm;
66
+ c>>>=bs;
67
+ }
68
+ for(; n<al; n++)
69
+ {
70
+ c+=a[n];
71
+ r[n]=c & bm;
72
+ c>>>=bs;
73
+ }
74
+ if(c) r[n]=c;
75
+ return r;
76
+ }
77
+
78
+ function bsub(a,b)
79
+ {
80
+ var al=a.length;
81
+ var bl=b.length;
82
+
83
+ if(bl > al) return [];
84
+ if(bl == al)
85
+ {
86
+ if(b[bl-1] > a[bl-1]) return [];
87
+ if(bl==1) return [a[0]-b[0]];
88
+ }
89
+
90
+ var r=new Array(al);
91
+ var c=0;
92
+
93
+ for(var n=0; n<bl; n++)
94
+ {
95
+ c+=a[n]-b[n];
96
+ r[n]=c & bm;
97
+ c>>=bs;
98
+ }
99
+ for(;n<al; n++)
100
+ {
101
+ c+=a[n];
102
+ r[n]=c & bm;
103
+ c>>=bs;
104
+ }
105
+ if(c) return [];
106
+
107
+ return zclip(r);
108
+ }
109
+
110
+ function ip(w, n, x, y, c)
111
+ {
112
+ var xl = x&bdm;
113
+ var xh = x>>bd;
114
+
115
+ var yl = y&bdm;
116
+ var yh = y>>bd;
117
+
118
+ var m = xh*yl+yh*xl;
119
+ var l = xl*yl+((m&bdm)<<bd)+w[n]+c;
120
+ w[n] = l&bm;
121
+ c = xh*yh+(m>>bd)+(l>>bs);
122
+ return c;
123
+ }
124
+
125
+ // Multiple-precision squaring, HAC Algorithm 14.16
126
+
127
+ function bsqr(x)
128
+ {
129
+ var t = x.length;
130
+ var n = 2*t;
131
+ var r = zeros(n);
132
+ var c = 0;
133
+ var i, j;
134
+
135
+ for(i = 0; i < t; i++)
136
+ {
137
+ c = ip(r,2*i,x[i],x[i],0);
138
+ for(j = i+1; j < t; j++)
139
+ {
140
+ c = ip(r,i+j,2*x[j],x[i],c);
141
+ }
142
+ r[i+t] = c;
143
+ }
144
+
145
+ return zclip(r);
146
+ }
147
+
148
+ // Multiple-precision multiplication, HAC Algorithm 14.12
149
+
150
+ function bmul(x,y)
151
+ {
152
+ var n = x.length;
153
+ var t = y.length;
154
+ var r = zeros(n+t-1);
155
+ var c, i, j;
156
+
157
+ for(i = 0; i < t; i++)
158
+ {
159
+ c = 0;
160
+ for(j = 0; j < n; j++)
161
+ {
162
+ c = ip(r,i+j,x[j],y[i],c);
163
+ }
164
+ r[i+n] = c;
165
+ }
166
+
167
+ return zclip(r);
168
+ }
169
+
170
+ function toppart(x,start,len)
171
+ {
172
+ var n=0;
173
+ while(start >= 0 && len-->0) n=n*bx2+x[start--];
174
+ return n;
175
+ }
176
+
177
+ // Multiple-precision division, HAC Algorithm 14.20
178
+
179
+ function bdiv(a,b)
180
+ {
181
+ var n=a.length-1;
182
+ var t=b.length-1;
183
+ var nmt=n-t;
184
+
185
+ // trivial cases; a < b
186
+ if(n < t || n==t && (a[n]<b[n] || n>0 && a[n]==b[n] && a[n-1]<b[n-1]))
187
+ {
188
+ this.q=[0]; this.mod=a;
189
+ return this;
190
+ }
191
+
192
+ // trivial cases; q < 4
193
+ if(n==t && toppart(a,t,2)/toppart(b,t,2) <4)
194
+ {
195
+ var x=a.concat();
196
+ var qq=0;
197
+ var xx;
198
+ for(;;)
199
+ {
200
+ xx=bsub(x,b);
201
+ if(xx.length==0) break;
202
+ x=xx; qq++;
203
+ }
204
+ this.q=[qq]; this.mod=x;
205
+ return this;
206
+ }
207
+
208
+ // normalize
209
+ var shift2=Math.floor(Math.log(b[t])/log2)+1;
210
+ var shift=bs-shift2;
211
+
212
+ var x=a.concat();
213
+ var y=b.concat();
214
+
215
+ if(shift)
216
+ {
217
+ for(i=t; i>0; i--) y[i]=((y[i]<<shift) & bm) | (y[i-1] >> shift2);
218
+ y[0]=(y[0]<<shift) & bm;
219
+ if(x[n] & ((bm <<shift2) & bm))
220
+ {
221
+ x[++n]=0; nmt++;
222
+ }
223
+ for(i=n; i>0; i--) x[i]=((x[i]<<shift) & bm) | (x[i-1] >> shift2);
224
+ x[0]=(x[0]<<shift) & bm;
225
+ }
226
+
227
+ var i, j, x2;
228
+ var q=zeros(nmt+1);
229
+ var y2=zeros(nmt).concat(y);
230
+ for(;;)
231
+ {
232
+ x2=bsub(x,y2);
233
+ if(x2.length==0) break;
234
+ q[nmt]++;
235
+ x=x2;
236
+ }
237
+
238
+ var yt=y[t], top=toppart(y,t,2)
239
+ for(i=n; i>t; i--)
240
+ {
241
+ var m=i-t-1;
242
+ if(i >= x.length) q[m]=1;
243
+ else if(x[i] == yt) q[m]=bm;
244
+ else q[m]=Math.floor(toppart(x,i,2)/yt);
245
+
246
+ var topx=toppart(x,i,3);
247
+ while(q[m] * top > topx) q[m]--;
248
+
249
+ //x-=q[m]*y*b^m
250
+ y2=y2.slice(1);
251
+ x2=bsub(x,bmul([q[m]],y2));
252
+ if(x2.length==0)
253
+ {
254
+ q[m]--;
255
+ x2=bsub(x,bmul([q[m]],y2));
256
+ }
257
+ x=x2;
258
+ }
259
+ // de-normalize
260
+ if(shift)
261
+ {
262
+ for(i=0; i<x.length-1; i++) x[i]=(x[i]>>shift) | ((x[i+1] << shift2) & bm);
263
+ x[x.length-1]>>=shift;
264
+ }
265
+
266
+ this.q = zclip(q);
267
+ this.mod = zclip(x);
268
+ return this;
269
+ }
270
+
271
+ function simplemod(i,m) // returns the mod where m < 2^bd
272
+ {
273
+ var c=0, v;
274
+ for(var n=i.length-1; n>=0; n--)
275
+ {
276
+ v=i[n];
277
+ c=((v >> bd) + (c<<bd)) % m;
278
+ c=((v & bdm) + (c<<bd)) % m;
279
+ }
280
+ return c;
281
+ }
282
+
283
+ function bmod(p,m)
284
+ {
285
+ if(m.length==1)
286
+ {
287
+ if(p.length==1) return [p[0] % m[0]];
288
+ if(m[0] < bdm) return [simplemod(p,m[0])];
289
+ }
290
+
291
+ var r=bdiv(p,m);
292
+ return r.mod;
293
+ }
294
+
295
+ // Barrett's modular reduction, HAC Algorithm 14.42
296
+
297
+ function bmod2(x,m,mu)
298
+ {
299
+ var xl=x.length - (m.length << 1);
300
+ if(xl > 0) return bmod2(x.slice(0,xl).concat(bmod2(x.slice(xl),m,mu)),m,mu);
301
+
302
+ var ml1=m.length+1, ml2=m.length-1,rr;
303
+ //var q1=x.slice(ml2)
304
+ //var q2=bmul(q1,mu)
305
+ var q3=bmul(x.slice(ml2),mu).slice(ml1);
306
+ var r1=x.slice(0,ml1);
307
+ var r2=bmul(q3,m).slice(0,ml1);
308
+ var r=bsub(r1,r2);
309
+
310
+ if(r.length==0)
311
+ {
312
+ r1[ml1]=1;
313
+ r=bsub(r1,r2);
314
+ }
315
+ for(var n=0;;n++)
316
+ {
317
+ rr=bsub(r,m);
318
+ if(rr.length==0) break;
319
+ r=rr;
320
+ if(n>=3) return bmod2(r,m,mu);
321
+ }
322
+ return r;
323
+ }
324
+
325
+ // Modular exponentiation, HAC Algorithm 14.79
326
+
327
+ function bexpmod(g,e,m)
328
+ {
329
+ var a = g.concat();
330
+ var l = e.length-1;
331
+ var n = nbits(e[l])-2;
332
+
333
+ for(; l >= 0; l--)
334
+ {
335
+ for(; n >= 0; n-=1)
336
+ {
337
+ a=bmod(bsqr(a),m);
338
+ if(e[l] & (1<<n)) a=bmod(bmul(a,g),m);
339
+ }
340
+ n = bs-1;
341
+ }
342
+ return a;
343
+ }
344
+
345
+ // Modular exponentiation using Barrett reduction
346
+
347
+ function bmodexp(g,e,m)
348
+ {
349
+ var a=g.concat();
350
+ var l=e.length-1;
351
+ var n=m.length*2;
352
+ var mu=zeros(n+1);
353
+ mu[n]=1;
354
+ mu=bdiv(mu,m).q;
355
+
356
+ n = nbits(e[l])-2;
357
+
358
+ for(; l >= 0; l--)
359
+ {
360
+ for(; n >= 0; n-=1)
361
+ {
362
+ a=bmod2(bsqr(a),m, mu);
363
+ if(e[l] & (1<<n)) a=bmod2(bmul(a,g),m, mu);
364
+ }
365
+ n = bs-1;
366
+ }
367
+ return a;
368
+ }
369
+
370
+ // -----------------------------------------------------
371
+ // Compute s**e mod m for RSA public key operation
372
+
373
+ function RSAencrypt(s, e, m) { return bexpmod(s,e,m); }
374
+
375
+ // Compute m**d mod p*q for RSA private key operations.
376
+
377
+ function RSAdecrypt(m, d, p, q, u)
378
+ {
379
+ var xp = bmodexp(bmod(m,p), bmod(d,bsub(p,[1])), p);
380
+ var xq = bmodexp(bmod(m,q), bmod(d,bsub(q,[1])), q);
381
+
382
+ var t=bsub(xq,xp);
383
+ if(t.length==0)
384
+ {
385
+ t=bsub(xp,xq);
386
+ t=bmod(bmul(t, u), q);
387
+ t=bsub(q,t);
388
+ }
389
+ else
390
+ {
391
+ t=bmod(bmul(t, u), q);
392
+ }
393
+ return badd(bmul(t,p), xp);
394
+ }
395
+
396
+ // -----------------------------------------------------------------
397
+ // conversion functions: num array <-> multi precision integer (mpi)
398
+ // mpi: 2 octets with length in bits + octets in big endian order
399
+
400
+ function mpi2b(s)
401
+ {
402
+ var bn=1, r=[0], rn=0, sb=256;
403
+ var c, sn=s.length;
404
+ if(sn < 2) return 0;
405
+
406
+ var len=(sn-2)*8;
407
+ var bits=s.charCodeAt(0)*256+s.charCodeAt(1);
408
+ if(bits > len || bits < len-8) return 0;
409
+
410
+ for(var n=0; n<len; n++)
411
+ {
412
+ if((sb<<=1) > 255)
413
+ {
414
+ sb=1; c=s.charCodeAt(--sn);
415
+ }
416
+ if(bn > bm)
417
+ {
418
+ bn=1;
419
+ r[++rn]=0;
420
+ }
421
+ if(c & sb) r[rn]|=bn;
422
+ bn<<=1;
423
+ }
424
+ return r;
425
+ }
426
+
427
+ function b2mpi(b)
428
+ {
429
+ var bn=1, bc=0, r=[0], rb=1, rn=0;
430
+ var bits=b.length*bs;
431
+ var n, rr='';
432
+
433
+ for(n=0; n<bits; n++)
434
+ {
435
+ if(b[bc] & bn) r[rn]|=rb;
436
+ if((rb<<=1) > 255)
437
+ {
438
+ rb=1; r[++rn]=0;
439
+ }
440
+ if((bn<<=1) > bm)
441
+ {
442
+ bn=1; bc++;
443
+ }
444
+ }
445
+
446
+ while(rn && r[rn]==0) rn--;
447
+
448
+ bn=256;
449
+ for(bits=8; bits>0; bits--) if(r[rn] & (bn>>=1)) break;
450
+ bits+=rn*8;
451
+
452
+ rr+=String.fromCharCode(bits/256)+String.fromCharCode(bits%256);
453
+ if(bits) for(n=rn; n>=0; n--) rr+=String.fromCharCode(r[n]);
454
+ return rr;
455
+ }