source: trip-planner-front/node_modules/node-forge/lib/pkcs1.js@ 1ad8e64

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

initial commit

  • Property mode set to 100644
File size: 8.2 KB
RevLine 
[6a3a178]1/**
2 * Partial implementation of PKCS#1 v2.2: RSA-OEAP
3 *
4 * Modified but based on the following MIT and BSD licensed code:
5 *
6 * https://github.com/kjur/jsjws/blob/master/rsa.js:
7 *
8 * The 'jsjws'(JSON Web Signature JavaScript Library) License
9 *
10 * Copyright (c) 2012 Kenji Urushima
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this software and associated documentation files (the "Software"), to deal
14 * in the Software without restriction, including without limitation the rights
15 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 * copies of the Software, and to permit persons to whom the Software is
17 * furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 * THE SOFTWARE.
29 *
30 * http://webrsa.cvs.sourceforge.net/viewvc/webrsa/Client/RSAES-OAEP.js?content-type=text%2Fplain:
31 *
32 * RSAES-OAEP.js
33 * $Id: RSAES-OAEP.js,v 1.1.1.1 2003/03/19 15:37:20 ellispritchard Exp $
34 * JavaScript Implementation of PKCS #1 v2.1 RSA CRYPTOGRAPHY STANDARD (RSA Laboratories, June 14, 2002)
35 * Copyright (C) Ellis Pritchard, Guardian Unlimited 2003.
36 * Contact: ellis@nukinetics.com
37 * Distributed under the BSD License.
38 *
39 * Official documentation: http://www.rsa.com/rsalabs/node.asp?id=2125
40 *
41 * @author Evan Jones (http://evanjones.ca/)
42 * @author Dave Longley
43 *
44 * Copyright (c) 2013-2014 Digital Bazaar, Inc.
45 */
46var forge = require('./forge');
47require('./util');
48require('./random');
49require('./sha1');
50
51// shortcut for PKCS#1 API
52var pkcs1 = module.exports = forge.pkcs1 = forge.pkcs1 || {};
53
54/**
55 * Encode the given RSAES-OAEP message (M) using key, with optional label (L)
56 * and seed.
57 *
58 * This method does not perform RSA encryption, it only encodes the message
59 * using RSAES-OAEP.
60 *
61 * @param key the RSA key to use.
62 * @param message the message to encode.
63 * @param options the options to use:
64 * label an optional label to use.
65 * seed the seed to use.
66 * md the message digest object to use, undefined for SHA-1.
67 * mgf1 optional mgf1 parameters:
68 * md the message digest object to use for MGF1.
69 *
70 * @return the encoded message bytes.
71 */
72pkcs1.encode_rsa_oaep = function(key, message, options) {
73 // parse arguments
74 var label;
75 var seed;
76 var md;
77 var mgf1Md;
78 // legacy args (label, seed, md)
79 if(typeof options === 'string') {
80 label = options;
81 seed = arguments[3] || undefined;
82 md = arguments[4] || undefined;
83 } else if(options) {
84 label = options.label || undefined;
85 seed = options.seed || undefined;
86 md = options.md || undefined;
87 if(options.mgf1 && options.mgf1.md) {
88 mgf1Md = options.mgf1.md;
89 }
90 }
91
92 // default OAEP to SHA-1 message digest
93 if(!md) {
94 md = forge.md.sha1.create();
95 } else {
96 md.start();
97 }
98
99 // default MGF-1 to same as OAEP
100 if(!mgf1Md) {
101 mgf1Md = md;
102 }
103
104 // compute length in bytes and check output
105 var keyLength = Math.ceil(key.n.bitLength() / 8);
106 var maxLength = keyLength - 2 * md.digestLength - 2;
107 if(message.length > maxLength) {
108 var error = new Error('RSAES-OAEP input message length is too long.');
109 error.length = message.length;
110 error.maxLength = maxLength;
111 throw error;
112 }
113
114 if(!label) {
115 label = '';
116 }
117 md.update(label, 'raw');
118 var lHash = md.digest();
119
120 var PS = '';
121 var PS_length = maxLength - message.length;
122 for(var i = 0; i < PS_length; i++) {
123 PS += '\x00';
124 }
125
126 var DB = lHash.getBytes() + PS + '\x01' + message;
127
128 if(!seed) {
129 seed = forge.random.getBytes(md.digestLength);
130 } else if(seed.length !== md.digestLength) {
131 var error = new Error('Invalid RSAES-OAEP seed. The seed length must ' +
132 'match the digest length.');
133 error.seedLength = seed.length;
134 error.digestLength = md.digestLength;
135 throw error;
136 }
137
138 var dbMask = rsa_mgf1(seed, keyLength - md.digestLength - 1, mgf1Md);
139 var maskedDB = forge.util.xorBytes(DB, dbMask, DB.length);
140
141 var seedMask = rsa_mgf1(maskedDB, md.digestLength, mgf1Md);
142 var maskedSeed = forge.util.xorBytes(seed, seedMask, seed.length);
143
144 // return encoded message
145 return '\x00' + maskedSeed + maskedDB;
146};
147
148/**
149 * Decode the given RSAES-OAEP encoded message (EM) using key, with optional
150 * label (L).
151 *
152 * This method does not perform RSA decryption, it only decodes the message
153 * using RSAES-OAEP.
154 *
155 * @param key the RSA key to use.
156 * @param em the encoded message to decode.
157 * @param options the options to use:
158 * label an optional label to use.
159 * md the message digest object to use for OAEP, undefined for SHA-1.
160 * mgf1 optional mgf1 parameters:
161 * md the message digest object to use for MGF1.
162 *
163 * @return the decoded message bytes.
164 */
165pkcs1.decode_rsa_oaep = function(key, em, options) {
166 // parse args
167 var label;
168 var md;
169 var mgf1Md;
170 // legacy args
171 if(typeof options === 'string') {
172 label = options;
173 md = arguments[3] || undefined;
174 } else if(options) {
175 label = options.label || undefined;
176 md = options.md || undefined;
177 if(options.mgf1 && options.mgf1.md) {
178 mgf1Md = options.mgf1.md;
179 }
180 }
181
182 // compute length in bytes
183 var keyLength = Math.ceil(key.n.bitLength() / 8);
184
185 if(em.length !== keyLength) {
186 var error = new Error('RSAES-OAEP encoded message length is invalid.');
187 error.length = em.length;
188 error.expectedLength = keyLength;
189 throw error;
190 }
191
192 // default OAEP to SHA-1 message digest
193 if(md === undefined) {
194 md = forge.md.sha1.create();
195 } else {
196 md.start();
197 }
198
199 // default MGF-1 to same as OAEP
200 if(!mgf1Md) {
201 mgf1Md = md;
202 }
203
204 if(keyLength < 2 * md.digestLength + 2) {
205 throw new Error('RSAES-OAEP key is too short for the hash function.');
206 }
207
208 if(!label) {
209 label = '';
210 }
211 md.update(label, 'raw');
212 var lHash = md.digest().getBytes();
213
214 // split the message into its parts
215 var y = em.charAt(0);
216 var maskedSeed = em.substring(1, md.digestLength + 1);
217 var maskedDB = em.substring(1 + md.digestLength);
218
219 var seedMask = rsa_mgf1(maskedDB, md.digestLength, mgf1Md);
220 var seed = forge.util.xorBytes(maskedSeed, seedMask, maskedSeed.length);
221
222 var dbMask = rsa_mgf1(seed, keyLength - md.digestLength - 1, mgf1Md);
223 var db = forge.util.xorBytes(maskedDB, dbMask, maskedDB.length);
224
225 var lHashPrime = db.substring(0, md.digestLength);
226
227 // constant time check that all values match what is expected
228 var error = (y !== '\x00');
229
230 // constant time check lHash vs lHashPrime
231 for(var i = 0; i < md.digestLength; ++i) {
232 error |= (lHash.charAt(i) !== lHashPrime.charAt(i));
233 }
234
235 // "constant time" find the 0x1 byte separating the padding (zeros) from the
236 // message
237 // TODO: It must be possible to do this in a better/smarter way?
238 var in_ps = 1;
239 var index = md.digestLength;
240 for(var j = md.digestLength; j < db.length; j++) {
241 var code = db.charCodeAt(j);
242
243 var is_0 = (code & 0x1) ^ 0x1;
244
245 // non-zero if not 0 or 1 in the ps section
246 var error_mask = in_ps ? 0xfffe : 0x0000;
247 error |= (code & error_mask);
248
249 // latch in_ps to zero after we find 0x1
250 in_ps = in_ps & is_0;
251 index += in_ps;
252 }
253
254 if(error || db.charCodeAt(index) !== 0x1) {
255 throw new Error('Invalid RSAES-OAEP padding.');
256 }
257
258 return db.substring(index + 1);
259};
260
261function rsa_mgf1(seed, maskLength, hash) {
262 // default to SHA-1 message digest
263 if(!hash) {
264 hash = forge.md.sha1.create();
265 }
266 var t = '';
267 var count = Math.ceil(maskLength / hash.digestLength);
268 for(var i = 0; i < count; ++i) {
269 var c = String.fromCharCode(
270 (i >> 24) & 0xFF, (i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
271 hash.start();
272 hash.update(seed + c);
273 t += hash.digest().getBytes();
274 }
275 return t.substring(0, maskLength);
276}
Note: See TracBrowser for help on using the repository browser.