source: trip-planner-front/node_modules/node-forge/lib/cipher.js

Last change on this file was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 6.5 KB
Line 
1/**
2 * Cipher base API.
3 *
4 * @author Dave Longley
5 *
6 * Copyright (c) 2010-2014 Digital Bazaar, Inc.
7 */
8var forge = require('./forge');
9require('./util');
10
11module.exports = forge.cipher = forge.cipher || {};
12
13// registered algorithms
14forge.cipher.algorithms = forge.cipher.algorithms || {};
15
16/**
17 * Creates a cipher object that can be used to encrypt data using the given
18 * algorithm and key. The algorithm may be provided as a string value for a
19 * previously registered algorithm or it may be given as a cipher algorithm
20 * API object.
21 *
22 * @param algorithm the algorithm to use, either a string or an algorithm API
23 * object.
24 * @param key the key to use, as a binary-encoded string of bytes or a
25 * byte buffer.
26 *
27 * @return the cipher.
28 */
29forge.cipher.createCipher = function(algorithm, key) {
30 var api = algorithm;
31 if(typeof api === 'string') {
32 api = forge.cipher.getAlgorithm(api);
33 if(api) {
34 api = api();
35 }
36 }
37 if(!api) {
38 throw new Error('Unsupported algorithm: ' + algorithm);
39 }
40
41 // assume block cipher
42 return new forge.cipher.BlockCipher({
43 algorithm: api,
44 key: key,
45 decrypt: false
46 });
47};
48
49/**
50 * Creates a decipher object that can be used to decrypt data using the given
51 * algorithm and key. The algorithm may be provided as a string value for a
52 * previously registered algorithm or it may be given as a cipher algorithm
53 * API object.
54 *
55 * @param algorithm the algorithm to use, either a string or an algorithm API
56 * object.
57 * @param key the key to use, as a binary-encoded string of bytes or a
58 * byte buffer.
59 *
60 * @return the cipher.
61 */
62forge.cipher.createDecipher = function(algorithm, key) {
63 var api = algorithm;
64 if(typeof api === 'string') {
65 api = forge.cipher.getAlgorithm(api);
66 if(api) {
67 api = api();
68 }
69 }
70 if(!api) {
71 throw new Error('Unsupported algorithm: ' + algorithm);
72 }
73
74 // assume block cipher
75 return new forge.cipher.BlockCipher({
76 algorithm: api,
77 key: key,
78 decrypt: true
79 });
80};
81
82/**
83 * Registers an algorithm by name. If the name was already registered, the
84 * algorithm API object will be overwritten.
85 *
86 * @param name the name of the algorithm.
87 * @param algorithm the algorithm API object.
88 */
89forge.cipher.registerAlgorithm = function(name, algorithm) {
90 name = name.toUpperCase();
91 forge.cipher.algorithms[name] = algorithm;
92};
93
94/**
95 * Gets a registered algorithm by name.
96 *
97 * @param name the name of the algorithm.
98 *
99 * @return the algorithm, if found, null if not.
100 */
101forge.cipher.getAlgorithm = function(name) {
102 name = name.toUpperCase();
103 if(name in forge.cipher.algorithms) {
104 return forge.cipher.algorithms[name];
105 }
106 return null;
107};
108
109var BlockCipher = forge.cipher.BlockCipher = function(options) {
110 this.algorithm = options.algorithm;
111 this.mode = this.algorithm.mode;
112 this.blockSize = this.mode.blockSize;
113 this._finish = false;
114 this._input = null;
115 this.output = null;
116 this._op = options.decrypt ? this.mode.decrypt : this.mode.encrypt;
117 this._decrypt = options.decrypt;
118 this.algorithm.initialize(options);
119};
120
121/**
122 * Starts or restarts the encryption or decryption process, whichever
123 * was previously configured.
124 *
125 * For non-GCM mode, the IV may be a binary-encoded string of bytes, an array
126 * of bytes, a byte buffer, or an array of 32-bit integers. If the IV is in
127 * bytes, then it must be Nb (16) bytes in length. If the IV is given in as
128 * 32-bit integers, then it must be 4 integers long.
129 *
130 * Note: an IV is not required or used in ECB mode.
131 *
132 * For GCM-mode, the IV must be given as a binary-encoded string of bytes or
133 * a byte buffer. The number of bytes should be 12 (96 bits) as recommended
134 * by NIST SP-800-38D but another length may be given.
135 *
136 * @param options the options to use:
137 * iv the initialization vector to use as a binary-encoded string of
138 * bytes, null to reuse the last ciphered block from a previous
139 * update() (this "residue" method is for legacy support only).
140 * additionalData additional authentication data as a binary-encoded
141 * string of bytes, for 'GCM' mode, (default: none).
142 * tagLength desired length of authentication tag, in bits, for
143 * 'GCM' mode (0-128, default: 128).
144 * tag the authentication tag to check if decrypting, as a
145 * binary-encoded string of bytes.
146 * output the output the buffer to write to, null to create one.
147 */
148BlockCipher.prototype.start = function(options) {
149 options = options || {};
150 var opts = {};
151 for(var key in options) {
152 opts[key] = options[key];
153 }
154 opts.decrypt = this._decrypt;
155 this._finish = false;
156 this._input = forge.util.createBuffer();
157 this.output = options.output || forge.util.createBuffer();
158 this.mode.start(opts);
159};
160
161/**
162 * Updates the next block according to the cipher mode.
163 *
164 * @param input the buffer to read from.
165 */
166BlockCipher.prototype.update = function(input) {
167 if(input) {
168 // input given, so empty it into the input buffer
169 this._input.putBuffer(input);
170 }
171
172 // do cipher operation until it needs more input and not finished
173 while(!this._op.call(this.mode, this._input, this.output, this._finish) &&
174 !this._finish) {}
175
176 // free consumed memory from input buffer
177 this._input.compact();
178};
179
180/**
181 * Finishes encrypting or decrypting.
182 *
183 * @param pad a padding function to use in CBC mode, null for default,
184 * signature(blockSize, buffer, decrypt).
185 *
186 * @return true if successful, false on error.
187 */
188BlockCipher.prototype.finish = function(pad) {
189 // backwards-compatibility w/deprecated padding API
190 // Note: will overwrite padding functions even after another start() call
191 if(pad && (this.mode.name === 'ECB' || this.mode.name === 'CBC')) {
192 this.mode.pad = function(input) {
193 return pad(this.blockSize, input, false);
194 };
195 this.mode.unpad = function(output) {
196 return pad(this.blockSize, output, true);
197 };
198 }
199
200 // build options for padding and afterFinish functions
201 var options = {};
202 options.decrypt = this._decrypt;
203
204 // get # of bytes that won't fill a block
205 options.overflow = this._input.length() % this.blockSize;
206
207 if(!this._decrypt && this.mode.pad) {
208 if(!this.mode.pad(this._input, options)) {
209 return false;
210 }
211 }
212
213 // do final update
214 this._finish = true;
215 this.update();
216
217 if(this._decrypt && this.mode.unpad) {
218 if(!this.mode.unpad(this.output, options)) {
219 return false;
220 }
221 }
222
223 if(this.mode.afterFinish) {
224 if(!this.mode.afterFinish(this.output, options)) {
225 return false;
226 }
227 }
228
229 return true;
230};
Note: See TracBrowser for help on using the repository browser.