]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.maps.server/node/node-v4.8.0-win-x64/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/key.js
Adding integrated tile server
[simantics/district.git] / org.simantics.maps.server / node / node-v4.8.0-win-x64 / node_modules / npm / node_modules / request / node_modules / http-signature / node_modules / sshpk / lib / key.js
1 // Copyright 2015 Joyent, Inc.
2
3 module.exports = Key;
4
5 var assert = require('assert-plus');
6 var algs = require('./algs');
7 var crypto = require('crypto');
8 var Fingerprint = require('./fingerprint');
9 var Signature = require('./signature');
10 var DiffieHellman = require('./dhe');
11 var errs = require('./errors');
12 var utils = require('./utils');
13 var PrivateKey = require('./private-key');
14 var edCompat;
15
16 try {
17         edCompat = require('./ed-compat');
18 } catch (e) {
19         /* Just continue through, and bail out if we try to use it. */
20 }
21
22 var InvalidAlgorithmError = errs.InvalidAlgorithmError;
23 var KeyParseError = errs.KeyParseError;
24
25 var formats = {};
26 formats['auto'] = require('./formats/auto');
27 formats['pem'] = require('./formats/pem');
28 formats['pkcs1'] = require('./formats/pkcs1');
29 formats['pkcs8'] = require('./formats/pkcs8');
30 formats['rfc4253'] = require('./formats/rfc4253');
31 formats['ssh'] = require('./formats/ssh');
32 formats['ssh-private'] = require('./formats/ssh-private');
33 formats['openssh'] = formats['ssh-private'];
34
35 function Key(opts) {
36         assert.object(opts, 'options');
37         assert.arrayOfObject(opts.parts, 'options.parts');
38         assert.string(opts.type, 'options.type');
39         assert.optionalString(opts.comment, 'options.comment');
40
41         var algInfo = algs.info[opts.type];
42         if (typeof (algInfo) !== 'object')
43                 throw (new InvalidAlgorithmError(opts.type));
44
45         var partLookup = {};
46         for (var i = 0; i < opts.parts.length; ++i) {
47                 var part = opts.parts[i];
48                 partLookup[part.name] = part;
49         }
50
51         this.type = opts.type;
52         this.parts = opts.parts;
53         this.part = partLookup;
54         this.comment = undefined;
55         this.source = opts.source;
56
57         /* for speeding up hashing/fingerprint operations */
58         this._rfc4253Cache = opts._rfc4253Cache;
59         this._hashCache = {};
60
61         var sz;
62         this.curve = undefined;
63         if (this.type === 'ecdsa') {
64                 var curve = this.part.curve.data.toString();
65                 this.curve = curve;
66                 sz = algs.curves[curve].size;
67         } else if (this.type === 'ed25519') {
68                 sz = 256;
69                 this.curve = 'curve25519';
70         } else {
71                 var szPart = this.part[algInfo.sizePart];
72                 sz = szPart.data.length;
73                 sz = sz * 8 - utils.countZeros(szPart.data);
74         }
75         this.size = sz;
76 }
77
78 Key.formats = formats;
79
80 Key.prototype.toBuffer = function (format, options) {
81         if (format === undefined)
82                 format = 'ssh';
83         assert.string(format, 'format');
84         assert.object(formats[format], 'formats[format]');
85         assert.optionalObject(options, 'options');
86
87         if (format === 'rfc4253') {
88                 if (this._rfc4253Cache === undefined)
89                         this._rfc4253Cache = formats['rfc4253'].write(this);
90                 return (this._rfc4253Cache);
91         }
92
93         return (formats[format].write(this, options));
94 };
95
96 Key.prototype.toString = function (format, options) {
97         return (this.toBuffer(format, options).toString());
98 };
99
100 Key.prototype.hash = function (algo) {
101         assert.string(algo, 'algorithm');
102         algo = algo.toLowerCase();
103         if (algs.hashAlgs[algo] === undefined)
104                 throw (new InvalidAlgorithmError(algo));
105
106         if (this._hashCache[algo])
107                 return (this._hashCache[algo]);
108
109         var hash = crypto.createHash(algo).
110             update(this.toBuffer('rfc4253')).digest();
111         this._hashCache[algo] = hash;
112         return (hash);
113 };
114
115 Key.prototype.fingerprint = function (algo) {
116         if (algo === undefined)
117                 algo = 'sha256';
118         assert.string(algo, 'algorithm');
119         var opts = {
120                 type: 'key',
121                 hash: this.hash(algo),
122                 algorithm: algo
123         };
124         return (new Fingerprint(opts));
125 };
126
127 Key.prototype.defaultHashAlgorithm = function () {
128         var hashAlgo = 'sha1';
129         if (this.type === 'rsa')
130                 hashAlgo = 'sha256';
131         if (this.type === 'dsa' && this.size > 1024)
132                 hashAlgo = 'sha256';
133         if (this.type === 'ed25519')
134                 hashAlgo = 'sha512';
135         if (this.type === 'ecdsa') {
136                 if (this.size <= 256)
137                         hashAlgo = 'sha256';
138                 else if (this.size <= 384)
139                         hashAlgo = 'sha384';
140                 else
141                         hashAlgo = 'sha512';
142         }
143         return (hashAlgo);
144 };
145
146 Key.prototype.createVerify = function (hashAlgo) {
147         if (hashAlgo === undefined)
148                 hashAlgo = this.defaultHashAlgorithm();
149         assert.string(hashAlgo, 'hash algorithm');
150
151         /* ED25519 is not supported by OpenSSL, use a javascript impl. */
152         if (this.type === 'ed25519' && edCompat !== undefined)
153                 return (new edCompat.Verifier(this, hashAlgo));
154         if (this.type === 'curve25519')
155                 throw (new Error('Curve25519 keys are not suitable for ' +
156                     'signing or verification'));
157
158         var v, nm, err;
159         try {
160                 nm = hashAlgo.toUpperCase();
161                 v = crypto.createVerify(nm);
162         } catch (e) {
163                 err = e;
164         }
165         if (v === undefined || (err instanceof Error &&
166             err.message.match(/Unknown message digest/))) {
167                 nm = 'RSA-';
168                 nm += hashAlgo.toUpperCase();
169                 v = crypto.createVerify(nm);
170         }
171         assert.ok(v, 'failed to create verifier');
172         var oldVerify = v.verify.bind(v);
173         var key = this.toBuffer('pkcs8');
174         var self = this;
175         v.verify = function (signature, fmt) {
176                 if (Signature.isSignature(signature, [2, 0])) {
177                         if (signature.type !== self.type)
178                                 return (false);
179                         if (signature.hashAlgorithm &&
180                             signature.hashAlgorithm !== hashAlgo)
181                                 return (false);
182                         return (oldVerify(key, signature.toBuffer('asn1')));
183
184                 } else if (typeof (signature) === 'string' ||
185                     Buffer.isBuffer(signature)) {
186                         return (oldVerify(key, signature, fmt));
187
188                 /*
189                  * Avoid doing this on valid arguments, walking the prototype
190                  * chain can be quite slow.
191                  */
192                 } else if (Signature.isSignature(signature, [1, 0])) {
193                         throw (new Error('signature was created by too old ' +
194                             'a version of sshpk and cannot be verified'));
195
196                 } else {
197                         throw (new TypeError('signature must be a string, ' +
198                             'Buffer, or Signature object'));
199                 }
200         };
201         return (v);
202 };
203
204 Key.prototype.createDiffieHellman = function () {
205         if (this.type === 'rsa')
206                 throw (new Error('RSA keys do not support Diffie-Hellman'));
207
208         return (new DiffieHellman(this));
209 };
210 Key.prototype.createDH = Key.prototype.createDiffieHellman;
211
212 Key.parse = function (data, format, options) {
213         if (typeof (data) !== 'string')
214                 assert.buffer(data, 'data');
215         if (format === undefined)
216                 format = 'auto';
217         assert.string(format, 'format');
218         if (typeof (options) === 'string')
219                 options = { filename: options };
220         assert.optionalObject(options, 'options');
221         if (options === undefined)
222                 options = {};
223         assert.optionalString(options.filename, 'options.filename');
224         if (options.filename === undefined)
225                 options.filename = '(unnamed)';
226
227         assert.object(formats[format], 'formats[format]');
228
229         try {
230                 var k = formats[format].read(data, options);
231                 if (k instanceof PrivateKey)
232                         k = k.toPublic();
233                 if (!k.comment)
234                         k.comment = options.filename;
235                 return (k);
236         } catch (e) {
237                 if (e.name === 'KeyEncryptedError')
238                         throw (e);
239                 throw (new KeyParseError(options.filename, format, e));
240         }
241 };
242
243 Key.isKey = function (obj, ver) {
244         return (utils.isCompatible(obj, Key, ver));
245 };
246
247 /*
248  * API versions for Key:
249  * [1,0] -- initial ver, may take Signature for createVerify or may not
250  * [1,1] -- added pkcs1, pkcs8 formats
251  * [1,2] -- added auto, ssh-private, openssh formats
252  * [1,3] -- added defaultHashAlgorithm
253  * [1,4] -- added ed support, createDH
254  * [1,5] -- first explicitly tagged version
255  */
256 Key.prototype._sshpkApiVersion = [1, 5];
257
258 Key._oldVersionDetect = function (obj) {
259         assert.func(obj.toBuffer);
260         assert.func(obj.fingerprint);
261         if (obj.createDH)
262                 return ([1, 4]);
263         if (obj.defaultHashAlgorithm)
264                 return ([1, 3]);
265         if (obj.formats['auto'])
266                 return ([1, 2]);
267         if (obj.formats['pkcs1'])
268                 return ([1, 1]);
269         return ([1, 0]);
270 };