source: trip-planner-front/node_modules/sshpk/lib/private-key.js@ b738035

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

initial commit

  • Property mode set to 100644
File size: 6.6 KB
RevLine 
[6a3a178]1// Copyright 2017 Joyent, Inc.
2
3module.exports = PrivateKey;
4
5var assert = require('assert-plus');
6var Buffer = require('safer-buffer').Buffer;
7var algs = require('./algs');
8var crypto = require('crypto');
9var Fingerprint = require('./fingerprint');
10var Signature = require('./signature');
11var errs = require('./errors');
12var util = require('util');
13var utils = require('./utils');
14var dhe = require('./dhe');
15var generateECDSA = dhe.generateECDSA;
16var generateED25519 = dhe.generateED25519;
17var edCompat = require('./ed-compat');
18var nacl = require('tweetnacl');
19
20var Key = require('./key');
21
22var InvalidAlgorithmError = errs.InvalidAlgorithmError;
23var KeyParseError = errs.KeyParseError;
24var KeyEncryptedError = errs.KeyEncryptedError;
25
26var formats = {};
27formats['auto'] = require('./formats/auto');
28formats['pem'] = require('./formats/pem');
29formats['pkcs1'] = require('./formats/pkcs1');
30formats['pkcs8'] = require('./formats/pkcs8');
31formats['rfc4253'] = require('./formats/rfc4253');
32formats['ssh-private'] = require('./formats/ssh-private');
33formats['openssh'] = formats['ssh-private'];
34formats['ssh'] = formats['ssh-private'];
35formats['dnssec'] = require('./formats/dnssec');
36
37function PrivateKey(opts) {
38 assert.object(opts, 'options');
39 Key.call(this, opts);
40
41 this._pubCache = undefined;
42}
43util.inherits(PrivateKey, Key);
44
45PrivateKey.formats = formats;
46
47PrivateKey.prototype.toBuffer = function (format, options) {
48 if (format === undefined)
49 format = 'pkcs1';
50 assert.string(format, 'format');
51 assert.object(formats[format], 'formats[format]');
52 assert.optionalObject(options, 'options');
53
54 return (formats[format].write(this, options));
55};
56
57PrivateKey.prototype.hash = function (algo, type) {
58 return (this.toPublic().hash(algo, type));
59};
60
61PrivateKey.prototype.fingerprint = function (algo, type) {
62 return (this.toPublic().fingerprint(algo, type));
63};
64
65PrivateKey.prototype.toPublic = function () {
66 if (this._pubCache)
67 return (this._pubCache);
68
69 var algInfo = algs.info[this.type];
70 var pubParts = [];
71 for (var i = 0; i < algInfo.parts.length; ++i) {
72 var p = algInfo.parts[i];
73 pubParts.push(this.part[p]);
74 }
75
76 this._pubCache = new Key({
77 type: this.type,
78 source: this,
79 parts: pubParts
80 });
81 if (this.comment)
82 this._pubCache.comment = this.comment;
83 return (this._pubCache);
84};
85
86PrivateKey.prototype.derive = function (newType) {
87 assert.string(newType, 'type');
88 var priv, pub, pair;
89
90 if (this.type === 'ed25519' && newType === 'curve25519') {
91 priv = this.part.k.data;
92 if (priv[0] === 0x00)
93 priv = priv.slice(1);
94
95 pair = nacl.box.keyPair.fromSecretKey(new Uint8Array(priv));
96 pub = Buffer.from(pair.publicKey);
97
98 return (new PrivateKey({
99 type: 'curve25519',
100 parts: [
101 { name: 'A', data: utils.mpNormalize(pub) },
102 { name: 'k', data: utils.mpNormalize(priv) }
103 ]
104 }));
105 } else if (this.type === 'curve25519' && newType === 'ed25519') {
106 priv = this.part.k.data;
107 if (priv[0] === 0x00)
108 priv = priv.slice(1);
109
110 pair = nacl.sign.keyPair.fromSeed(new Uint8Array(priv));
111 pub = Buffer.from(pair.publicKey);
112
113 return (new PrivateKey({
114 type: 'ed25519',
115 parts: [
116 { name: 'A', data: utils.mpNormalize(pub) },
117 { name: 'k', data: utils.mpNormalize(priv) }
118 ]
119 }));
120 }
121 throw (new Error('Key derivation not supported from ' + this.type +
122 ' to ' + newType));
123};
124
125PrivateKey.prototype.createVerify = function (hashAlgo) {
126 return (this.toPublic().createVerify(hashAlgo));
127};
128
129PrivateKey.prototype.createSign = function (hashAlgo) {
130 if (hashAlgo === undefined)
131 hashAlgo = this.defaultHashAlgorithm();
132 assert.string(hashAlgo, 'hash algorithm');
133
134 /* ED25519 is not supported by OpenSSL, use a javascript impl. */
135 if (this.type === 'ed25519' && edCompat !== undefined)
136 return (new edCompat.Signer(this, hashAlgo));
137 if (this.type === 'curve25519')
138 throw (new Error('Curve25519 keys are not suitable for ' +
139 'signing or verification'));
140
141 var v, nm, err;
142 try {
143 nm = hashAlgo.toUpperCase();
144 v = crypto.createSign(nm);
145 } catch (e) {
146 err = e;
147 }
148 if (v === undefined || (err instanceof Error &&
149 err.message.match(/Unknown message digest/))) {
150 nm = 'RSA-';
151 nm += hashAlgo.toUpperCase();
152 v = crypto.createSign(nm);
153 }
154 assert.ok(v, 'failed to create verifier');
155 var oldSign = v.sign.bind(v);
156 var key = this.toBuffer('pkcs1');
157 var type = this.type;
158 var curve = this.curve;
159 v.sign = function () {
160 var sig = oldSign(key);
161 if (typeof (sig) === 'string')
162 sig = Buffer.from(sig, 'binary');
163 sig = Signature.parse(sig, type, 'asn1');
164 sig.hashAlgorithm = hashAlgo;
165 sig.curve = curve;
166 return (sig);
167 };
168 return (v);
169};
170
171PrivateKey.parse = function (data, format, options) {
172 if (typeof (data) !== 'string')
173 assert.buffer(data, 'data');
174 if (format === undefined)
175 format = 'auto';
176 assert.string(format, 'format');
177 if (typeof (options) === 'string')
178 options = { filename: options };
179 assert.optionalObject(options, 'options');
180 if (options === undefined)
181 options = {};
182 assert.optionalString(options.filename, 'options.filename');
183 if (options.filename === undefined)
184 options.filename = '(unnamed)';
185
186 assert.object(formats[format], 'formats[format]');
187
188 try {
189 var k = formats[format].read(data, options);
190 assert.ok(k instanceof PrivateKey, 'key is not a private key');
191 if (!k.comment)
192 k.comment = options.filename;
193 return (k);
194 } catch (e) {
195 if (e.name === 'KeyEncryptedError')
196 throw (e);
197 throw (new KeyParseError(options.filename, format, e));
198 }
199};
200
201PrivateKey.isPrivateKey = function (obj, ver) {
202 return (utils.isCompatible(obj, PrivateKey, ver));
203};
204
205PrivateKey.generate = function (type, options) {
206 if (options === undefined)
207 options = {};
208 assert.object(options, 'options');
209
210 switch (type) {
211 case 'ecdsa':
212 if (options.curve === undefined)
213 options.curve = 'nistp256';
214 assert.string(options.curve, 'options.curve');
215 return (generateECDSA(options.curve));
216 case 'ed25519':
217 return (generateED25519());
218 default:
219 throw (new Error('Key generation not supported with key ' +
220 'type "' + type + '"'));
221 }
222};
223
224/*
225 * API versions for PrivateKey:
226 * [1,0] -- initial ver
227 * [1,1] -- added auto, pkcs[18], openssh/ssh-private formats
228 * [1,2] -- added defaultHashAlgorithm
229 * [1,3] -- added derive, ed, createDH
230 * [1,4] -- first tagged version
231 * [1,5] -- changed ed25519 part names and format
232 * [1,6] -- type arguments for hash() and fingerprint()
233 */
234PrivateKey.prototype._sshpkApiVersion = [1, 6];
235
236PrivateKey._oldVersionDetect = function (obj) {
237 assert.func(obj.toPublic);
238 assert.func(obj.createSign);
239 if (obj.derive)
240 return ([1, 3]);
241 if (obj.defaultHashAlgorithm)
242 return ([1, 2]);
243 if (obj.formats['auto'])
244 return ([1, 1]);
245 return ([1, 0]);
246};
Note: See TracBrowser for help on using the repository browser.