UNPKG

14.3 kBJavaScriptView Raw
1var assert = require('assert')
2 , fs = require('fs')
3 , path = require('path')
4 , crypto = require('crypto')
5 , rimraf = require('rimraf')
6 , child_process = require('child_process')
7 , suppose = require('suppose')
8 , tmpDir = path.join(require('os').tmpDir(), Math.random().toString(36).slice(2))
9 , BIN = path.join(__dirname, '..', 'bin', 'salty')
10 , request = require('micro-request')
11
12describe('tests', function () {
13 var p = path.join(tmpDir, 'alice.jpg')
14
15 before(function () {
16 fs.mkdirSync(tmpDir)
17 if (!process.env.DEBUG) {
18 process.once('exit', function () {
19 rimraf.sync(tmpDir)
20 })
21 }
22 else console.log('tmpDir', tmpDir)
23 })
24
25 it('stream fixture', function (done) {
26 request('https://raw.githubusercontent.com/carlos8f/node-buffet/master/test/files/folder/Alice-white-rabbit.jpg', {stream: true}, function (err, resp, body) {
27 assert.ifError(err)
28 body.pipe(fs.createWriteStream(p))
29 .once('finish', done)
30 })
31 })
32 it('verify stream fixture', function (done) {
33 fs.createReadStream(p)
34 .pipe(crypto.createHash('sha1'))
35 .on('data', function (data) {
36 assert.equal(data.toString('hex'), '2bce2ffc40e0d90afe577a76db5db4290c48ddf4')
37 done()
38 })
39 })
40 it('set up alice', function (done) {
41 suppose(BIN, ['init', '--wallet', 'alice'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
42 .when('Creating wallet...\nYour name: ').respond('Alice\n')
43 .when('Your email address: ').respond('alice@s8f.org\n')
44 .when('Create a passphrase: ').respond('disney sucks\n')
45 .when('Verify passphrase: ').respond('disney sucks\n')
46 .end(function (code) {
47 assert(!code)
48 done()
49 })
50 })
51 it('set up bob', function (done) {
52 suppose(BIN, ['init', '--wallet', 'bob'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
53 .when('Creating wallet...\nYour name: ').respond('Bob\n')
54 .when('Your email address: ').respond('bob@s8f.org\n')
55 .when('Create a passphrase: ').respond('i am bob\n')
56 .when('Verify passphrase: ').respond('i am bob\n')
57 .end(function (code) {
58 assert(!code)
59 done()
60 })
61 })
62 var alice_pubkey
63 it('alice pubkey', function (done) {
64 var chunks = []
65 suppose(BIN, ['pubkey', '--wallet', 'alice'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
66 .end(function (code) {
67 assert(!code)
68 })
69 .stdout.on('data', function (chunk) {
70 chunks.push(chunk)
71 })
72 .once('end', function () {
73 var stdout = Buffer.concat(chunks).toString('utf8')
74 var match = stdout.match(/salty\-id ([a-zA-Z0-9-\_]+)\s*(?:"([^"]*)")?\s*(?:<([^>]*)>)?/)
75 assert(match)
76 alice_pubkey = match[0]
77 done()
78 })
79 })
80 it('alice change password', function (done) {
81 suppose(BIN, ['init', '--wallet', 'alice'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
82 .when('Wallet exists. Update it? (y/n): ').respond('y\n')
83 .when('Wallet is encrypted.\nEnter passphrase: ').respond('disney sucks\n')
84 .when('Your name: (Alice) ').respond('\n')
85 .when('Your email address: (alice@s8f.org) ').respond('\n')
86 .when('Create a passphrase: ').respond('not a blonde\n')
87 .when('Verify passphrase: ').respond('not a blonde\n')
88 .end(function (code) {
89 assert(!code)
90 done()
91 })
92 })
93 var bob_pubkey
94 it('bob pubkey', function (done) {
95 var chunks = []
96 suppose(BIN, ['pubkey', '--wallet', 'bob'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
97 .end(function (code) {
98 assert(!code)
99 })
100 .stdout.on('data', function (chunk) {
101 chunks.push(chunk)
102 })
103 .once('end', function () {
104 var stdout = Buffer.concat(chunks).toString('utf8')
105 var match = stdout.match(/salty\-id ([a-zA-Z0-9-\_]+)\s*(?:"([^"]*)")?\s*(?:<([^>]*)>)?/)
106 assert(match)
107 bob_pubkey = match[0]
108 done()
109 })
110 })
111 it('alice import bob', function (done) {
112 var chunks = []
113 var proc = suppose(BIN, ['import', '--wallet', 'alice', bob_pubkey], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
114 .when('Enter name: (Bob) ').respond('\n')
115 .when('Enter email: (bob@s8f.org) ').respond('\n')
116 .end(function (code) {
117 assert(!code)
118 done()
119 })
120 })
121 it('alice ls', function (done) {
122 var chunks = []
123 suppose(BIN, ['ls', '--wallet', 'alice'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
124 .end(function (code) {
125 assert(!code)
126 })
127 .stdout.on('data', function (chunk) {
128 chunks.push(chunk)
129 })
130 .once('end', function () {
131 var stdout = Buffer.concat(chunks).toString('utf8')
132 var match = stdout.match(/salty\-id ([a-zA-Z0-9-\_]+)\s*(?:"([^"]*)")?\s*(?:<([^>]*)>)?/g)
133 assert.equal(match.length, 1)
134 assert.equal(match[0], bob_pubkey)
135 done()
136 })
137 })
138 it('alice save', function (done) {
139 var chunks = []
140 var proc = suppose(BIN, ['save', '--wallet', 'alice'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
141 .when('Create a passphrase: ').respond('blarg\n')
142 .when('Verify passphrase: ').respond('blarg\n')
143 .end(function (code) {
144 assert(!code)
145 done()
146 })
147 })
148 it('alice destroy', function () {
149 rimraf.sync(path.join(tmpDir, 'alice'))
150 })
151 it('alice restore', function (done) {
152 var chunks = []
153 var proc = suppose(BIN, ['restore', 'salty.pem', 'alice'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
154 .when('Enter passphrase: ').respond('blarg\n')
155 .end(function (code) {
156 assert(!code)
157 done()
158 })
159 })
160 var outFile
161 it('alice encrypt for bob (no sign)', function (done) {
162 var chunks = []
163 var proc = suppose(BIN, ['encrypt', '--to', 'bob@s8f.org', 'alice.jpg', '--wallet', 'alice'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
164 .end(function (code) {
165 assert(!code)
166 })
167 .stdout.on('data', function (chunk) {
168 chunks.push(chunk)
169 })
170 .once('end', function () {
171 var stdout = Buffer.concat(chunks).toString('utf8')
172 var match = stdout.match(/Encrypted to (.*)/)
173 assert(match)
174 outFile = match[1]
175 done()
176 })
177 })
178 it('bob decrypt', function (done) {
179 var proc = suppose(BIN, ['decrypt', outFile, '--wallet', 'bob'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
180 .when('Wallet is encrypted.\nEnter passphrase: ').respond('i am bob\n')
181 .end(function (code) {
182 assert(!code)
183 done()
184 })
185 })
186 it('verify decrypt', function (done) {
187 fs.createReadStream(path.join(tmpDir, outFile.replace('.salty', '')))
188 .pipe(crypto.createHash('sha1'))
189 .on('data', function (data) {
190 assert.equal(data.toString('hex'), '2bce2ffc40e0d90afe577a76db5db4290c48ddf4')
191 done()
192 })
193 })
194 it('alice encrypt for bob (sign)', function (done) {
195 var chunks = []
196 var proc = suppose(BIN, ['encrypt', '--to', 'bob@s8f.org', 'alice.jpg', '--sign', '--wallet', 'alice'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
197 .when('Wallet is encrypted.\nEnter passphrase: ').respond('not a blonde\n')
198 .end(function (code) {
199 assert(!code)
200 })
201 .stdout.on('data', function (chunk) {
202 chunks.push(chunk)
203 })
204 .once('end', function () {
205 var stdout = Buffer.concat(chunks).toString('utf8')
206 var match = stdout.match(/Encrypted to (.*)/)
207 assert(match)
208 assert(match[1] !== outFile)
209 outFile = match[1]
210 done()
211 })
212 })
213 it('bob decrypt', function (done) {
214 var proc = suppose(BIN, ['decrypt', outFile, '--sig', '--wallet', 'bob'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
215 .when('Wallet is encrypted.\nEnter passphrase: ').respond('i am bob\n')
216 .end(function (code) {
217 assert(!code)
218 done()
219 })
220 })
221 it('verify decrypt', function (done) {
222 fs.createReadStream(path.join(tmpDir, outFile.replace('.salty', '')))
223 .pipe(crypto.createHash('sha1'))
224 .on('data', function (data) {
225 assert.equal(data.toString('hex'), '2bce2ffc40e0d90afe577a76db5db4290c48ddf4')
226 done()
227 })
228 })
229 it('stream fixture', function (done) {
230 request('https://gist.githubusercontent.com/carlos8f/a3fd03a48341e36bd2d1/raw/bc01eeaf1b664f79bf4de9c917ac87f94a291a76/jabberwocky.txt', {stream: true}, function (err, resp, body) {
231 assert.ifError(err)
232 body.pipe(fs.createWriteStream(path.join(tmpDir, 'jabberwocky.txt')))
233 .once('finish', done)
234 })
235 })
236 it('verify stream fixture', function (done) {
237 fs.createReadStream(path.join(tmpDir, 'jabberwocky.txt'))
238 .pipe(crypto.createHash('sha1'))
239 .on('data', function (data) {
240 assert.equal(data.toString('hex'), '24a80c902db33368958664babde4b019cdaa65f0')
241 done()
242 })
243 })
244 var pem
245 it('alice encrypt for bob (armor)', function (done) {
246 var chunks = []
247 var proc = suppose(BIN, ['encrypt', '--to', 'bob@s8f.org', 'jabberwocky.txt', '--sign', '--armor', '--wallet', 'alice'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
248 .when('Wallet is encrypted.\nEnter passphrase: ').respond('not a blonde\n')
249 .end(function (code) {
250 assert(!code)
251 })
252 .stdout.on('data', function (chunk) {
253 chunks.push(chunk)
254 })
255 .once('end', function () {
256 var stdout = Buffer.concat(chunks).toString('utf8')
257 assert(stdout.match(/BEGIN SALTY MESSAGE/))
258 assert(stdout.match(/END SALTY MESSAGE/))
259 pem = stdout
260 done()
261 })
262 })
263 it('write pem to file', function (done) {
264 fs.writeFile(path.join(tmpDir, 'ctxt.pem'), pem, done)
265 })
266 var stdout
267 it('bob decrypt', function (done) {
268 var chunks = [], valid = false
269 var proc = suppose(BIN, ['decrypt', 'ctxt.pem', '--sig', '--wallet', 'bob'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
270 .when('Wallet is encrypted.\nEnter passphrase: ').respond('i am bob\n')
271 .end(function (code) {
272 assert(!code)
273 assert(stdout)
274 assert(valid)
275 done()
276 })
277 .stdout.on('data', function (chunk) {
278 chunks.push(chunk)
279 })
280 .once('end', function () {
281 stdout = Buffer.concat(chunks).toString('utf8')
282 var beginMatch = stdout.match(/^'Twas brillig, and the slithy toves/)
283 assert(beginMatch, stdout)
284 var endMatch = stdout.match(/And the mome raths outgrabe\.$/)
285 assert(endMatch, stdout)
286 valid = true
287 })
288 })
289 var msg
290 it('alice encrypt for bob (compose)', function (done) {
291 var chunks = [], valid = false
292 msg = 'Hi,\n\nThis is my message...\n\nRegards,\Alice\n'
293 var proc = suppose(BIN, ['encrypt', '--to', 'bob@s8f.org', '--sign', '--message', '--wallet', 'alice'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
294 .when('Wallet is encrypted.\nEnter passphrase: ').respond('not a blonde\n')
295 .when('\nCompose message: (CTL-D when done)\n\n> ').respond(msg + '\4')
296 .end(function (code) {
297 assert(!code)
298 assert(valid)
299 done()
300 })
301 .stdout.on('data', function (chunk) {
302 chunks.push(chunk)
303 })
304 .once('end', function () {
305 var stdout = Buffer.concat(chunks).toString('utf8')
306 assert(stdout.match(/BEGIN SALTY MESSAGE/))
307 assert(stdout.match(/END SALTY MESSAGE/))
308 pem = stdout
309 valid = true
310 })
311 })
312 it('write pem to file', function (done) {
313 fs.writeFile(path.join(tmpDir, 'ctxt.pem'), pem, done)
314 })
315 it('bob decrypt', function (done) {
316 var chunks = [], valid = false
317 var proc = suppose(BIN, ['decrypt', 'ctxt.pem', '--sig', '--wallet', 'bob'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
318 .when('Wallet is encrypted.\nEnter passphrase: ').respond('i am bob\n')
319 .end(function (code) {
320 assert(!code)
321 assert(stdout)
322 assert(valid)
323 done()
324 })
325 .stdout.on('data', function (chunk) {
326 chunks.push(chunk)
327 })
328 .once('end', function () {
329 stdout = Buffer.concat(chunks).toString('utf8')
330 assert.deepEqual(stdout, msg)
331 valid = true
332 })
333 })
334 it('alice sign', function (done) {
335 var chunks = [], valid = false
336 msg = 'Hi,\n\nThis is my message...\n\nRegards,\Alice\n'
337 var proc = suppose(BIN, ['sign', '--wallet', 'alice', 'alice.jpg'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
338 .when('Wallet is encrypted.\nEnter passphrase: ').respond('not a blonde\n')
339 .end(function (code) {
340 assert(!code)
341 assert(valid)
342 done()
343 })
344 .stdout.on('data', function (chunk) {
345 chunks.push(chunk)
346 })
347 .once('end', function () {
348 var stdout = Buffer.concat(chunks).toString('utf8')
349 var match = stdout.match(/Wrote signature to alice\.jpg\.salty-sig/)
350 assert(match)
351 valid = true
352 })
353 })
354 var stderr
355 it('bob verify', function (done) {
356 var chunks = [], valid = false
357 var proc = suppose(BIN, ['verify', 'alice.jpg'], {cwd: tmpDir, debug: fs.createWriteStream('/tmp/debug.txt')})
358 .end(function (code) {
359 assert(!code)
360 assert(stdout)
361 assert(valid)
362 done()
363 })
364 .stderr.on('data', function (chunk) {
365 chunks.push(chunk)
366 })
367 .once('end', function () {
368 stderr = Buffer.concat(chunks).toString('utf8')
369 var match = stderr.match(/signature:\s*OK/)
370 assert(match)
371 valid = true
372 })
373 })
374
375 /* errors
376 - init over existing dir
377 - import error
378 - restore bad pw
379 - open wallet bad pw
380 - encrypt noent, encrypt bad recip
381 - decrypt noent
382 - decrypt fail (bad hash, bad sig, box open)
383 - verify fail
384
385 edge cases
386 - init in home/specified dir
387 - init without email
388 - init without name
389 - weird chars in id?
390 - import from url/file
391 - encrypt for self
392 - force flag
393 - armor flag
394 - delete flag
395 - sign/verify path detection
396 */
397})
\No newline at end of file