ec01a09c by brandonocasey

browserify-p3: decrypter

convert decrypter module to es6/node/browserify
stub old functionalify to get all tests working
updated scripts to keep builds and tests working
1 parent a8daa7f7
...@@ -47,13 +47,11 @@ ...@@ -47,13 +47,11 @@
47 47
48 <script src="/node_modules/video.js/dist/video.js"></script> 48 <script src="/node_modules/video.js/dist/video.js"></script>
49 <script src="/node_modules/videojs-contrib-media-sources/dist/videojs-media-sources.js"></script> 49 <script src="/node_modules/videojs-contrib-media-sources/dist/videojs-media-sources.js"></script>
50 <script src="/node_modules/pkcs7/dist/pkcs7.unpad.js"></script>
51 <script src="/src/videojs-contrib-hls.js"></script> 50 <script src="/src/videojs-contrib-hls.js"></script>
52 <script src="/src/xhr.js"></script> 51 <script src="/src/xhr.js"></script>
53 <script src="/dist/videojs-contrib-hls.js"></script> 52 <script src="/dist/videojs-contrib-hls.js"></script>
54 <script src="/src/playlist.js"></script> 53 <script src="/src/playlist.js"></script>
55 <script src="/src/playlist-loader.js"></script> 54 <script src="/src/playlist-loader.js"></script>
56 <script src="/src/decrypter.js"></script>
57 <script src="/src/bin-utils.js"></script> 55 <script src="/src/bin-utils.js"></script>
58 <script> 56 <script>
59 (function(window, videojs) { 57 (function(window, videojs) {
......
...@@ -2,7 +2,7 @@ var browserify = require('browserify'); ...@@ -2,7 +2,7 @@ var browserify = require('browserify');
2 var fs = require('fs'); 2 var fs = require('fs');
3 var glob = require('glob'); 3 var glob = require('glob');
4 4
5 glob('test/{m3u8,stub}.test.js', function(err, files) { 5 glob('test/{decryper,m3u8,stub}.test.js', function(err, files) {
6 browserify(files) 6 browserify(files)
7 .transform('babelify') 7 .transform('babelify')
8 .bundle() 8 .bundle()
......
...@@ -3,7 +3,7 @@ var fs = require('fs'); ...@@ -3,7 +3,7 @@ var fs = require('fs');
3 var glob = require('glob'); 3 var glob = require('glob');
4 var watchify = require('watchify'); 4 var watchify = require('watchify');
5 5
6 glob('test/{m3u8,stub}.test.js', function(err, files) { 6 glob('test/{decrypter,m3u8,stub}.test.js', function(err, files) {
7 var b = browserify(files, { 7 var b = browserify(files, {
8 cache: {}, 8 cache: {},
9 packageCache: {}, 9 packageCache: {},
......
1 import m3u8 from './m3u8'; 1 import m3u8 from './m3u8';
2 import Stream from './stream'; 2 import Stream from './stream';
3 import videojs from 'video.js'; 3 import videojs from 'video.js';
4 import {Decrypter, decrypt, AsyncStream} from './decrypter';
4 5
5 if(typeof window.videojs.Hls === 'undefined') { 6 if(typeof window.videojs.Hls === 'undefined') {
6 videojs.Hls = {}; 7 videojs.Hls = {};
7 } 8 }
8 videojs.Hls.Stream = Stream; 9 videojs.Hls.Stream = Stream;
9 videojs.m3u8 = m3u8; 10 videojs.m3u8 = m3u8;
10 11 videojs.Hls.decrypt = decrypt;
12 videojs.Hls.Decrypter = Decrypter;
13 videojs.Hls.AsyncStream = AsyncStream;
......
1 (function(window, videojs, unpad, undefined) {
2 'use strict';
3 /*
4 ======== A Handy Little QUnit Reference ========
5 http://api.qunitjs.com/
6
7 Test methods:
8 module(name, {[setup][ ,teardown]})
9 test(name, callback)
10 expect(numberOfAssertions)
11 stop(increment)
12 start(decrement)
13 Test assertions:
14 ok(value, [message])
15 equal(actual, expected, [message])
16 notEqual(actual, expected, [message])
17 deepEqual(actual, expected, [message])
18 notDeepEqual(actual, expected, [message])
19 strictEqual(actual, expected, [message])
20 notStrictEqual(actual, expected, [message])
21 throws(block, [expected], [message])
22 */
23
24 // see docs/hlse.md for instructions on how test data was generated 1 // see docs/hlse.md for instructions on how test data was generated
2 import QUnit from 'qunit';
3 import {unpad} from 'pkcs7';
4 import sinon from 'sinon';
5 import {decrypt, Decrypter, AsyncStream} from '../src/decrypter';
25 6
26 var stringFromBytes = function(bytes) { 7 // see docs/hlse.md for instructions on how test data was generated
27 var result = '', i; 8 const stringFromBytes = function(bytes) {
9 let result = '';
28 10
29 for (i = 0; i < bytes.length; i++) { 11 for (let i = 0; i < bytes.length; i++) {
30 result += String.fromCharCode(bytes[i]); 12 result += String.fromCharCode(bytes[i]);
31 } 13 }
32 return result; 14 return result;
33 }; 15 };
34 16
35 QUnit.module('Decryption'); 17 QUnit.module('Decryption');
36 18 QUnit.test('decrypts a single AES-128 with PKCS7 block', function() {
37 test('decrypts a single AES-128 with PKCS7 block', function() { 19 let key = new Uint32Array([0, 0, 0, 0]);
38 var 20 let initVector = key;
39 key = new Uint32Array([0, 0, 0, 0]), 21 // the string "howdy folks" encrypted
40 initVector = key, 22 let encrypted = new Uint8Array([
41 // the string "howdy folks" encrypted 23 0xce, 0x90, 0x97, 0xd0,
42 encrypted = new Uint8Array([ 24 0x08, 0x46, 0x4d, 0x18,
43 0xce, 0x90, 0x97, 0xd0, 25 0x4f, 0xae, 0x01, 0x1c,
44 0x08, 0x46, 0x4d, 0x18, 26 0x82, 0xa8, 0xf0, 0x67
45 0x4f, 0xae, 0x01, 0x1c, 27 ]);
46 0x82, 0xa8, 0xf0, 0x67]); 28
47 29 QUnit.deepEqual('howdy folks',
48 deepEqual('howdy folks', 30 stringFromBytes(unpad(decrypt(encrypted, key, initVector))),
49 stringFromBytes(unpad(videojs.Hls.decrypt(encrypted, key, initVector))), 31 'decrypted with a byte array key'
50 'decrypted with a byte array key'); 32 );
51 }); 33 });
52 34
53 test('decrypts multiple AES-128 blocks with CBC', function() { 35 QUnit.test('decrypts multiple AES-128 blocks with CBC', function() {
54 var 36 let key = new Uint32Array([0, 0, 0, 0]);
55 key = new Uint32Array([0, 0, 0, 0]), 37 let initVector = key;
56 initVector = key,
57 // the string "0123456789abcdef01234" encrypted 38 // the string "0123456789abcdef01234" encrypted
58 encrypted = new Uint8Array([ 39 let encrypted = new Uint8Array([
59 0x14, 0xf5, 0xfe, 0x74, 40 0x14, 0xf5, 0xfe, 0x74,
60 0x69, 0x66, 0xf2, 0x92, 41 0x69, 0x66, 0xf2, 0x92,
61 0x65, 0x1c, 0x22, 0x88, 42 0x65, 0x1c, 0x22, 0x88,
62 0xbb, 0xff, 0x46, 0x09, 43 0xbb, 0xff, 0x46, 0x09,
63 44
64 0x0b, 0xde, 0x5e, 0x71, 45 0x0b, 0xde, 0x5e, 0x71,
65 0x77, 0x87, 0xeb, 0x84, 46 0x77, 0x87, 0xeb, 0x84,
66 0xa9, 0x54, 0xc2, 0x45, 47 0xa9, 0x54, 0xc2, 0x45,
67 0xe9, 0x4e, 0x29, 0xb3 48 0xe9, 0x4e, 0x29, 0xb3
68 ]); 49 ]);
69 50
70 deepEqual('0123456789abcdef01234', 51 QUnit.deepEqual('0123456789abcdef01234',
71 stringFromBytes(unpad(videojs.Hls.decrypt(encrypted, key, initVector))), 52 stringFromBytes(unpad(decrypt(encrypted, key, initVector))),
72 'decrypted multiple blocks'); 53 'decrypted multiple blocks');
73 }); 54 });
74 55
75 var clock;
76
77 QUnit.module('Incremental Processing', { 56 QUnit.module('Incremental Processing', {
78 setup: function() { 57 beforeEach() {
79 clock = sinon.useFakeTimers(); 58 this.clock = sinon.useFakeTimers();
80 }, 59 },
81 teardown: function() { 60 afterEach() {
82 clock.restore(); 61 this.clock.restore();
83 } 62 }
84 }); 63 });
85 64
86 test('executes a callback after a timeout', function() { 65 QUnit.test('executes a callback after a timeout', function() {
87 var asyncStream = new videojs.Hls.AsyncStream(), 66 let asyncStream = new AsyncStream();
88 calls = ''; 67 let calls = '';
68
89 asyncStream.push(function() { 69 asyncStream.push(function() {
90 calls += 'a'; 70 calls += 'a';
91 }); 71 });
92 72
93 clock.tick(asyncStream.delay); 73 this.clock.tick(asyncStream.delay);
94 equal(calls, 'a', 'invoked the callback once'); 74 QUnit.equal(calls, 'a', 'invoked the callback once');
95 clock.tick(asyncStream.delay); 75 this.clock.tick(asyncStream.delay);
96 equal(calls, 'a', 'only invoked the callback once'); 76 QUnit.equal(calls, 'a', 'only invoked the callback once');
97 }); 77 });
98 78
99 test('executes callback in series', function() { 79 QUnit.test('executes callback in series', function() {
100 var asyncStream = new videojs.Hls.AsyncStream(), 80 let asyncStream = new AsyncStream();
101 calls = ''; 81 let calls = '';
82
102 asyncStream.push(function() { 83 asyncStream.push(function() {
103 calls += 'a'; 84 calls += 'a';
104 }); 85 });
...@@ -106,62 +87,68 @@ test('executes callback in series', function() { ...@@ -106,62 +87,68 @@ test('executes callback in series', function() {
106 calls += 'b'; 87 calls += 'b';
107 }); 88 });
108 89
109 clock.tick(asyncStream.delay); 90 this.clock.tick(asyncStream.delay);
110 equal(calls, 'a', 'invoked the first callback'); 91 QUnit.equal(calls, 'a', 'invoked the first callback');
111 clock.tick(asyncStream.delay); 92 this.clock.tick(asyncStream.delay);
112 equal(calls, 'ab', 'invoked the second'); 93 QUnit.equal(calls, 'ab', 'invoked the second');
113 }); 94 });
114 95
115 var decrypter;
116
117 QUnit.module('Incremental Decryption', { 96 QUnit.module('Incremental Decryption', {
118 setup: function() { 97 beforeEach() {
119 clock = sinon.useFakeTimers(); 98 this.clock = sinon.useFakeTimers();
120 }, 99 },
121 teardown: function() { 100 afterEach() {
122 clock.restore(); 101 this.clock.restore();
123 } 102 }
124 }); 103 });
125 104
126 test('asynchronously decrypts a 4-word block', function() { 105 QUnit.test('asynchronously decrypts a 4-word block', function() {
127 var 106 let key = new Uint32Array([0, 0, 0, 0]);
128 key = new Uint32Array([0, 0, 0, 0]), 107 let initVector = key;
129 initVector = key, 108 // the string "howdy folks" encrypted
130 // the string "howdy folks" encrypted 109 let encrypted = new Uint8Array([
131 encrypted = new Uint8Array([ 110 0xce, 0x90, 0x97, 0xd0,
132 0xce, 0x90, 0x97, 0xd0, 111 0x08, 0x46, 0x4d, 0x18,
133 0x08, 0x46, 0x4d, 0x18, 112 0x4f, 0xae, 0x01, 0x1c,
134 0x4f, 0xae, 0x01, 0x1c, 113 0x82, 0xa8, 0xf0, 0x67
135 0x82, 0xa8, 0xf0, 0x67]), 114 ]);
136 decrypted; 115 let decrypted;
137 116 let decrypter = new Decrypter(
138 decrypter = new videojs.Hls.Decrypter(encrypted, key, initVector, function(error, result) { 117 encrypted,
139 decrypted = result; 118 key,
140 }); 119 initVector,
141 ok(!decrypted, 'asynchronously decrypts'); 120 function(error, result) {
142 121 if (error) {
143 clock.tick(decrypter.asyncStream_.delay * 2); 122 throw new Error(error);
144 123 }
145 ok(decrypted, 'completed decryption'); 124 decrypted = result;
146 deepEqual('howdy folks', 125 }
147 stringFromBytes(decrypted), 126 );
148 'decrypts and unpads the result'); 127
128 QUnit.ok(!decrypted, 'asynchronously decrypts');
129 this.clock.tick(decrypter.asyncStream_.delay * 2);
130
131 QUnit.ok(decrypted, 'completed decryption');
132 QUnit.deepEqual('howdy folks',
133 stringFromBytes(decrypted),
134 'decrypts and unpads the result');
149 }); 135 });
150 136
151 test('breaks up input greater than the step value', function() { 137 QUnit.test('breaks up input greater than the step value', function() {
152 var encrypted = new Int32Array(videojs.Hls.Decrypter.STEP + 4), 138 let encrypted = new Int32Array(Decrypter.STEP + 4);
153 done = false, 139 let done = false;
154 decrypter = new videojs.Hls.Decrypter(encrypted, 140 let decrypter = new Decrypter(
155 new Uint32Array(4), 141 encrypted,
156 new Uint32Array(4), 142 new Uint32Array(4),
157 function() { 143 new Uint32Array(4),
158 done = true; 144 function() {
159 }); 145 done = true;
160 clock.tick(decrypter.asyncStream_.delay * 2); 146 }
161 ok(!done, 'not finished after two ticks'); 147 );
162 148
163 clock.tick(decrypter.asyncStream_.delay); 149 this.clock.tick(decrypter.asyncStream_.delay * 2);
164 ok(done, 'finished after the last chunk is decrypted'); 150 QUnit.ok(!done, 'not finished after two ticks');
151
152 this.clock.tick(decrypter.asyncStream_.delay);
153 QUnit.ok(done, 'finished after the last chunk is decrypted');
165 }); 154 });
166
167 })(window, window.videojs, window.pkcs7.unpad);
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
12 <!-- NOTE in order for test to pass we require sinon 1.10.2 exactly --> 12 <!-- NOTE in order for test to pass we require sinon 1.10.2 exactly -->
13 <script src="/node_modules/sinon/pkg/sinon.js"></script> 13 <script src="/node_modules/sinon/pkg/sinon.js"></script>
14 <script src="/node_modules/qunitjs/qunit/qunit.js"></script> 14 <script src="/node_modules/qunitjs/qunit/qunit.js"></script>
15 <script src="/node_modules/pkcs7/dist/pkcs7.unpad.js"></script>
16 <script src="/node_modules/video.js/dist/video.js"></script> 15 <script src="/node_modules/video.js/dist/video.js"></script>
17 <script src="/node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js"></script> 16 <script src="/node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js"></script>
18 17
...@@ -21,14 +20,12 @@ ...@@ -21,14 +20,12 @@
21 <script src="/dist/videojs-contrib-hls.js"></script> 20 <script src="/dist/videojs-contrib-hls.js"></script>
22 <script src="/src/playlist.js"></script> 21 <script src="/src/playlist.js"></script>
23 <script src="/src/playlist-loader.js"></script> 22 <script src="/src/playlist-loader.js"></script>
24 <script src="/src/decrypter.js"></script>
25 <script src="/src/bin-utils.js"></script> 23 <script src="/src/bin-utils.js"></script>
26 24
27 <script src="/test/videojs-contrib-hls.test.js"></script> 25 <script src="/test/videojs-contrib-hls.test.js"></script>
28 <script src="/dist-test/videojs-contrib-hls.js"></script> 26 <script src="/dist-test/videojs-contrib-hls.js"></script>
29 <script src="/test/playlist.test.js"></script> 27 <script src="/test/playlist.test.js"></script>
30 <script src="/test/playlist-loader.test.js"></script> 28 <script src="/test/playlist-loader.test.js"></script>
31 <script src="/test/decrypter.test.js"></script>
32 29
33 </body> 30 </body>
34 </html> 31 </html>
......
...@@ -12,7 +12,6 @@ var DEFAULTS = { ...@@ -12,7 +12,6 @@ var DEFAULTS = {
12 'node_modules/video.js/dist/video-js.css', 12 'node_modules/video.js/dist/video-js.css',
13 13
14 // REMOVE ME WHEN BROWSERIFIED 14 // REMOVE ME WHEN BROWSERIFIED
15 'node_modules/pkcs7/dist/pkcs7.unpad.js',
16 'node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js', 15 'node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js',
17 16
18 // these two stub old functionality 17 // these two stub old functionality
...@@ -22,7 +21,6 @@ var DEFAULTS = { ...@@ -22,7 +21,6 @@ var DEFAULTS = {
22 21
23 'src/playlist.js', 22 'src/playlist.js',
24 'src/playlist-loader.js', 23 'src/playlist-loader.js',
25 'src/decrypter.js',
26 'src/bin-utils.js', 24 'src/bin-utils.js',
27 25
28 'test/stub.test.js', 26 'test/stub.test.js',
...@@ -47,7 +45,7 @@ var DEFAULTS = { ...@@ -47,7 +45,7 @@ var DEFAULTS = {
47 ], 45 ],
48 46
49 preprocessors: { 47 preprocessors: {
50 'test/{stub,m3u8}.test.js': ['browserify'] 48 'test/{decrypter,stub,m3u8}.test.js': ['browserify']
51 }, 49 },
52 50
53 reporters: ['dots'], 51 reporters: ['dots'],
......