crypt.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright 2008 The Closure Library Authors. All Rights Reserved.
  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. * @fileoverview Namespace with crypto related helper functions.
  16. */
  17. goog.provide('goog.crypt');
  18. goog.require('goog.array');
  19. goog.require('goog.asserts');
  20. /**
  21. * Turns a string into an array of bytes; a "byte" being a JS number in the
  22. * range 0-255. Multi-byte characters are written as little-endian.
  23. * @param {string} str String value to arrify.
  24. * @return {!Array<number>} Array of numbers corresponding to the
  25. * UCS character codes of each character in str.
  26. */
  27. goog.crypt.stringToByteArray = function(str) {
  28. var output = [], p = 0;
  29. for (var i = 0; i < str.length; i++) {
  30. var c = str.charCodeAt(i);
  31. // NOTE: c <= 0xffff since JavaScript strings are UTF-16.
  32. if (c > 0xff) {
  33. output[p++] = c & 0xff;
  34. c >>= 8;
  35. }
  36. output[p++] = c;
  37. }
  38. return output;
  39. };
  40. /**
  41. * Turns an array of numbers into the string given by the concatenation of the
  42. * characters to which the numbers correspond.
  43. * @param {!Uint8Array|!Array<number>} bytes Array of numbers representing
  44. * characters.
  45. * @return {string} Stringification of the array.
  46. */
  47. goog.crypt.byteArrayToString = function(bytes) {
  48. var CHUNK_SIZE = 8192;
  49. // Special-case the simple case for speed's sake.
  50. if (bytes.length <= CHUNK_SIZE) {
  51. return String.fromCharCode.apply(null, bytes);
  52. }
  53. // The remaining logic splits conversion by chunks since
  54. // Function#apply() has a maximum parameter count.
  55. // See discussion: http://goo.gl/LrWmZ9
  56. var str = '';
  57. for (var i = 0; i < bytes.length; i += CHUNK_SIZE) {
  58. var chunk = goog.array.slice(bytes, i, i + CHUNK_SIZE);
  59. str += String.fromCharCode.apply(null, chunk);
  60. }
  61. return str;
  62. };
  63. /**
  64. * Turns an array of numbers into the hex string given by the concatenation of
  65. * the hex values to which the numbers correspond.
  66. * @param {Uint8Array|Array<number>} array Array of numbers representing
  67. * characters.
  68. * @return {string} Hex string.
  69. */
  70. goog.crypt.byteArrayToHex = function(array) {
  71. return goog.array
  72. .map(
  73. array,
  74. function(numByte) {
  75. var hexByte = numByte.toString(16);
  76. return hexByte.length > 1 ? hexByte : '0' + hexByte;
  77. })
  78. .join('');
  79. };
  80. /**
  81. * Converts a hex string into an integer array.
  82. * @param {string} hexString Hex string of 16-bit integers (two characters
  83. * per integer).
  84. * @return {!Array<number>} Array of {0,255} integers for the given string.
  85. */
  86. goog.crypt.hexToByteArray = function(hexString) {
  87. goog.asserts.assert(
  88. hexString.length % 2 == 0, 'Key string length must be multiple of 2');
  89. var arr = [];
  90. for (var i = 0; i < hexString.length; i += 2) {
  91. arr.push(parseInt(hexString.substring(i, i + 2), 16));
  92. }
  93. return arr;
  94. };
  95. /**
  96. * Converts a JS string to a UTF-8 "byte" array.
  97. * @param {string} str 16-bit unicode string.
  98. * @return {!Array<number>} UTF-8 byte array.
  99. */
  100. goog.crypt.stringToUtf8ByteArray = function(str) {
  101. // TODO(user): Use native implementations if/when available
  102. var out = [], p = 0;
  103. for (var i = 0; i < str.length; i++) {
  104. var c = str.charCodeAt(i);
  105. if (c < 128) {
  106. out[p++] = c;
  107. } else if (c < 2048) {
  108. out[p++] = (c >> 6) | 192;
  109. out[p++] = (c & 63) | 128;
  110. } else if (
  111. ((c & 0xFC00) == 0xD800) && (i + 1) < str.length &&
  112. ((str.charCodeAt(i + 1) & 0xFC00) == 0xDC00)) {
  113. // Surrogate Pair
  114. c = 0x10000 + ((c & 0x03FF) << 10) + (str.charCodeAt(++i) & 0x03FF);
  115. out[p++] = (c >> 18) | 240;
  116. out[p++] = ((c >> 12) & 63) | 128;
  117. out[p++] = ((c >> 6) & 63) | 128;
  118. out[p++] = (c & 63) | 128;
  119. } else {
  120. out[p++] = (c >> 12) | 224;
  121. out[p++] = ((c >> 6) & 63) | 128;
  122. out[p++] = (c & 63) | 128;
  123. }
  124. }
  125. return out;
  126. };
  127. /**
  128. * Converts a UTF-8 byte array to JavaScript's 16-bit Unicode.
  129. * @param {Uint8Array|Array<number>} bytes UTF-8 byte array.
  130. * @return {string} 16-bit Unicode string.
  131. */
  132. goog.crypt.utf8ByteArrayToString = function(bytes) {
  133. // TODO(user): Use native implementations if/when available
  134. var out = [], pos = 0, c = 0;
  135. while (pos < bytes.length) {
  136. var c1 = bytes[pos++];
  137. if (c1 < 128) {
  138. out[c++] = String.fromCharCode(c1);
  139. } else if (c1 > 191 && c1 < 224) {
  140. var c2 = bytes[pos++];
  141. out[c++] = String.fromCharCode((c1 & 31) << 6 | c2 & 63);
  142. } else if (c1 > 239 && c1 < 365) {
  143. // Surrogate Pair
  144. var c2 = bytes[pos++];
  145. var c3 = bytes[pos++];
  146. var c4 = bytes[pos++];
  147. var u = ((c1 & 7) << 18 | (c2 & 63) << 12 | (c3 & 63) << 6 | c4 & 63) -
  148. 0x10000;
  149. out[c++] = String.fromCharCode(0xD800 + (u >> 10));
  150. out[c++] = String.fromCharCode(0xDC00 + (u & 1023));
  151. } else {
  152. var c2 = bytes[pos++];
  153. var c3 = bytes[pos++];
  154. out[c++] =
  155. String.fromCharCode((c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
  156. }
  157. }
  158. return out.join('');
  159. };
  160. /**
  161. * XOR two byte arrays.
  162. * @param {!Uint8Array|!Int8Array|!Array<number>} bytes1 Byte array 1.
  163. * @param {!Uint8Array|!Int8Array|!Array<number>} bytes2 Byte array 2.
  164. * @return {!Array<number>} Resulting XOR of the two byte arrays.
  165. */
  166. goog.crypt.xorByteArray = function(bytes1, bytes2) {
  167. goog.asserts.assert(
  168. bytes1.length == bytes2.length, 'XOR array lengths must match');
  169. var result = [];
  170. for (var i = 0; i < bytes1.length; i++) {
  171. result.push(bytes1[i] ^ bytes2[i]);
  172. }
  173. return result;
  174. };