source: trip-planner-front/node_modules/node-forge/lib/kem.js@ bdd6491

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

initial commit

  • Property mode set to 100644
File size: 5.1 KB
Line 
1/**
2 * Javascript implementation of RSA-KEM.
3 *
4 * @author Lautaro Cozzani Rodriguez
5 * @author Dave Longley
6 *
7 * Copyright (c) 2014 Lautaro Cozzani <lautaro.cozzani@scytl.com>
8 * Copyright (c) 2014 Digital Bazaar, Inc.
9 */
10var forge = require('./forge');
11require('./util');
12require('./random');
13require('./jsbn');
14
15module.exports = forge.kem = forge.kem || {};
16
17var BigInteger = forge.jsbn.BigInteger;
18
19/**
20 * The API for the RSA Key Encapsulation Mechanism (RSA-KEM) from ISO 18033-2.
21 */
22forge.kem.rsa = {};
23
24/**
25 * Creates an RSA KEM API object for generating a secret asymmetric key.
26 *
27 * The symmetric key may be generated via a call to 'encrypt', which will
28 * produce a ciphertext to be transmitted to the recipient and a key to be
29 * kept secret. The ciphertext is a parameter to be passed to 'decrypt' which
30 * will produce the same secret key for the recipient to use to decrypt a
31 * message that was encrypted with the secret key.
32 *
33 * @param kdf the KDF API to use (eg: new forge.kem.kdf1()).
34 * @param options the options to use.
35 * [prng] a custom crypto-secure pseudo-random number generator to use,
36 * that must define "getBytesSync".
37 */
38forge.kem.rsa.create = function(kdf, options) {
39 options = options || {};
40 var prng = options.prng || forge.random;
41
42 var kem = {};
43
44 /**
45 * Generates a secret key and its encapsulation.
46 *
47 * @param publicKey the RSA public key to encrypt with.
48 * @param keyLength the length, in bytes, of the secret key to generate.
49 *
50 * @return an object with:
51 * encapsulation: the ciphertext for generating the secret key, as a
52 * binary-encoded string of bytes.
53 * key: the secret key to use for encrypting a message.
54 */
55 kem.encrypt = function(publicKey, keyLength) {
56 // generate a random r where 1 < r < n
57 var byteLength = Math.ceil(publicKey.n.bitLength() / 8);
58 var r;
59 do {
60 r = new BigInteger(
61 forge.util.bytesToHex(prng.getBytesSync(byteLength)),
62 16).mod(publicKey.n);
63 } while(r.compareTo(BigInteger.ONE) <= 0);
64
65 // prepend r with zeros
66 r = forge.util.hexToBytes(r.toString(16));
67 var zeros = byteLength - r.length;
68 if(zeros > 0) {
69 r = forge.util.fillString(String.fromCharCode(0), zeros) + r;
70 }
71
72 // encrypt the random
73 var encapsulation = publicKey.encrypt(r, 'NONE');
74
75 // generate the secret key
76 var key = kdf.generate(r, keyLength);
77
78 return {encapsulation: encapsulation, key: key};
79 };
80
81 /**
82 * Decrypts an encapsulated secret key.
83 *
84 * @param privateKey the RSA private key to decrypt with.
85 * @param encapsulation the ciphertext for generating the secret key, as
86 * a binary-encoded string of bytes.
87 * @param keyLength the length, in bytes, of the secret key to generate.
88 *
89 * @return the secret key as a binary-encoded string of bytes.
90 */
91 kem.decrypt = function(privateKey, encapsulation, keyLength) {
92 // decrypt the encapsulation and generate the secret key
93 var r = privateKey.decrypt(encapsulation, 'NONE');
94 return kdf.generate(r, keyLength);
95 };
96
97 return kem;
98};
99
100// TODO: add forge.kem.kdf.create('KDF1', {md: ..., ...}) API?
101
102/**
103 * Creates a key derivation API object that implements KDF1 per ISO 18033-2.
104 *
105 * @param md the hash API to use.
106 * @param [digestLength] an optional digest length that must be positive and
107 * less than or equal to md.digestLength.
108 *
109 * @return a KDF1 API object.
110 */
111forge.kem.kdf1 = function(md, digestLength) {
112 _createKDF(this, md, 0, digestLength || md.digestLength);
113};
114
115/**
116 * Creates a key derivation API object that implements KDF2 per ISO 18033-2.
117 *
118 * @param md the hash API to use.
119 * @param [digestLength] an optional digest length that must be positive and
120 * less than or equal to md.digestLength.
121 *
122 * @return a KDF2 API object.
123 */
124forge.kem.kdf2 = function(md, digestLength) {
125 _createKDF(this, md, 1, digestLength || md.digestLength);
126};
127
128/**
129 * Creates a KDF1 or KDF2 API object.
130 *
131 * @param md the hash API to use.
132 * @param counterStart the starting index for the counter.
133 * @param digestLength the digest length to use.
134 *
135 * @return the KDF API object.
136 */
137function _createKDF(kdf, md, counterStart, digestLength) {
138 /**
139 * Generate a key of the specified length.
140 *
141 * @param x the binary-encoded byte string to generate a key from.
142 * @param length the number of bytes to generate (the size of the key).
143 *
144 * @return the key as a binary-encoded string.
145 */
146 kdf.generate = function(x, length) {
147 var key = new forge.util.ByteBuffer();
148
149 // run counter from counterStart to ceil(length / Hash.len)
150 var k = Math.ceil(length / digestLength) + counterStart;
151
152 var c = new forge.util.ByteBuffer();
153 for(var i = counterStart; i < k; ++i) {
154 // I2OSP(i, 4): convert counter to an octet string of 4 octets
155 c.putInt32(i);
156
157 // digest 'x' and the counter and add the result to the key
158 md.start();
159 md.update(x + c.getBytes());
160 var hash = md.digest();
161 key.putBytes(hash.getBytes(digestLength));
162 }
163
164 // truncate to the correct key length
165 key.truncate(key.length() - length);
166 return key.getBytes();
167 };
168}
Note: See TracBrowser for help on using the repository browser.