CryptUtils.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import { inject, injectable } from 'inversify';
  2. import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
  3. import { ICryptUtils } from '../interfaces/utils/ICryptUtils';
  4. import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
  5. import { RandomGenerator } from './RandomGenerator';
  6. import { Utils } from './Utils';
  7. @injectable()
  8. export class CryptUtils implements ICryptUtils {
  9. /**
  10. * @type {IRandomGenerator}
  11. */
  12. private readonly randomGenerator: IRandomGenerator;
  13. /**
  14. * @param {IRandomGenerator} randomGenerator
  15. */
  16. public constructor (
  17. @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator
  18. ) {
  19. this.randomGenerator = randomGenerator;
  20. }
  21. /**
  22. * @param {string} string
  23. * @returns {string}
  24. */
  25. public btoa (string: string): string {
  26. const chars: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
  27. let output: string = '';
  28. string = encodeURIComponent(string).replace(/%([0-9A-F]{2})/g, (match: string, p1: string) => {
  29. return String.fromCharCode(parseInt(`${Utils.hexadecimalPrefix}${p1}`, 16));
  30. });
  31. for (
  32. let block: number | undefined, charCode: number, idx: number = 0, map: string = chars;
  33. string.charAt(idx | 0) || (map = '=', idx % 1);
  34. output += map.charAt(63 & block >> 8 - idx % 1 * 8)
  35. ) {
  36. charCode = string.charCodeAt(idx += 3/4);
  37. if (charCode > 0xFF) {
  38. throw new Error('\'btoa\' failed: The string to be encoded contains characters outside of the Latin1 range.');
  39. }
  40. block = <number>block << 8 | charCode;
  41. }
  42. return output;
  43. }
  44. /**
  45. * Hides string inside a other random string with larger length
  46. *
  47. * @param {string} str
  48. * @param {number} length
  49. * @returns {[string , string]}
  50. */
  51. public hideString (str: string, length: number): [string, string] {
  52. const escapeRegExp: (s: string) => string = (s: string) =>
  53. s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
  54. const randomMerge: (s1: string, s2: string) => string = (s1: string, s2: string): string => {
  55. let i1: number = -1;
  56. let i2: number = -1;
  57. let result: string = '';
  58. while (i1 < s1.length || i2 < s2.length) {
  59. if (this.randomGenerator.getMathRandom() < 0.5 && i2 < s2.length) {
  60. result += s2.charAt(++i2);
  61. } else {
  62. result += s1.charAt(++i1);
  63. }
  64. }
  65. return result;
  66. };
  67. const randomString: string = this.randomGenerator.getRandomGenerator().string({
  68. length: length,
  69. pool: RandomGenerator.randomGeneratorPool
  70. });
  71. let randomStringDiff: string = randomString.replace(
  72. new RegExp(`[${escapeRegExp(str)}]`, 'g'),
  73. ''
  74. );
  75. const randomStringDiffArray: string[] = randomStringDiff.split('');
  76. this.randomGenerator.getRandomGenerator().shuffle(randomStringDiffArray);
  77. randomStringDiff = randomStringDiffArray.join('');
  78. return [randomMerge(str, randomStringDiff), randomStringDiff];
  79. }
  80. /**
  81. * RC4 symmetric cipher encryption/decryption
  82. * https://gist.github.com/farhadi/2185197
  83. *
  84. * @param {string} string
  85. * @param {string} key
  86. * @returns {string}
  87. */
  88. public rc4 (string: string, key: string): string {
  89. const s: number[] = [];
  90. let j: number = 0;
  91. let x: number;
  92. let result: string = '';
  93. // eslint-disable-next-line no-var
  94. for (var i = 0; i < 256; i++) {
  95. s[i] = i;
  96. }
  97. for (i = 0; i < 256; i++) {
  98. j = (j + s[i] + key.charCodeAt(i % key.length)) % 256;
  99. x = s[i];
  100. s[i] = s[j];
  101. s[j] = x;
  102. }
  103. i = 0;
  104. j = 0;
  105. for (let y = 0; y < string.length; y++) {
  106. i = (i + 1) % 256;
  107. j = (j + s[i]) % 256;
  108. x = s[i];
  109. s[i] = s[j];
  110. s[j] = x;
  111. result += String.fromCharCode(string.charCodeAt(y) ^ s[(s[i] + s[j]) % 256]);
  112. }
  113. return result;
  114. }
  115. }