decode.ts 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /* tslint:disable:no-bitwise false */
  2. 'use strict';
  3. export = main;
  4. import crypto = require('crypto');
  5. import bigInt = require('big-integer');
  6. import zlib = require('zlib');
  7. /**
  8. * Decodes the data.
  9. */
  10. function main(id: number, iv: Buffer|string, data: Buffer|string, done: (err?: Error, result?: Buffer) => void) {
  11. try {
  12. decompress(decrypt(id, iv, data), done);
  13. } catch (e) {
  14. done(e);
  15. }
  16. }
  17. /**
  18. * Decrypts the data.
  19. */
  20. function decrypt(id: number, iv: Buffer|string, data: Buffer|string) {
  21. var ivBuffer = typeof iv === 'string' ? new Buffer(iv, 'base64') : iv;
  22. var dataBuffer = typeof data === 'string' ? new Buffer(data, 'base64') : data;
  23. var decipher = crypto.createDecipheriv('aes-256-cbc', key(id), ivBuffer);
  24. decipher.setAutoPadding(false);
  25. return Buffer.concat([decipher.update(dataBuffer), decipher.final()]);
  26. }
  27. /**
  28. * Decompresses the data.
  29. */
  30. function decompress(data: Buffer, done: (err: Error, result?: Buffer) => void) {
  31. try {
  32. zlib.inflate(data, done);
  33. } catch (e) {
  34. done(null, data);
  35. }
  36. }
  37. /**
  38. * Generates a key.
  39. */
  40. function key(subtitleId: number): Buffer {
  41. var hash = secret(20, 97, 1, 2) + magic(subtitleId);
  42. var result = new Buffer(32);
  43. result.fill(0);
  44. crypto.createHash('sha1').update(hash).digest().copy(result);
  45. return result;
  46. }
  47. /**
  48. * Generates a magic number.
  49. */
  50. function magic(subtitleId: number): number {
  51. var base = Math.floor(Math.sqrt(6.9) * Math.pow(2, 25));
  52. var hash = bigInt(base).xor(subtitleId).toJSNumber();
  53. var multipliedHash = bigInt(hash).multiply(32).toJSNumber();
  54. return bigInt(hash).xor(hash >> 3).xor(multipliedHash).toJSNumber();
  55. }
  56. /**
  57. * Generates a secret string based on a Fibonacci sequence.
  58. */
  59. function secret(size: number, modulo: number, firstSeed: number, secondSeed: number): string {
  60. var currentValue = firstSeed + secondSeed;
  61. var previousValue = secondSeed;
  62. var result = '';
  63. for (var i = 0; i < size; i += 1) {
  64. var oldValue = currentValue;
  65. result += String.fromCharCode(currentValue % modulo + 33);
  66. currentValue += previousValue;
  67. previousValue = oldValue;
  68. }
  69. return result;
  70. }