source: trip-planner-front/node_modules/sshpk/lib/fingerprint.js@ 6c1585f

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

initial commit

  • Property mode set to 100644
File size: 5.4 KB
Line 
1// Copyright 2018 Joyent, Inc.
2
3module.exports = Fingerprint;
4
5var assert = require('assert-plus');
6var Buffer = require('safer-buffer').Buffer;
7var algs = require('./algs');
8var crypto = require('crypto');
9var errs = require('./errors');
10var Key = require('./key');
11var PrivateKey = require('./private-key');
12var Certificate = require('./certificate');
13var utils = require('./utils');
14
15var FingerprintFormatError = errs.FingerprintFormatError;
16var InvalidAlgorithmError = errs.InvalidAlgorithmError;
17
18function Fingerprint(opts) {
19 assert.object(opts, 'options');
20 assert.string(opts.type, 'options.type');
21 assert.buffer(opts.hash, 'options.hash');
22 assert.string(opts.algorithm, 'options.algorithm');
23
24 this.algorithm = opts.algorithm.toLowerCase();
25 if (algs.hashAlgs[this.algorithm] !== true)
26 throw (new InvalidAlgorithmError(this.algorithm));
27
28 this.hash = opts.hash;
29 this.type = opts.type;
30 this.hashType = opts.hashType;
31}
32
33Fingerprint.prototype.toString = function (format) {
34 if (format === undefined) {
35 if (this.algorithm === 'md5' || this.hashType === 'spki')
36 format = 'hex';
37 else
38 format = 'base64';
39 }
40 assert.string(format);
41
42 switch (format) {
43 case 'hex':
44 if (this.hashType === 'spki')
45 return (this.hash.toString('hex'));
46 return (addColons(this.hash.toString('hex')));
47 case 'base64':
48 if (this.hashType === 'spki')
49 return (this.hash.toString('base64'));
50 return (sshBase64Format(this.algorithm,
51 this.hash.toString('base64')));
52 default:
53 throw (new FingerprintFormatError(undefined, format));
54 }
55};
56
57Fingerprint.prototype.matches = function (other) {
58 assert.object(other, 'key or certificate');
59 if (this.type === 'key' && this.hashType !== 'ssh') {
60 utils.assertCompatible(other, Key, [1, 7], 'key with spki');
61 if (PrivateKey.isPrivateKey(other)) {
62 utils.assertCompatible(other, PrivateKey, [1, 6],
63 'privatekey with spki support');
64 }
65 } else if (this.type === 'key') {
66 utils.assertCompatible(other, Key, [1, 0], 'key');
67 } else {
68 utils.assertCompatible(other, Certificate, [1, 0],
69 'certificate');
70 }
71
72 var theirHash = other.hash(this.algorithm, this.hashType);
73 var theirHash2 = crypto.createHash(this.algorithm).
74 update(theirHash).digest('base64');
75
76 if (this.hash2 === undefined)
77 this.hash2 = crypto.createHash(this.algorithm).
78 update(this.hash).digest('base64');
79
80 return (this.hash2 === theirHash2);
81};
82
83/*JSSTYLED*/
84var base64RE = /^[A-Za-z0-9+\/=]+$/;
85/*JSSTYLED*/
86var hexRE = /^[a-fA-F0-9]+$/;
87
88Fingerprint.parse = function (fp, options) {
89 assert.string(fp, 'fingerprint');
90
91 var alg, hash, enAlgs;
92 if (Array.isArray(options)) {
93 enAlgs = options;
94 options = {};
95 }
96 assert.optionalObject(options, 'options');
97 if (options === undefined)
98 options = {};
99 if (options.enAlgs !== undefined)
100 enAlgs = options.enAlgs;
101 if (options.algorithms !== undefined)
102 enAlgs = options.algorithms;
103 assert.optionalArrayOfString(enAlgs, 'algorithms');
104
105 var hashType = 'ssh';
106 if (options.hashType !== undefined)
107 hashType = options.hashType;
108 assert.string(hashType, 'options.hashType');
109
110 var parts = fp.split(':');
111 if (parts.length == 2) {
112 alg = parts[0].toLowerCase();
113 if (!base64RE.test(parts[1]))
114 throw (new FingerprintFormatError(fp));
115 try {
116 hash = Buffer.from(parts[1], 'base64');
117 } catch (e) {
118 throw (new FingerprintFormatError(fp));
119 }
120 } else if (parts.length > 2) {
121 alg = 'md5';
122 if (parts[0].toLowerCase() === 'md5')
123 parts = parts.slice(1);
124 parts = parts.map(function (p) {
125 while (p.length < 2)
126 p = '0' + p;
127 if (p.length > 2)
128 throw (new FingerprintFormatError(fp));
129 return (p);
130 });
131 parts = parts.join('');
132 if (!hexRE.test(parts) || parts.length % 2 !== 0)
133 throw (new FingerprintFormatError(fp));
134 try {
135 hash = Buffer.from(parts, 'hex');
136 } catch (e) {
137 throw (new FingerprintFormatError(fp));
138 }
139 } else {
140 if (hexRE.test(fp)) {
141 hash = Buffer.from(fp, 'hex');
142 } else if (base64RE.test(fp)) {
143 hash = Buffer.from(fp, 'base64');
144 } else {
145 throw (new FingerprintFormatError(fp));
146 }
147
148 switch (hash.length) {
149 case 32:
150 alg = 'sha256';
151 break;
152 case 16:
153 alg = 'md5';
154 break;
155 case 20:
156 alg = 'sha1';
157 break;
158 case 64:
159 alg = 'sha512';
160 break;
161 default:
162 throw (new FingerprintFormatError(fp));
163 }
164
165 /* Plain hex/base64: guess it's probably SPKI unless told. */
166 if (options.hashType === undefined)
167 hashType = 'spki';
168 }
169
170 if (alg === undefined)
171 throw (new FingerprintFormatError(fp));
172
173 if (algs.hashAlgs[alg] === undefined)
174 throw (new InvalidAlgorithmError(alg));
175
176 if (enAlgs !== undefined) {
177 enAlgs = enAlgs.map(function (a) { return a.toLowerCase(); });
178 if (enAlgs.indexOf(alg) === -1)
179 throw (new InvalidAlgorithmError(alg));
180 }
181
182 return (new Fingerprint({
183 algorithm: alg,
184 hash: hash,
185 type: options.type || 'key',
186 hashType: hashType
187 }));
188};
189
190function addColons(s) {
191 /*JSSTYLED*/
192 return (s.replace(/(.{2})(?=.)/g, '$1:'));
193}
194
195function base64Strip(s) {
196 /*JSSTYLED*/
197 return (s.replace(/=*$/, ''));
198}
199
200function sshBase64Format(alg, h) {
201 return (alg.toUpperCase() + ':' + base64Strip(h));
202}
203
204Fingerprint.isFingerprint = function (obj, ver) {
205 return (utils.isCompatible(obj, Fingerprint, ver));
206};
207
208/*
209 * API versions for Fingerprint:
210 * [1,0] -- initial ver
211 * [1,1] -- first tagged ver
212 * [1,2] -- hashType and spki support
213 */
214Fingerprint.prototype._sshpkApiVersion = [1, 2];
215
216Fingerprint._oldVersionDetect = function (obj) {
217 assert.func(obj.toString);
218 assert.func(obj.matches);
219 return ([1, 0]);
220};
Note: See TracBrowser for help on using the repository browser.