crypto_spec.js 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235
  1. /* Copyright 2017 Mozilla Foundation
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. 'use strict';
  16. var coreCrypto = require('../../core/crypto.js');
  17. var corePrimitives = require('../../core/primitives.js');
  18. var sharedUtil = require('../../shared/util.js');
  19. var calculateMD5 = coreCrypto.calculateMD5;
  20. var ARCFourCipher = coreCrypto.ARCFourCipher;
  21. var calculateSHA256 = coreCrypto.calculateSHA256;
  22. var calculateSHA384 = coreCrypto.calculateSHA384;
  23. var calculateSHA512 = coreCrypto.calculateSHA512;
  24. var AES128Cipher = coreCrypto.AES128Cipher;
  25. var AES256Cipher = coreCrypto.AES256Cipher;
  26. var PDF17 = coreCrypto.PDF17;
  27. var PDF20 = coreCrypto.PDF20;
  28. var CipherTransformFactory = coreCrypto.CipherTransformFactory;
  29. var Name = corePrimitives.Name;
  30. var Dict = corePrimitives.Dict;
  31. var stringToBytes = sharedUtil.stringToBytes;
  32. var PasswordException = sharedUtil.PasswordException;
  33. var PasswordResponses = sharedUtil.PasswordResponses;
  34. describe('crypto', function () {
  35. function hex2binary(s) {
  36. var digits = '0123456789ABCDEF';
  37. s = s.toUpperCase();
  38. var n = s.length >> 1, i, j;
  39. var result = new Uint8Array(n);
  40. for (i = 0, j = 0; i < n; ++i) {
  41. var d1 = s.charAt(j++);
  42. var d2 = s.charAt(j++);
  43. var value = digits.indexOf(d1) << 4 | digits.indexOf(d2);
  44. result[i] = value;
  45. }
  46. return result;
  47. }
  48. describe('calculateMD5', function () {
  49. it('should pass RFC 1321 test #1', function () {
  50. var input, result, expected;
  51. input = stringToBytes('');
  52. result = calculateMD5(input, 0, input.length);
  53. expected = hex2binary('d41d8cd98f00b204e9800998ecf8427e');
  54. expect(result).toEqual(expected);
  55. });
  56. it('should pass RFC 1321 test #2', function () {
  57. var input, result, expected;
  58. input = stringToBytes('a');
  59. result = calculateMD5(input, 0, input.length);
  60. expected = hex2binary('0cc175b9c0f1b6a831c399e269772661');
  61. expect(result).toEqual(expected);
  62. });
  63. it('should pass RFC 1321 test #3', function () {
  64. var input, result, expected;
  65. input = stringToBytes('abc');
  66. result = calculateMD5(input, 0, input.length);
  67. expected = hex2binary('900150983cd24fb0d6963f7d28e17f72');
  68. expect(result).toEqual(expected);
  69. });
  70. it('should pass RFC 1321 test #4', function () {
  71. var input, result, expected;
  72. input = stringToBytes('message digest');
  73. result = calculateMD5(input, 0, input.length);
  74. expected = hex2binary('f96b697d7cb7938d525a2f31aaf161d0');
  75. expect(result).toEqual(expected);
  76. });
  77. it('should pass RFC 1321 test #5', function () {
  78. var input, result, expected;
  79. input = stringToBytes('abcdefghijklmnopqrstuvwxyz');
  80. result = calculateMD5(input, 0, input.length);
  81. expected = hex2binary('c3fcd3d76192e4007dfb496cca67e13b');
  82. expect(result).toEqual(expected);
  83. });
  84. it('should pass RFC 1321 test #6', function () {
  85. var input, result, expected;
  86. input = stringToBytes('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv' + 'wxyz0123456789');
  87. result = calculateMD5(input, 0, input.length);
  88. expected = hex2binary('d174ab98d277d9f5a5611c2c9f419d9f');
  89. expect(result).toEqual(expected);
  90. });
  91. it('should pass RFC 1321 test #7', function () {
  92. var input, result, expected;
  93. input = stringToBytes('123456789012345678901234567890123456789012345678' + '90123456789012345678901234567890');
  94. result = calculateMD5(input, 0, input.length);
  95. expected = hex2binary('57edf4a22be3c955ac49da2e2107b67a');
  96. expect(result).toEqual(expected);
  97. });
  98. });
  99. describe('ARCFourCipher', function () {
  100. it('should pass test #1', function () {
  101. var key, input, result, expected, cipher;
  102. key = hex2binary('0123456789abcdef');
  103. input = hex2binary('0123456789abcdef');
  104. cipher = new ARCFourCipher(key);
  105. result = cipher.encryptBlock(input);
  106. expected = hex2binary('75b7878099e0c596');
  107. expect(result).toEqual(expected);
  108. });
  109. it('should pass test #2', function () {
  110. var key, input, result, expected, cipher;
  111. key = hex2binary('0123456789abcdef');
  112. input = hex2binary('0000000000000000');
  113. cipher = new ARCFourCipher(key);
  114. result = cipher.encryptBlock(input);
  115. expected = hex2binary('7494c2e7104b0879');
  116. expect(result).toEqual(expected);
  117. });
  118. it('should pass test #3', function () {
  119. var key, input, result, expected, cipher;
  120. key = hex2binary('0000000000000000');
  121. input = hex2binary('0000000000000000');
  122. cipher = new ARCFourCipher(key);
  123. result = cipher.encryptBlock(input);
  124. expected = hex2binary('de188941a3375d3a');
  125. expect(result).toEqual(expected);
  126. });
  127. it('should pass test #4', function () {
  128. var key, input, result, expected, cipher;
  129. key = hex2binary('ef012345');
  130. input = hex2binary('00000000000000000000');
  131. cipher = new ARCFourCipher(key);
  132. result = cipher.encryptBlock(input);
  133. expected = hex2binary('d6a141a7ec3c38dfbd61');
  134. expect(result).toEqual(expected);
  135. });
  136. it('should pass test #5', function () {
  137. var key, input, result, expected, cipher;
  138. key = hex2binary('0123456789abcdef');
  139. input = hex2binary('010101010101010101010101010101010101010101010101010' + '10101010101010101010101010101010101010101010101010101010101010101010' + '10101010101010101010101010101010101010101010101010101010101010101010' + '10101010101010101010101010101010101010101010101010101010101010101010' + '10101010101010101010101010101010101010101010101010101010101010101010' + '10101010101010101010101010101010101010101010101010101010101010101010' + '10101010101010101010101010101010101010101010101010101010101010101010' + '10101010101010101010101010101010101010101010101010101010101010101010' + '10101010101010101010101010101010101010101010101010101010101010101010' + '10101010101010101010101010101010101010101010101010101010101010101010' + '10101010101010101010101010101010101010101010101010101010101010101010' + '10101010101010101010101010101010101010101010101010101010101010101010' + '10101010101010101010101010101010101010101010101010101010101010101010' + '10101010101010101010101010101010101010101010101010101010101010101010' + '10101010101010101010101010101010101010101010101010101010101010101010' + '101010101010101010101');
  140. cipher = new ARCFourCipher(key);
  141. result = cipher.encryptBlock(input);
  142. expected = hex2binary('7595c3e6114a09780c4ad452338e1ffd9a1be9498f813d76' + '533449b6778dcad8c78a8d2ba9ac66085d0e53d59c26c2d1c490c1ebbe0ce66d1b6b' + '1b13b6b919b847c25a91447a95e75e4ef16779cde8bf0a95850e32af9689444fd377' + '108f98fdcbd4e726567500990bcc7e0ca3c4aaa304a387d20f3b8fbbcd42a1bd311d' + '7a4303dda5ab078896ae80c18b0af66dff319616eb784e495ad2ce90d7f772a81747' + 'b65f62093b1e0db9e5ba532fafec47508323e671327df9444432cb7367cec82f5d44' + 'c0d00b67d650a075cd4b70dedd77eb9b10231b6b5b741347396d62897421d43df9b4' + '2e446e358e9c11a9b2184ecbef0cd8e7a877ef968f1390ec9b3d35a5585cb009290e' + '2fcde7b5ec66d9084be44055a619d9dd7fc3166f9487f7cb272912426445998514c1' + '5d53a18c864ce3a2b7555793988126520eacf2e3066e230c91bee4dd5304f5fd0405' + 'b35bd99c73135d3d9bc335ee049ef69b3867bf2d7bd1eaa595d8bfc0066ff8d31509' + 'eb0c6caa006c807a623ef84c3d33c195d23ee320c40de0558157c822d4b8c569d849' + 'aed59d4e0fd7f379586b4b7ff684ed6a189f7486d49b9c4bad9ba24b96abf924372c' + '8a8fffb10d55354900a77a3db5f205e1b99fcd8660863a159ad4abe40fa48934163d' + 'dde542a6585540fd683cbfd8c00f12129a284deacc4cdefe58be7137541c047126c8' + 'd49e2755ab181ab7e940b0c0');
  143. expect(result).toEqual(expected);
  144. });
  145. it('should pass test #6', function () {
  146. var key, input, result, expected, cipher;
  147. key = hex2binary('fb029e3031323334');
  148. input = hex2binary('aaaa0300000008004500004e661a00008011be640a0001220af' + 'fffff00890089003a000080a601100001000000000000204543454a4548454346434' + '550464545494546464343414341434143414341414100002000011bd0b604');
  149. cipher = new ARCFourCipher(key);
  150. result = cipher.encryptBlock(input);
  151. expected = hex2binary('f69c5806bd6ce84626bcbefb9474650aad1f7909b0f64d5f' + '58a503a258b7ed22eb0ea64930d3a056a55742fcce141d485f8aa836dea18df42c53' + '80805ad0c61a5d6f58f41040b24b7d1a693856ed0d4398e7aee3bf0e2a2ca8f7');
  152. expect(result).toEqual(expected);
  153. });
  154. it('should pass test #7', function () {
  155. var key, input, result, expected, cipher;
  156. key = hex2binary('0123456789abcdef');
  157. input = hex2binary('123456789abcdef0123456789abcdef0123456789abcdef0123' + '45678');
  158. cipher = new ARCFourCipher(key);
  159. result = cipher.encryptBlock(input);
  160. expected = hex2binary('66a0949f8af7d6891f7f832ba833c00c892ebe30143ce287' + '40011ecf');
  161. expect(result).toEqual(expected);
  162. });
  163. });
  164. describe('calculateSHA256', function () {
  165. it('should properly hash abc', function () {
  166. var input, result, expected;
  167. input = stringToBytes('abc');
  168. result = calculateSHA256(input, 0, input.length);
  169. expected = hex2binary('BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9C' + 'B410FF61F20015AD');
  170. expect(result).toEqual(expected);
  171. });
  172. it('should properly hash a multiblock input', function () {
  173. var input, result, expected;
  174. input = stringToBytes('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno' + 'mnopnopq');
  175. result = calculateSHA256(input, 0, input.length);
  176. expected = hex2binary('248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167' + 'F6ECEDD419DB06C1');
  177. expect(result).toEqual(expected);
  178. });
  179. });
  180. describe('calculateSHA384', function () {
  181. it('should properly hash abc', function () {
  182. var input, result, expected;
  183. input = stringToBytes('abc');
  184. result = calculateSHA384(input, 0, input.length);
  185. expected = hex2binary('CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED163' + '1A8B605A43FF5BED8086072BA1E7CC2358BAECA134C825A7');
  186. expect(result).toEqual(expected);
  187. });
  188. it('should properly hash a multiblock input', function () {
  189. var input, result, expected;
  190. input = stringToBytes('abcdefghbcdefghicdefghijdefghijkefghijklfghijklm' + 'ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs' + 'mnopqrstnopqrstu');
  191. result = calculateSHA384(input, 0, input.length);
  192. expected = hex2binary('09330C33F71147E83D192FC782CD1B4753111B173B3B05D2' + '2FA08086E3B0F712FCC7C71A557E2DB966C3E9FA91746039');
  193. expect(result).toEqual(expected);
  194. });
  195. });
  196. describe('calculateSHA512', function () {
  197. it('should properly hash abc', function () {
  198. var input, result, expected;
  199. input = stringToBytes('abc');
  200. result = calculateSHA512(input, 0, input.length);
  201. expected = hex2binary('DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA2' + '0A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD' + '454D4423643CE80E2A9AC94FA54CA49F');
  202. expect(result).toEqual(expected);
  203. });
  204. it('should properly hash a multiblock input', function () {
  205. var input, result, expected;
  206. input = stringToBytes('abcdefghbcdefghicdefghijdefghijkefghijklfghijklm' + 'ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs' + 'mnopqrstnopqrstu');
  207. result = calculateSHA512(input, 0, input.length);
  208. expected = hex2binary('8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA1' + '7299AEADB6889018501D289E4900F7E4331B99DEC4B5433A' + 'C7D329EEB6DD26545E96E55B874BE909');
  209. expect(result).toEqual(expected);
  210. });
  211. });
  212. describe('AES128', function () {
  213. describe('Encryption', function () {
  214. it('should be able to encrypt a block', function () {
  215. var input, key, result, expected, iv, cipher;
  216. input = hex2binary('00112233445566778899aabbccddeeff');
  217. key = hex2binary('000102030405060708090a0b0c0d0e0f');
  218. iv = hex2binary('00000000000000000000000000000000');
  219. cipher = new AES128Cipher(key);
  220. result = cipher.encrypt(input, iv);
  221. expected = hex2binary('69c4e0d86a7b0430d8cdb78070b4c55a');
  222. expect(result).toEqual(expected);
  223. });
  224. });
  225. describe('Decryption', function () {
  226. it('should be able to decrypt a block with IV in stream', function () {
  227. var input, key, result, expected, cipher;
  228. input = hex2binary('0000000000000000000000000000000069c4e0d86a7b0430d' + '8cdb78070b4c55a');
  229. key = hex2binary('000102030405060708090a0b0c0d0e0f');
  230. cipher = new AES128Cipher(key);
  231. result = cipher.decryptBlock(input);
  232. expected = hex2binary('00112233445566778899aabbccddeeff');
  233. expect(result).toEqual(expected);
  234. });
  235. });
  236. });
  237. describe('AES256', function () {
  238. describe('Encryption', function () {
  239. it('should be able to encrypt a block', function () {
  240. var input, key, result, expected, iv, cipher;
  241. input = hex2binary('00112233445566778899aabbccddeeff');
  242. key = hex2binary('000102030405060708090a0b0c0d0e0f101112131415161718' + '191a1b1c1d1e1f');
  243. iv = hex2binary('00000000000000000000000000000000');
  244. cipher = new AES256Cipher(key);
  245. result = cipher.encrypt(input, iv);
  246. expected = hex2binary('8ea2b7ca516745bfeafc49904b496089');
  247. expect(result).toEqual(expected);
  248. });
  249. });
  250. describe('Decryption', function () {
  251. it('should be able to decrypt a block with specified iv', function () {
  252. var input, key, result, expected, cipher, iv;
  253. input = hex2binary('8ea2b7ca516745bfeafc49904b496089');
  254. key = hex2binary('000102030405060708090a0b0c0d0e0f101112131415161718' + '191a1b1c1d1e1f');
  255. iv = hex2binary('00000000000000000000000000000000');
  256. cipher = new AES256Cipher(key);
  257. result = cipher.decryptBlock(input, false, iv);
  258. expected = hex2binary('00112233445566778899aabbccddeeff');
  259. expect(result).toEqual(expected);
  260. });
  261. it('should be able to decrypt a block with IV in stream', function () {
  262. var input, key, result, expected, cipher;
  263. input = hex2binary('000000000000000000000000000000008ea2b7ca516745bf' + 'eafc49904b496089');
  264. key = hex2binary('000102030405060708090a0b0c0d0e0f101112131415161718' + '191a1b1c1d1e1f');
  265. cipher = new AES256Cipher(key);
  266. result = cipher.decryptBlock(input, false);
  267. expected = hex2binary('00112233445566778899aabbccddeeff');
  268. expect(result).toEqual(expected);
  269. });
  270. });
  271. });
  272. describe('PDF17Algorithm', function () {
  273. it('should correctly check a user key', function () {
  274. var password, userValidation, userPassword, alg, result;
  275. alg = new PDF17();
  276. password = new Uint8Array([
  277. 117,
  278. 115,
  279. 101,
  280. 114
  281. ]);
  282. userValidation = new Uint8Array([
  283. 117,
  284. 169,
  285. 4,
  286. 32,
  287. 159,
  288. 101,
  289. 22,
  290. 220
  291. ]);
  292. userPassword = new Uint8Array([
  293. 131,
  294. 242,
  295. 143,
  296. 160,
  297. 87,
  298. 2,
  299. 138,
  300. 134,
  301. 79,
  302. 253,
  303. 189,
  304. 173,
  305. 224,
  306. 73,
  307. 144,
  308. 241,
  309. 190,
  310. 81,
  311. 197,
  312. 15,
  313. 249,
  314. 105,
  315. 145,
  316. 151,
  317. 15,
  318. 194,
  319. 65,
  320. 3,
  321. 1,
  322. 126,
  323. 187,
  324. 221
  325. ]);
  326. result = alg.checkUserPassword(password, userValidation, userPassword);
  327. expect(result).toEqual(true);
  328. });
  329. it('should correctly check an owner key', function () {
  330. var password, ownerValidation, ownerPassword, alg, result, uBytes;
  331. alg = new PDF17();
  332. password = new Uint8Array([
  333. 111,
  334. 119,
  335. 110,
  336. 101,
  337. 114
  338. ]);
  339. ownerValidation = new Uint8Array([
  340. 243,
  341. 118,
  342. 71,
  343. 153,
  344. 128,
  345. 17,
  346. 101,
  347. 62
  348. ]);
  349. ownerPassword = new Uint8Array([
  350. 60,
  351. 98,
  352. 137,
  353. 35,
  354. 51,
  355. 101,
  356. 200,
  357. 152,
  358. 210,
  359. 178,
  360. 226,
  361. 228,
  362. 134,
  363. 205,
  364. 163,
  365. 24,
  366. 204,
  367. 126,
  368. 177,
  369. 36,
  370. 106,
  371. 50,
  372. 36,
  373. 125,
  374. 210,
  375. 172,
  376. 171,
  377. 120,
  378. 222,
  379. 108,
  380. 139,
  381. 115
  382. ]);
  383. uBytes = new Uint8Array([
  384. 131,
  385. 242,
  386. 143,
  387. 160,
  388. 87,
  389. 2,
  390. 138,
  391. 134,
  392. 79,
  393. 253,
  394. 189,
  395. 173,
  396. 224,
  397. 73,
  398. 144,
  399. 241,
  400. 190,
  401. 81,
  402. 197,
  403. 15,
  404. 249,
  405. 105,
  406. 145,
  407. 151,
  408. 15,
  409. 194,
  410. 65,
  411. 3,
  412. 1,
  413. 126,
  414. 187,
  415. 221,
  416. 117,
  417. 169,
  418. 4,
  419. 32,
  420. 159,
  421. 101,
  422. 22,
  423. 220,
  424. 168,
  425. 94,
  426. 215,
  427. 192,
  428. 100,
  429. 38,
  430. 188,
  431. 40
  432. ]);
  433. result = alg.checkOwnerPassword(password, ownerValidation, uBytes, ownerPassword);
  434. expect(result).toEqual(true);
  435. });
  436. it('should generate a file encryption key from the user key', function () {
  437. var password, userKeySalt, expected, alg, result, userEncryption;
  438. alg = new PDF17();
  439. password = new Uint8Array([
  440. 117,
  441. 115,
  442. 101,
  443. 114
  444. ]);
  445. userKeySalt = new Uint8Array([
  446. 168,
  447. 94,
  448. 215,
  449. 192,
  450. 100,
  451. 38,
  452. 188,
  453. 40
  454. ]);
  455. userEncryption = new Uint8Array([
  456. 35,
  457. 150,
  458. 195,
  459. 169,
  460. 245,
  461. 51,
  462. 51,
  463. 255,
  464. 158,
  465. 158,
  466. 33,
  467. 242,
  468. 231,
  469. 75,
  470. 125,
  471. 190,
  472. 25,
  473. 126,
  474. 172,
  475. 114,
  476. 195,
  477. 244,
  478. 137,
  479. 245,
  480. 234,
  481. 165,
  482. 42,
  483. 74,
  484. 60,
  485. 38,
  486. 17,
  487. 17
  488. ]);
  489. result = alg.getUserKey(password, userKeySalt, userEncryption);
  490. expected = new Uint8Array([
  491. 63,
  492. 114,
  493. 136,
  494. 209,
  495. 87,
  496. 61,
  497. 12,
  498. 30,
  499. 249,
  500. 1,
  501. 186,
  502. 144,
  503. 254,
  504. 248,
  505. 163,
  506. 153,
  507. 151,
  508. 51,
  509. 133,
  510. 10,
  511. 80,
  512. 152,
  513. 206,
  514. 15,
  515. 72,
  516. 187,
  517. 231,
  518. 33,
  519. 224,
  520. 239,
  521. 13,
  522. 213
  523. ]);
  524. expect(result).toEqual(expected);
  525. });
  526. it('should generate a file encryption key from the owner key', function () {
  527. var password, ownerKeySalt, expected, alg, result, ownerEncryption;
  528. var uBytes;
  529. alg = new PDF17();
  530. password = new Uint8Array([
  531. 111,
  532. 119,
  533. 110,
  534. 101,
  535. 114
  536. ]);
  537. ownerKeySalt = new Uint8Array([
  538. 200,
  539. 245,
  540. 242,
  541. 12,
  542. 218,
  543. 123,
  544. 24,
  545. 120
  546. ]);
  547. ownerEncryption = new Uint8Array([
  548. 213,
  549. 202,
  550. 14,
  551. 189,
  552. 110,
  553. 76,
  554. 70,
  555. 191,
  556. 6,
  557. 195,
  558. 10,
  559. 190,
  560. 157,
  561. 100,
  562. 144,
  563. 85,
  564. 8,
  565. 62,
  566. 123,
  567. 178,
  568. 156,
  569. 229,
  570. 50,
  571. 40,
  572. 229,
  573. 216,
  574. 54,
  575. 222,
  576. 34,
  577. 38,
  578. 106,
  579. 223
  580. ]);
  581. uBytes = new Uint8Array([
  582. 131,
  583. 242,
  584. 143,
  585. 160,
  586. 87,
  587. 2,
  588. 138,
  589. 134,
  590. 79,
  591. 253,
  592. 189,
  593. 173,
  594. 224,
  595. 73,
  596. 144,
  597. 241,
  598. 190,
  599. 81,
  600. 197,
  601. 15,
  602. 249,
  603. 105,
  604. 145,
  605. 151,
  606. 15,
  607. 194,
  608. 65,
  609. 3,
  610. 1,
  611. 126,
  612. 187,
  613. 221,
  614. 117,
  615. 169,
  616. 4,
  617. 32,
  618. 159,
  619. 101,
  620. 22,
  621. 220,
  622. 168,
  623. 94,
  624. 215,
  625. 192,
  626. 100,
  627. 38,
  628. 188,
  629. 40
  630. ]);
  631. result = alg.getOwnerKey(password, ownerKeySalt, uBytes, ownerEncryption);
  632. expected = new Uint8Array([
  633. 63,
  634. 114,
  635. 136,
  636. 209,
  637. 87,
  638. 61,
  639. 12,
  640. 30,
  641. 249,
  642. 1,
  643. 186,
  644. 144,
  645. 254,
  646. 248,
  647. 163,
  648. 153,
  649. 151,
  650. 51,
  651. 133,
  652. 10,
  653. 80,
  654. 152,
  655. 206,
  656. 15,
  657. 72,
  658. 187,
  659. 231,
  660. 33,
  661. 224,
  662. 239,
  663. 13,
  664. 213
  665. ]);
  666. expect(result).toEqual(expected);
  667. });
  668. });
  669. describe('PDF20Algorithm', function () {
  670. it('should correctly check a user key', function () {
  671. var password, userValidation, userPassword, alg, result;
  672. alg = new PDF20();
  673. password = new Uint8Array([
  674. 117,
  675. 115,
  676. 101,
  677. 114
  678. ]);
  679. userValidation = new Uint8Array([
  680. 83,
  681. 245,
  682. 146,
  683. 101,
  684. 198,
  685. 247,
  686. 34,
  687. 198
  688. ]);
  689. userPassword = new Uint8Array([
  690. 94,
  691. 230,
  692. 205,
  693. 75,
  694. 166,
  695. 99,
  696. 250,
  697. 76,
  698. 219,
  699. 128,
  700. 17,
  701. 85,
  702. 57,
  703. 17,
  704. 33,
  705. 164,
  706. 150,
  707. 46,
  708. 103,
  709. 176,
  710. 160,
  711. 156,
  712. 187,
  713. 233,
  714. 166,
  715. 223,
  716. 163,
  717. 253,
  718. 147,
  719. 235,
  720. 95,
  721. 184
  722. ]);
  723. result = alg.checkUserPassword(password, userValidation, userPassword);
  724. expect(result).toEqual(true);
  725. });
  726. it('should correctly check an owner key', function () {
  727. var password, ownerValidation, ownerPassword, alg, result, uBytes;
  728. alg = new PDF20();
  729. password = new Uint8Array([
  730. 111,
  731. 119,
  732. 110,
  733. 101,
  734. 114
  735. ]);
  736. ownerValidation = new Uint8Array([
  737. 142,
  738. 232,
  739. 169,
  740. 208,
  741. 202,
  742. 214,
  743. 5,
  744. 185
  745. ]);
  746. ownerPassword = new Uint8Array([
  747. 88,
  748. 232,
  749. 62,
  750. 54,
  751. 245,
  752. 26,
  753. 245,
  754. 209,
  755. 137,
  756. 123,
  757. 221,
  758. 72,
  759. 199,
  760. 49,
  761. 37,
  762. 217,
  763. 31,
  764. 74,
  765. 115,
  766. 167,
  767. 127,
  768. 158,
  769. 176,
  770. 77,
  771. 45,
  772. 163,
  773. 87,
  774. 47,
  775. 39,
  776. 90,
  777. 217,
  778. 141
  779. ]);
  780. uBytes = new Uint8Array([
  781. 94,
  782. 230,
  783. 205,
  784. 75,
  785. 166,
  786. 99,
  787. 250,
  788. 76,
  789. 219,
  790. 128,
  791. 17,
  792. 85,
  793. 57,
  794. 17,
  795. 33,
  796. 164,
  797. 150,
  798. 46,
  799. 103,
  800. 176,
  801. 160,
  802. 156,
  803. 187,
  804. 233,
  805. 166,
  806. 223,
  807. 163,
  808. 253,
  809. 147,
  810. 235,
  811. 95,
  812. 184,
  813. 83,
  814. 245,
  815. 146,
  816. 101,
  817. 198,
  818. 247,
  819. 34,
  820. 198,
  821. 191,
  822. 11,
  823. 16,
  824. 94,
  825. 237,
  826. 216,
  827. 20,
  828. 175
  829. ]);
  830. result = alg.checkOwnerPassword(password, ownerValidation, uBytes, ownerPassword);
  831. expect(result).toEqual(true);
  832. });
  833. it('should generate a file encryption key from the user key', function () {
  834. var password, userKeySalt, expected, alg, result, userEncryption;
  835. alg = new PDF20();
  836. password = new Uint8Array([
  837. 117,
  838. 115,
  839. 101,
  840. 114
  841. ]);
  842. userKeySalt = new Uint8Array([
  843. 191,
  844. 11,
  845. 16,
  846. 94,
  847. 237,
  848. 216,
  849. 20,
  850. 175
  851. ]);
  852. userEncryption = new Uint8Array([
  853. 121,
  854. 208,
  855. 2,
  856. 181,
  857. 230,
  858. 89,
  859. 156,
  860. 60,
  861. 253,
  862. 143,
  863. 212,
  864. 28,
  865. 84,
  866. 180,
  867. 196,
  868. 177,
  869. 173,
  870. 128,
  871. 221,
  872. 107,
  873. 46,
  874. 20,
  875. 94,
  876. 186,
  877. 135,
  878. 51,
  879. 95,
  880. 24,
  881. 20,
  882. 223,
  883. 254,
  884. 36
  885. ]);
  886. result = alg.getUserKey(password, userKeySalt, userEncryption);
  887. expected = new Uint8Array([
  888. 42,
  889. 218,
  890. 213,
  891. 39,
  892. 73,
  893. 91,
  894. 72,
  895. 79,
  896. 67,
  897. 38,
  898. 248,
  899. 133,
  900. 18,
  901. 189,
  902. 61,
  903. 34,
  904. 107,
  905. 79,
  906. 29,
  907. 56,
  908. 59,
  909. 181,
  910. 213,
  911. 118,
  912. 113,
  913. 34,
  914. 65,
  915. 210,
  916. 87,
  917. 174,
  918. 22,
  919. 239
  920. ]);
  921. expect(result).toEqual(expected);
  922. });
  923. it('should generate a file encryption key from the owner key', function () {
  924. var password, ownerKeySalt, expected, alg, result, ownerEncryption;
  925. var uBytes;
  926. alg = new PDF20();
  927. password = new Uint8Array([
  928. 111,
  929. 119,
  930. 110,
  931. 101,
  932. 114
  933. ]);
  934. ownerKeySalt = new Uint8Array([
  935. 29,
  936. 208,
  937. 185,
  938. 46,
  939. 11,
  940. 76,
  941. 135,
  942. 149
  943. ]);
  944. ownerEncryption = new Uint8Array([
  945. 209,
  946. 73,
  947. 224,
  948. 77,
  949. 103,
  950. 155,
  951. 201,
  952. 181,
  953. 190,
  954. 68,
  955. 223,
  956. 20,
  957. 62,
  958. 90,
  959. 56,
  960. 210,
  961. 5,
  962. 240,
  963. 178,
  964. 128,
  965. 238,
  966. 124,
  967. 68,
  968. 254,
  969. 253,
  970. 244,
  971. 62,
  972. 108,
  973. 208,
  974. 135,
  975. 10,
  976. 251
  977. ]);
  978. uBytes = new Uint8Array([
  979. 94,
  980. 230,
  981. 205,
  982. 75,
  983. 166,
  984. 99,
  985. 250,
  986. 76,
  987. 219,
  988. 128,
  989. 17,
  990. 85,
  991. 57,
  992. 17,
  993. 33,
  994. 164,
  995. 150,
  996. 46,
  997. 103,
  998. 176,
  999. 160,
  1000. 156,
  1001. 187,
  1002. 233,
  1003. 166,
  1004. 223,
  1005. 163,
  1006. 253,
  1007. 147,
  1008. 235,
  1009. 95,
  1010. 184,
  1011. 83,
  1012. 245,
  1013. 146,
  1014. 101,
  1015. 198,
  1016. 247,
  1017. 34,
  1018. 198,
  1019. 191,
  1020. 11,
  1021. 16,
  1022. 94,
  1023. 237,
  1024. 216,
  1025. 20,
  1026. 175
  1027. ]);
  1028. result = alg.getOwnerKey(password, ownerKeySalt, uBytes, ownerEncryption);
  1029. expected = new Uint8Array([
  1030. 42,
  1031. 218,
  1032. 213,
  1033. 39,
  1034. 73,
  1035. 91,
  1036. 72,
  1037. 79,
  1038. 67,
  1039. 38,
  1040. 248,
  1041. 133,
  1042. 18,
  1043. 189,
  1044. 61,
  1045. 34,
  1046. 107,
  1047. 79,
  1048. 29,
  1049. 56,
  1050. 59,
  1051. 181,
  1052. 213,
  1053. 118,
  1054. 113,
  1055. 34,
  1056. 65,
  1057. 210,
  1058. 87,
  1059. 174,
  1060. 22,
  1061. 239
  1062. ]);
  1063. expect(result).toEqual(expected);
  1064. });
  1065. });
  1066. });
  1067. describe('CipherTransformFactory', function () {
  1068. function buildDict(map) {
  1069. var dict = new Dict();
  1070. for (var key in map) {
  1071. dict.set(key, map[key]);
  1072. }
  1073. return dict;
  1074. }
  1075. function ensurePasswordCorrect(done, dict, fileId, password) {
  1076. try {
  1077. var factory = new CipherTransformFactory(dict, fileId, password);
  1078. expect('createCipherTransform' in factory).toEqual(true);
  1079. } catch (ex) {
  1080. done.fail('Password should be accepted: ' + ex);
  1081. return;
  1082. }
  1083. done();
  1084. }
  1085. function ensurePasswordNeeded(done, dict, fileId, password) {
  1086. try {
  1087. new CipherTransformFactory(dict, fileId, password);
  1088. } catch (ex) {
  1089. expect(ex instanceof PasswordException).toEqual(true);
  1090. expect(ex.code).toEqual(PasswordResponses.NEED_PASSWORD);
  1091. done();
  1092. return;
  1093. }
  1094. done.fail('Password should be rejected.');
  1095. }
  1096. function ensurePasswordIncorrect(done, dict, fileId, password) {
  1097. try {
  1098. new CipherTransformFactory(dict, fileId, password);
  1099. } catch (ex) {
  1100. expect(ex instanceof PasswordException).toEqual(true);
  1101. expect(ex.code).toEqual(PasswordResponses.INCORRECT_PASSWORD);
  1102. done();
  1103. return;
  1104. }
  1105. done.fail('Password should be rejected.');
  1106. }
  1107. var fileId1, fileId2, dict1, dict2;
  1108. var aes256Dict, aes256IsoDict, aes256BlankDict, aes256IsoBlankDict;
  1109. beforeAll(function (done) {
  1110. fileId1 = unescape('%F6%C6%AF%17%F3rR%8DRM%9A%80%D1%EF%DF%18');
  1111. fileId2 = unescape('%3CL_%3AD%96%AF@%9A%9D%B3%3Cx%1Cv%AC');
  1112. dict1 = buildDict({
  1113. Filter: Name.get('Standard'),
  1114. V: 2,
  1115. Length: 128,
  1116. O: unescape('%80%C3%04%96%91o%20sl%3A%E6%1B%13T%91%F2%0DV%12%E3%FF%5E%B' + 'B%E9VO%D8k%9A%CA%7C%5D'),
  1117. U: unescape('j%0C%8D%3EY%19%00%BCjd%7D%91%BD%AA%00%18%00%00%00%00%00%00' + '%00%00%00%00%00%00%00%00%00%00'),
  1118. P: -1028,
  1119. R: 3
  1120. });
  1121. dict2 = buildDict({
  1122. Filter: Name.get('Standard'),
  1123. V: 4,
  1124. Length: 128,
  1125. O: unescape('sF%14v.y5%27%DB%97%0A5%22%B3%E1%D4%AD%BD%9B%3C%B4%A5%89u%1' + '5%B2Y%F1h%D9%E9%F4'),
  1126. U: unescape('%93%04%89%A9%BF%8AE%A6%88%A2%DB%C2%A0%A8gn%00%00%00%00%00%' + '00%00%00%00%00%00%00%00%00%00%00'),
  1127. P: -1084,
  1128. R: 4
  1129. });
  1130. aes256Dict = buildDict({
  1131. Filter: Name.get('Standard'),
  1132. V: 5,
  1133. Length: 256,
  1134. O: unescape('%3Cb%89%233e%C8%98%D2%B2%E2%E4%86%CD%A3%18%CC%7E%B1%24j2%2' + '4%7D%D2%AC%ABx%DEl%8Bs%F3vG%99%80%11e%3E%C8%F5%F2%0C%DA%7B' + '%18x'),
  1135. U: unescape('%83%F2%8F%A0W%02%8A%86O%FD%BD%AD%E0I%90%F1%BEQ%C5%0F%F9i%9' + '1%97%0F%C2A%03%01%7E%BB%DDu%A9%04%20%9Fe%16%DC%A8%5E%D7%C0' + 'd%26%BC%28'),
  1136. OE: unescape('%D5%CA%0E%BDnLF%BF%06%C3%0A%BE%9Dd%90U%08%3E%7B%B2%9C%E52' + '%28%E5%D86%DE%22%26j%DF'),
  1137. UE: unescape('%23%96%C3%A9%F533%FF%9E%9E%21%F2%E7K%7D%BE%19%7E%ACr%C3%F' + '4%89%F5%EA%A5*J%3C%26%11%11'),
  1138. Perms: unescape('%D8%FC%844%E5e%0DB%5D%7Ff%FD%3COMM'),
  1139. P: -1084,
  1140. R: 5
  1141. });
  1142. aes256IsoDict = buildDict({
  1143. Filter: Name.get('Standard'),
  1144. V: 5,
  1145. Length: 256,
  1146. O: unescape('X%E8%3E6%F5%1A%F5%D1%89%7B%DDH%C71%25%D9%1FJs%A7%7F%9E%B0M' + '-%A3W/%27Z%D9%8D%8E%E8%A9%D0%CA%D6%05%B9%1D%D0%B9.%0BL%87%' + '95'),
  1147. U: unescape('%5E%E6%CDK%A6c%FAL%DB%80%11U9%11%21%A4%96.g%B0%A0%9C%BB%E9' + '%A6%DF%A3%FD%93%EB_%B8S%F5%92e%C6%F7%22%C6%BF%0B%10%5E%ED%' + 'D8%14%AF'),
  1148. OE: unescape('%D1I%E0Mg%9B%C9%B5%BED%DF%14%3EZ8%D2%05%F0%B2%80%EE%7CD%F' + 'E%FD%F4%3El%D0%87%0A%FB'),
  1149. UE: unescape('y%D0%02%B5%E6Y%9C%3C%FD%8F%D4%1CT%B4%C4%B1%AD%80%DDk.%14%' + '5E%BA%873_%18%14%DF%FE%24'),
  1150. Perms: unescape('l%AD%0F%A0%EBM%86WM%3E%CB%B5%E0X%C97'),
  1151. P: -1084,
  1152. R: 6
  1153. });
  1154. aes256BlankDict = buildDict({
  1155. Filter: Name.get('Standard'),
  1156. V: 5,
  1157. Length: 256,
  1158. O: unescape('%B8p%04%C3g%26%FCW%CCN%D4%16%A1%E8%950YZ%C9%9E%B1-%97%F3%F' + 'E%03%13%19ffZn%8F%F5%EB%EC%CC5sV%10e%CEl%B5%E9G%C1'),
  1159. U: unescape('%83%D4zi%F1O0%961%12%CC%82%CB%CA%BF5y%FD%21%EB%E4%D1%B5%1D' + '%D6%FA%14%F3%BE%8Fqs%EF%88%DE%E2%E8%DC%F55%E4%B8%16%C8%14%' + '8De%1E'),
  1160. OE: unescape('%8F%19%E8%D4%27%D5%07%CA%C6%A1%11%A6a%5Bt%F4%DF%0F%84%29%' + '0F%E4%EFF7%5B%5B%11%A0%8F%17e'),
  1161. UE: unescape('%81%F5%5D%B0%28%81%E4%7F_%7C%8F%85b%A0%7E%10%D0%88lx%7B%7' + 'EJ%5E%912%B6d%12%27%05%F6'),
  1162. Perms: unescape('%86%1562%0D%AE%A2%FB%5D%3B%22%3Dq%12%B2H'),
  1163. P: -1084,
  1164. R: 5
  1165. });
  1166. aes256IsoBlankDict = buildDict({
  1167. Filter: Name.get('Standard'),
  1168. V: 5,
  1169. Length: 256,
  1170. O: unescape('%F7%DB%99U%A6M%ACk%AF%CF%D7AFw%E9%C1%91%CBDgI%23R%CF%0C%15' + 'r%D74%0D%CE%E9%91@%E4%98QF%BF%88%7Ej%DE%AD%8F%F4@%C1'),
  1171. U: unescape('%1A%A9%DC%918%83%93k%29%5B%117%B16%DB%E8%8E%FE%28%E5%89%D4' + '%0E%AD%12%3B%7DN_6fez%8BG%18%05YOh%7DZH%A3Z%87%17*'),
  1172. OE: unescape('%A4a%88%20h%1B%7F%CD%D5%CAc%D8R%83%E5%D6%1C%D2%98%07%984%' + 'BA%AF%1B%B4%7FQ%F8%1EU%7D'),
  1173. UE: unescape('%A0%0AZU%27%1D%27%2C%0B%FE%0E%A2L%F9b%5E%A1%B9%D6v7b%B26%' + 'A9N%99%F1%A4Deq'),
  1174. Perms: unescape('%03%F2i%07%0D%C3%F9%F2%28%80%B7%F5%DD%D1c%EB'),
  1175. P: -1084,
  1176. R: 6
  1177. });
  1178. done();
  1179. });
  1180. afterAll(function () {
  1181. fileId1 = fileId2 = dict1 = dict2 = null;
  1182. aes256Dict = aes256IsoDict = aes256BlankDict = aes256IsoBlankDict = null;
  1183. });
  1184. describe('#ctor', function () {
  1185. describe('AES256 Revision 5', function () {
  1186. it('should accept user password', function (done) {
  1187. ensurePasswordCorrect(done, aes256Dict, fileId1, 'user');
  1188. });
  1189. it('should accept owner password', function (done) {
  1190. ensurePasswordCorrect(done, aes256Dict, fileId1, 'owner');
  1191. });
  1192. it('should not accept blank password', function (done) {
  1193. ensurePasswordNeeded(done, aes256Dict, fileId1);
  1194. });
  1195. it('should not accept wrong password', function (done) {
  1196. ensurePasswordIncorrect(done, aes256Dict, fileId1, 'wrong');
  1197. });
  1198. it('should accept blank password', function (done) {
  1199. ensurePasswordCorrect(done, aes256BlankDict, fileId1);
  1200. });
  1201. });
  1202. describe('AES256 Revision 6', function () {
  1203. it('should accept user password', function (done) {
  1204. ensurePasswordCorrect(done, aes256IsoDict, fileId1, 'user');
  1205. });
  1206. it('should accept owner password', function (done) {
  1207. ensurePasswordCorrect(done, aes256IsoDict, fileId1, 'owner');
  1208. });
  1209. it('should not accept blank password', function (done) {
  1210. ensurePasswordNeeded(done, aes256IsoDict, fileId1);
  1211. });
  1212. it('should not accept wrong password', function (done) {
  1213. ensurePasswordIncorrect(done, aes256IsoDict, fileId1, 'wrong');
  1214. });
  1215. it('should accept blank password', function (done) {
  1216. ensurePasswordCorrect(done, aes256IsoBlankDict, fileId1);
  1217. });
  1218. });
  1219. it('should accept user password', function (done) {
  1220. ensurePasswordCorrect(done, dict1, fileId1, '123456');
  1221. });
  1222. it('should accept owner password', function (done) {
  1223. ensurePasswordCorrect(done, dict1, fileId1, '654321');
  1224. });
  1225. it('should not accept blank password', function (done) {
  1226. ensurePasswordNeeded(done, dict1, fileId1);
  1227. });
  1228. it('should not accept wrong password', function (done) {
  1229. ensurePasswordIncorrect(done, dict1, fileId1, 'wrong');
  1230. });
  1231. it('should accept blank password', function (done) {
  1232. ensurePasswordCorrect(done, dict2, fileId2);
  1233. });
  1234. });
  1235. });