UNPKG

9.47 kBJavaScriptView Raw
1(function() {
2 var BLOCKSIZE, Crypto, nodeCrypto, sjcl;
3
4 nodeCrypto = require('crypto');
5
6 sjcl = require('../libs/sjcl');
7
8 BLOCKSIZE = 16;
9
10 /**
11 * @class Crypto
12 */
13
14
15 Crypto = {
16 /**
17 * Encipher data
18 * @param {String} mode The type of encryption to use.
19 * @param {Buffer} plaintext The data to encrypt.
20 * @param {String|Buffer} key The key to encrypt with. Can be a Buffer or
21 * hex encoded string.
22 * @param {String|Buffer} iv The IV. Can be a Buffer or hex encoded string.
23 * @param {string} [encoding=Buffer] The format to return the encrypted
24 * data at.
25 * @return {Buffer|String} The encrypted data.
26 */
27
28 encrypt: function(mode, plaintext, key, iv, encoding) {
29 var binary, buffer, cipher;
30 iv = this.toBuffer(iv);
31 key = this.toBuffer(key);
32 cipher = nodeCrypto.createCipheriv(mode, key, iv);
33 cipher.setAutoPadding(false);
34 binary = cipher.update(plaintext) + cipher.final();
35 buffer = new Buffer(binary, 'binary');
36 if (encoding != null) {
37 return buffer.toString(encoding);
38 } else {
39 return buffer;
40 }
41 },
42 /**
43 * Decipher encrypted data.
44 * @param {String} mode The type of encryption to use.
45 * @param {String|Buffer} ciphertext The data to decipher. Must be a
46 * multiple of the blocksize.
47 * @param {String|Buffer} key The key to decipher the data with.
48 * @param {String|Buffer} iv The initialization vector to use.
49 * @param {String} [encoding=Buffer] The format to return the decrypted
50 * contents as.
51 * @return {Buffer|String} The decrypted contents.
52 */
53
54 decrypt: function(mode, ciphertext, key, iv, encoding) {
55 var binary, buffer, cipher;
56 iv = this.toBuffer(iv);
57 key = this.toBuffer(key);
58 ciphertext = this.toBuffer(ciphertext);
59 cipher = nodeCrypto.createDecipheriv(mode, key, iv);
60 cipher.setAutoPadding(false);
61 binary = cipher.update(ciphertext) + cipher.final();
62 buffer = new Buffer(binary, 'binary');
63 if (encoding != null) {
64 return buffer.toString(encoding);
65 } else {
66 return buffer;
67 }
68 },
69 /**
70 * Generate keys from password using PKDF2-HMAC-SHA512.
71 * @param {String} password The password.
72 * @param {String|Buffer} salt The salt.
73 * @param {Number} [iterations=10000] The numbers of iterations.
74 * @param {Numbers} [keysize=512] The length of the derived key in bits.
75 * @return {String} Returns the derived key encoded as hex.
76 */
77
78 pbkdf2: function(password, salt, iterations, keysize) {
79 var bits, hmac, shaKey;
80 if (iterations == null) {
81 iterations = 10000;
82 }
83 if (keysize == null) {
84 keysize = 512;
85 }
86 shaKey = "sha" + keysize;
87 hmac = (function() {
88
89 function hmac(key) {
90 this.key = sjcl.codec.utf8String.fromBits(key);
91 }
92
93 hmac.prototype.encrypt = function(sjclArray) {
94 var bits, buffer, byteArray, hex;
95 byteArray = sjcl.codec.bytes.fromBits(sjclArray);
96 buffer = new Buffer(byteArray);
97 hex = nodeCrypto.createHmac(shaKey, this.key).update(buffer).digest('hex');
98 bits = sjcl.codec.hex.toBits(hex);
99 return bits;
100 };
101
102 return hmac;
103
104 })();
105 salt = sjcl.codec.hex.toBits(this.toHex(salt));
106 bits = sjcl.misc.pbkdf2(password, salt, iterations, keysize, hmac);
107 return sjcl.codec.hex.fromBits(bits);
108 },
109 /**
110 * Cryptographically hash data using HMAC.
111 * @param {String|Buffer} data The data to be hashed.
112 * @param {String|Buffer} key The key to use with HMAC.
113 * @param {string} mode The type of hash to use, such as sha1, sha256 or
114 * sha512.
115 * @return {String} The hmac digest encoded as hex.
116 */
117
118 hmac: function(data, key, keysize) {
119 var hmac, mode;
120 data = this.toBuffer(data);
121 key = this.toBuffer(key);
122 mode = "sha" + keysize;
123 hmac = nodeCrypto.createHmac(mode, key);
124 hmac.update(data);
125 return hmac.digest('hex');
126 },
127 /**
128 * Create a hash digest of data.
129 * @param {String|Buffer} data The data to hash.
130 * @param {String} mode The type of hash to use, such as sha1, sha256, or
131 * sha512.
132 * @return {String} The hash digest encoded as hex.
133 */
134
135 hash: function(data, keysize) {
136 var hash, mode;
137 data = this.toBuffer(data);
138 mode = "sha" + keysize;
139 hash = nodeCrypto.createHash(mode);
140 hash.update(data);
141 return hash.digest('hex');
142 },
143 /**
144 * Prepend padding to data to make it fill the blocksize.
145 * @param {Buffer} data The data to pad.
146 * @return {Buffer} The data with padding added.
147 */
148
149 pad: function(data) {
150 var bytesToPad, padding;
151 bytesToPad = BLOCKSIZE - (data.length % BLOCKSIZE);
152 padding = this.randomBytes(bytesToPad);
153 return Buffer.concat([padding, data]);
154 },
155 /**
156 * Remove padding from text.
157 * @param {Numbers} plaintextLength The length of the plaintext in bytes.
158 * @param {String|Buffer} data The data to remove the padding as a string
159 * encoded as hex or a buffer.
160 * @return {String} The data with the padding removed encoded as hex.
161 */
162
163 unpad: function(plaintextLength, data) {
164 data = this.toHex(data);
165 plaintextLength *= 2;
166 return data.slice(-plaintextLength);
167 },
168 /**
169 * Generates cryptographically strong pseudo-random data.
170 * @param {Numbers} length How many bytes of data you want.
171 * @return {Buffer} The random data as a Buffer.
172 */
173
174 randomBytes: function(length) {
175 return nodeCrypto.randomBytes(length);
176 },
177 /**
178 * Convert data to a Buffer
179 * @param {String|Buffer} data The data to be converted. If a string, must
180 * be encoded as hex.
181 * @param {String} [encoding=hex] The format of the data to convert.
182 * @return {Buffer} The data as a Buffer
183 */
184
185 toBuffer: function(data, encoding) {
186 if (encoding == null) {
187 encoding = 'hex';
188 }
189 if (data instanceof Buffer) {
190 return data;
191 }
192 return new Buffer(data, encoding);
193 },
194 /**
195 * Convert data to hex.
196 * @param {String|Buffer} data The data to be converted.
197 * @return {String} The data encoded as hex.
198 */
199
200 toHex: function(data) {
201 if (data instanceof Buffer) {
202 return data.toString('hex');
203 }
204 return data;
205 },
206 /**
207 * Convert base64 to Buffer.
208 * @param {String} data A base64 encoded string.
209 * @return {Buffer} The base64 string as a Buffer.
210 */
211
212 fromBase64: function(data) {
213 return new Buffer(data, 'base64');
214 },
215 /**
216 * Join an array of buffers together.
217 * @param {Array} buffers An array of buffers.
218 * @return {Buffer} The buffers joined together.
219 */
220
221 concat: function(buffers) {
222 return Buffer.concat(buffers);
223 },
224 /**
225 * Parse a litte endian number.
226 * @author Jim Rogers {@link http://www.jimandkatrin.com/CodeBlog/post/Parse-a-little-endian.aspx}
227 * @param {String} hex The little endian number.
228 * @return {Number} The little endian converted to a number.
229 */
230
231 parseLittleEndian: function(hex) {
232 var pow, result;
233 result = 0;
234 pow = 0;
235 while (hex.length > 0) {
236 result += parseInt(hex.substring(0, 2), 16) * Math.pow(2, pow);
237 hex = hex.substring(2, hex.length);
238 pow += 8;
239 }
240 return result;
241 },
242 /**
243 * Convert an integer into a little endian.
244 * @param {Number} number The integer you want to convert.
245 * @param {Boolean} [pad=true] Pad the little endian with zeroes.
246 * @return {String} The little endian.
247 */
248
249 stringifyLittleEndian: function(number, pad) {
250 var endian, i, multiplier, padding, power, remainder, value, _i;
251 if (pad == null) {
252 pad = true;
253 }
254 power = Math.floor((Math.log(number) / Math.LN2) / 8) * 8;
255 multiplier = Math.pow(2, power);
256 value = Math.floor(number / multiplier);
257 remainder = number % multiplier;
258 endian = "";
259 if (remainder > 255) {
260 endian += this.stringifyLittleEndian(remainder, false);
261 } else if (power !== 0) {
262 endian += this.dec2hex(remainder);
263 }
264 endian += this.dec2hex(value);
265 if (pad) {
266 padding = 16 - endian.length;
267 for (i = _i = 0; _i < padding; i = _i += 1) {
268 endian += "0";
269 }
270 }
271 return endian;
272 },
273 /**
274 * Turn a decimal into a hexadecimal.
275 * @param {Number} dec The decimal.
276 * @return {String} The hexadecimal.
277 */
278
279 dec2hex: function(dec) {
280 var hex;
281 hex = dec.toString(16);
282 if (hex.length < 2) {
283 hex = "0" + hex;
284 }
285 return hex;
286 },
287 /**
288 * Generate a uuid.
289 * @param {Number} [length=32] The length of the UUID.
290 * @return {String} The UUID.
291 */
292
293 generateUuid: function(length) {
294 if (length == null) {
295 length = 32;
296 }
297 length /= 2;
298 return this.randomBytes(length).toString('hex').toUpperCase(0);
299 }
300 };
301
302 module.exports = Crypto;
303
304}).call(this);