Comparing version
@@ -123,2 +123,33 @@ // Copyright 2016 Joyent, Inc. | ||
Certificate.prototype.getExtension = function (keyOrOid) { | ||
assert.string(keyOrOid, 'keyOrOid'); | ||
var ext = this.getExtensions().filter(function (maybeExt) { | ||
if (maybeExt.format === 'x509') | ||
return (maybeExt.oid === keyOrOid); | ||
if (maybeExt.format === 'openssh') | ||
return (maybeExt.name === keyOrOid); | ||
return (false); | ||
})[0]; | ||
return (ext); | ||
}; | ||
Certificate.prototype.getExtensions = function () { | ||
var exts = []; | ||
var x509 = this.signatures.x509; | ||
if (x509 && x509.extras && x509.extras.exts) { | ||
x509.extras.exts.forEach(function (ext) { | ||
ext.format = 'x509'; | ||
exts.push(ext); | ||
}); | ||
} | ||
var openssh = this.signatures.openssh; | ||
if (openssh && openssh.exts) { | ||
openssh.exts.forEach(function (ext) { | ||
ext.format = 'openssh'; | ||
exts.push(ext); | ||
}); | ||
} | ||
return (exts); | ||
}; | ||
Certificate.prototype.isSignedByKey = function (issuerKey) { | ||
@@ -374,4 +405,5 @@ utils.assertCompatible(issuerKey, Key, [1, 2], 'issuerKey'); | ||
* [1,0] -- initial ver | ||
* [1,1] -- openssh format now unpacks extensions | ||
*/ | ||
Certificate.prototype._sshpkApiVersion = [1, 0]; | ||
Certificate.prototype._sshpkApiVersion = [1, 1]; | ||
@@ -378,0 +410,0 @@ Certificate._oldVersionDetect = function (obj) { |
@@ -14,3 +14,3 @@ // Copyright 2017 Joyent, Inc. | ||
var utils = require('./utils'); | ||
var nacl; | ||
var nacl = require('tweetnacl'); | ||
@@ -22,3 +22,5 @@ var Key = require('./key'); | ||
var ecdh, ec, jsbn; | ||
var ecdh = require('ecc-jsbn'); | ||
var ec = require('ecc-jsbn/lib/ec'); | ||
var jsbn = require('jsbn').BigInteger; | ||
@@ -48,9 +50,2 @@ function DiffieHellman(key) { | ||
if (!CRYPTO_HAVE_ECDH) { | ||
if (ecdh === undefined) | ||
ecdh = require('ecc-jsbn'); | ||
if (ec === undefined) | ||
ec = require('ecc-jsbn/lib/ec'); | ||
if (jsbn === undefined) | ||
jsbn = require('jsbn').BigInteger; | ||
this._ecParams = new X9ECParameters(this._curve); | ||
@@ -82,5 +77,2 @@ | ||
} else if (key.type === 'curve25519') { | ||
if (nacl === undefined) | ||
nacl = require('tweetnacl'); | ||
if (this._isPriv) { | ||
@@ -328,5 +320,2 @@ utils.assertCompatible(key, PrivateKey, [1, 5], 'key'); | ||
function generateED25519() { | ||
if (nacl === undefined) | ||
nacl = require('tweetnacl'); | ||
var pair = nacl.sign.keyPair(); | ||
@@ -382,8 +371,2 @@ var priv = Buffer.from(pair.secretKey); | ||
} else { | ||
if (ecdh === undefined) | ||
ecdh = require('ecc-jsbn'); | ||
if (ec === undefined) | ||
ec = require('ecc-jsbn/lib/ec'); | ||
if (jsbn === undefined) | ||
jsbn = require('jsbn').BigInteger; | ||
@@ -390,0 +373,0 @@ var ecParams = new X9ECParameters(curve); |
@@ -8,3 +8,3 @@ // Copyright 2015 Joyent, Inc. | ||
var nacl; | ||
var nacl = require('tweetnacl'); | ||
var stream = require('stream'); | ||
@@ -17,5 +17,2 @@ var util = require('util'); | ||
function Verifier(key, hashAlgo) { | ||
if (nacl === undefined) | ||
nacl = require('tweetnacl'); | ||
if (hashAlgo.toLowerCase() !== 'sha512') | ||
@@ -66,5 +63,2 @@ throw (new Error('ED25519 only supports the use of ' + | ||
function Signer(key, hashAlgo) { | ||
if (nacl === undefined) | ||
nacl = require('tweetnacl'); | ||
if (hashAlgo.toLowerCase() !== 'sha512') | ||
@@ -71,0 +65,0 @@ throw (new Error('ED25519 only supports the use of ' + |
@@ -105,3 +105,3 @@ // Copyright 2015 Joyent, Inc. | ||
var md5RE = /^[a-fA-F0-9]+$/; | ||
if (!md5RE.test(parts)) | ||
if (!md5RE.test(parts) || md5RE.length % 2 !== 0) | ||
throw (new FingerprintFormatError(fp)); | ||
@@ -108,0 +108,0 @@ try { |
@@ -125,4 +125,19 @@ // Copyright 2017 Joyent, Inc. | ||
cert.signatures.openssh.critical = sshbuf.readBuffer(); | ||
cert.signatures.openssh.exts = sshbuf.readBuffer(); | ||
var exts = []; | ||
var extbuf = new SSHBuffer({ buffer: sshbuf.readBuffer() }); | ||
var ext; | ||
while (!extbuf.atEnd()) { | ||
ext = { critical: true }; | ||
ext.name = extbuf.readString(); | ||
ext.data = extbuf.readBuffer(); | ||
exts.push(ext); | ||
} | ||
extbuf = new SSHBuffer({ buffer: sshbuf.readBuffer() }); | ||
while (!extbuf.atEnd()) { | ||
ext = { critical: false }; | ||
ext.name = extbuf.readString(); | ||
ext.data = extbuf.readBuffer(); | ||
exts.push(ext); | ||
} | ||
cert.signatures.openssh.exts = exts; | ||
@@ -282,10 +297,24 @@ /* reserved */ | ||
if (sig.critical === undefined) | ||
sig.critical = Buffer.alloc(0); | ||
buf.writeBuffer(sig.critical); | ||
var exts = sig.exts; | ||
if (exts === undefined) | ||
exts = []; | ||
if (sig.exts === undefined) | ||
sig.exts = Buffer.alloc(0); | ||
buf.writeBuffer(sig.exts); | ||
var extbuf = new SSHBuffer({}); | ||
exts.forEach(function (ext) { | ||
if (ext.critical !== true) | ||
return; | ||
extbuf.writeString(ext.name); | ||
extbuf.writeBuffer(ext.data); | ||
}); | ||
buf.writeBuffer(extbuf.toBuffer()); | ||
extbuf = new SSHBuffer({}); | ||
exts.forEach(function (ext) { | ||
if (ext.critical === true) | ||
return; | ||
extbuf.writeString(ext.name); | ||
extbuf.writeBuffer(ext.data); | ||
}); | ||
buf.writeBuffer(extbuf.toBuffer()); | ||
/* reserved */ | ||
@@ -292,0 +321,0 @@ buf.writeBuffer(Buffer.alloc(0)); |
@@ -245,3 +245,4 @@ // Copyright 2017 Joyent, Inc. | ||
var sig = cert.signatures.x509; | ||
sig.extras.exts = []; | ||
if (!sig.extras.exts) | ||
sig.extras.exts = []; | ||
@@ -248,0 +249,0 @@ var critical; |
@@ -27,5 +27,17 @@ // Copyright 2017 Joyent, Inc. | ||
oids.sn = '2.5.4.4'; | ||
oids.postalCode = '2.5.4.17'; | ||
oids.serialNumber = '2.5.4.5'; | ||
oids.street = '2.5.4.9'; | ||
oids.x500UniqueIdentifier = '2.5.4.45'; | ||
oids.role = '2.5.4.72'; | ||
oids.telephoneNumber = '2.5.4.20'; | ||
oids.description = '2.5.4.13'; | ||
oids.dc = '0.9.2342.19200300.100.1.25'; | ||
oids.uid = '0.9.2342.19200300.100.1.1'; | ||
oids.mail = '0.9.2342.19200300.100.1.3'; | ||
oids.title = '2.5.4.12'; | ||
oids.gn = '2.5.4.42'; | ||
oids.initials = '2.5.4.43'; | ||
oids.pseudonym = '2.5.4.65'; | ||
oids.emailAddress = '1.2.840.113549.1.9.1'; | ||
@@ -117,6 +129,35 @@ var unoids = {}; | ||
return (this.components.map(function (c) { | ||
return (c.name.toUpperCase() + '=' + c.value); | ||
var n = c.name.toUpperCase(); | ||
/*JSSTYLED*/ | ||
n = n.replace(/=/g, '\\='); | ||
var v = c.value; | ||
/*JSSTYLED*/ | ||
v = v.replace(/,/g, '\\,'); | ||
return (n + '=' + v); | ||
}).join(', ')); | ||
}; | ||
Identity.prototype.get = function (name, asArray) { | ||
assert.string(name, 'name'); | ||
var arr = this.componentLookup[name]; | ||
if (arr === undefined || arr.length === 0) | ||
return (undefined); | ||
if (!asArray && arr.length > 1) | ||
throw (new Error('Multiple values for attribute ' + name)); | ||
if (!asArray) | ||
return (arr[0].value); | ||
return (arr.map(function (c) { | ||
return (c.value); | ||
})); | ||
}; | ||
Identity.prototype.toArray = function (idx) { | ||
return (this.components.map(function (c) { | ||
return ({ | ||
name: c.name, | ||
value: c.value | ||
}); | ||
})); | ||
}; | ||
/* | ||
@@ -229,7 +270,37 @@ * These are from X.680 -- PrintableString allowed chars are in section 37.4 | ||
assert.string(dn, 'dn'); | ||
var parts = dn.split(','); | ||
var parts = ['']; | ||
var idx = 0; | ||
var rem = dn; | ||
while (rem.length > 0) { | ||
var m; | ||
/*JSSTYLED*/ | ||
if ((m = /^,/.exec(rem)) !== null) { | ||
parts[++idx] = ''; | ||
rem = rem.slice(m[0].length); | ||
/*JSSTYLED*/ | ||
} else if ((m = /^\\,/.exec(rem)) !== null) { | ||
parts[idx] += ','; | ||
rem = rem.slice(m[0].length); | ||
/*JSSTYLED*/ | ||
} else if ((m = /^\\./.exec(rem)) !== null) { | ||
parts[idx] += m[0]; | ||
rem = rem.slice(m[0].length); | ||
/*JSSTYLED*/ | ||
} else if ((m = /^[^\\,]+/.exec(rem)) !== null) { | ||
parts[idx] += m[0]; | ||
rem = rem.slice(m[0].length); | ||
} else { | ||
throw (new Error('Failed to parse DN')); | ||
} | ||
} | ||
var cmps = parts.map(function (c) { | ||
c = c.trim(); | ||
var eqPos = c.indexOf('='); | ||
var name = c.slice(0, eqPos).toLowerCase(); | ||
while (eqPos > 0 && c.charAt(eqPos - 1) === '\\') | ||
eqPos = c.indexOf('=', eqPos + 1); | ||
if (eqPos === -1) { | ||
throw (new Error('Failed to parse DN')); | ||
} | ||
/*JSSTYLED*/ | ||
var name = c.slice(0, eqPos).toLowerCase().replace(/\\=/g, '='); | ||
var value = c.slice(eqPos + 1); | ||
@@ -241,2 +312,15 @@ return ({ name: name, value: value }); | ||
Identity.fromArray = function (components) { | ||
assert.arrayOfObject(components, 'components'); | ||
components.forEach(function (cmp) { | ||
assert.object(cmp, 'component'); | ||
assert.string(cmp.name, 'component.name'); | ||
if (!Buffer.isBuffer(cmp.value) && | ||
!(typeof (cmp.value) === 'string')) { | ||
throw (new Error('Invalid component value')); | ||
} | ||
}); | ||
return (new Identity({ components: components })); | ||
}; | ||
Identity.parseAsn1 = function (der, top) { | ||
@@ -243,0 +327,0 @@ var components = []; |
@@ -31,2 +31,3 @@ // Copyright 2015 Joyent, Inc. | ||
identityForEmail: Identity.forEmail, | ||
identityFromArray: Identity.fromArray, | ||
@@ -33,0 +34,0 @@ /* errors */ |
@@ -17,11 +17,5 @@ // Copyright 2017 Joyent, Inc. | ||
var generateED25519 = dhe.generateED25519; | ||
var edCompat; | ||
var nacl; | ||
var edCompat = require('./ed-compat'); | ||
var nacl = require('tweetnacl'); | ||
try { | ||
edCompat = require('./ed-compat'); | ||
} catch (e) { | ||
/* Just continue through, and bail out if we try to use it. */ | ||
} | ||
var Key = require('./key'); | ||
@@ -94,5 +88,2 @@ | ||
if (this.type === 'ed25519' && newType === 'curve25519') { | ||
if (nacl === undefined) | ||
nacl = require('tweetnacl'); | ||
priv = this.part.k.data; | ||
@@ -113,5 +104,2 @@ if (priv[0] === 0x00) | ||
} else if (this.type === 'curve25519' && newType === 'ed25519') { | ||
if (nacl === undefined) | ||
nacl = require('tweetnacl'); | ||
priv = this.part.k.data; | ||
@@ -118,0 +106,0 @@ if (priv[0] === 0x00) |
@@ -31,4 +31,5 @@ // Copyright 2015 Joyent, Inc. | ||
var ec, jsbn; | ||
var nacl; | ||
var ec = require('ecc-jsbn/lib/ec'); | ||
var jsbn = require('jsbn').BigInteger; | ||
var nacl = require('tweetnacl'); | ||
@@ -91,3 +92,4 @@ var MAX_CLASS_DEPTH = 3; | ||
'des-ede3-cbc': { key: 7, iv: 8 }, | ||
'aes-128-cbc': { key: 16, iv: 16 } | ||
'aes-128-cbc': { key: 16, iv: 16 }, | ||
'aes-256-cbc': { key: 32, iv: 16 } | ||
}; | ||
@@ -261,11 +263,5 @@ var PKCS5_SALT_LEN = 8; | ||
assert.buffer(x); | ||
try { | ||
var bigInt = require('jsbn').BigInteger; | ||
} catch (e) { | ||
throw (new Error('To load a PKCS#8 format DSA private key, ' + | ||
'the node jsbn library is required.')); | ||
} | ||
g = new bigInt(g); | ||
p = new bigInt(p); | ||
x = new bigInt(x); | ||
g = new jsbn(g); | ||
p = new jsbn(p); | ||
x = new jsbn(x); | ||
var y = g.modPow(x, p); | ||
@@ -279,5 +275,2 @@ var ybuf = bigintToMpBuf(y); | ||
if (nacl === undefined) | ||
nacl = require('tweetnacl'); | ||
var kp = nacl.sign.keyPair.fromSeed(new Uint8Array(k)); | ||
@@ -290,5 +283,2 @@ return (Buffer.from(kp.publicKey)); | ||
if (nacl === undefined) | ||
nacl = require('tweetnacl'); | ||
var kp = nacl.box.keyPair.fromSeed(new Uint8Array(k)); | ||
@@ -301,14 +291,8 @@ return (Buffer.from(kp.publicKey)); | ||
assertCompatible(key, PrivateKey, [1, 1]); | ||
try { | ||
var bigInt = require('jsbn').BigInteger; | ||
} catch (e) { | ||
throw (new Error('To write a PEM private key from ' + | ||
'this source, the node jsbn lib is required.')); | ||
} | ||
var d = new bigInt(key.part.d.data); | ||
var d = new jsbn(key.part.d.data); | ||
var buf; | ||
if (!key.part.dmodp) { | ||
var p = new bigInt(key.part.p.data); | ||
var p = new jsbn(key.part.p.data); | ||
var dmodp = d.mod(p.subtract(1)); | ||
@@ -321,3 +305,3 @@ | ||
if (!key.part.dmodq) { | ||
var q = new bigInt(key.part.q.data); | ||
var q = new jsbn(key.part.q.data); | ||
var dmodq = d.mod(q.subtract(1)); | ||
@@ -334,6 +318,2 @@ | ||
assert.buffer(priv); | ||
if (ec === undefined) | ||
ec = require('ecc-jsbn/lib/ec'); | ||
if (jsbn === undefined) | ||
jsbn = require('jsbn').BigInteger; | ||
var params = algs.curves[curveName]; | ||
@@ -340,0 +320,0 @@ var p = new jsbn(params.p); |
{ | ||
"name": "sshpk", | ||
"version": "1.14.2", | ||
"version": "1.15.0", | ||
"description": "A library for finding and using SSH public keys", | ||
@@ -11,3 +11,3 @@ "main": "lib/index.js", | ||
"type": "git", | ||
"url": "git+https://github.com/arekinath/node-sshpk.git" | ||
"url": "git+https://github.com/joyent/node-sshpk.git" | ||
}, | ||
@@ -47,5 +47,3 @@ "author": "Joyent, Inc", | ||
"getpass": "^0.1.1", | ||
"safer-buffer": "^2.0.2" | ||
}, | ||
"optionalDependencies": { | ||
"safer-buffer": "^2.0.2", | ||
"jsbn": "~0.1.0", | ||
@@ -56,2 +54,4 @@ "tweetnacl": "~0.14.0", | ||
}, | ||
"optionalDependencies": { | ||
}, | ||
"devDependencies": { | ||
@@ -58,0 +58,0 @@ "tape": "^3.5.0", |
@@ -510,2 +510,20 @@ sshpk | ||
### `Certificate#getExtension(nameOrOid)` | ||
Retrieves information about a certificate extension, if present, or returns | ||
`undefined` if not. The string argument `nameOrOid` should be either the OID | ||
(for X509 extensions) or the name (for OpenSSH extensions) of the extension | ||
to retrieve. | ||
The object returned will have the following properties: | ||
* `format` -- String, set to either `'x509'` or `'openssh'` | ||
* `name` or `oid` -- String, only one set based on value of `format` | ||
* `data` -- Buffer, the raw data inside the extension | ||
### `Certificate#getExtensions()` | ||
Returns an Array of all present certificate extensions, in the same manner and | ||
format as `getExtension()`. | ||
### `Certificate#isExpired([when])` | ||
@@ -618,2 +636,40 @@ | ||
### `identityFromArray(arr)` | ||
Constructs an Identity from an array of DN components (see `Identity#toArray()` | ||
for the format). | ||
Parameters | ||
- `arr` -- an Array of Objects, DN components with `name` and `value` | ||
Returns an Identity instance. | ||
Supported attributes in DNs: | ||
| Attribute name | OID | | ||
| -------------- | --- | | ||
| `cn` | `2.5.4.3` | | ||
| `o` | `2.5.4.10` | | ||
| `ou` | `2.5.4.11` | | ||
| `l` | `2.5.4.7` | | ||
| `s` | `2.5.4.8` | | ||
| `c` | `2.5.4.6` | | ||
| `sn` | `2.5.4.4` | | ||
| `postalCode` | `2.5.4.17` | | ||
| `serialNumber` | `2.5.4.5` | | ||
| `street` | `2.5.4.9` | | ||
| `x500UniqueIdentifier` | `2.5.4.45` | | ||
| `role` | `2.5.4.72` | | ||
| `telephoneNumber` | `2.5.4.20` | | ||
| `description` | `2.5.4.13` | | ||
| `dc` | `0.9.2342.19200300.100.1.25` | | ||
| `uid` | `0.9.2342.19200300.100.1.1` | | ||
| `mail` | `0.9.2342.19200300.100.1.3` | | ||
| `title` | `2.5.4.12` | | ||
| `gn` | `2.5.4.42` | | ||
| `initials` | `2.5.4.43` | | ||
| `pseudonym` | `2.5.4.65` | | ||
### `Identity#toString()` | ||
@@ -636,4 +692,36 @@ | ||
The value of the first `CN=` in the DN, if any. | ||
The value of the first `CN=` in the DN, if any. It's probably better to use | ||
the `#get()` method instead of this property. | ||
### `Identity#get(name[, asArray])` | ||
Returns the value of a named attribute in the Identity DN. If there is no | ||
attribute of the given name, returns `undefined`. If multiple components | ||
of the DN contain an attribute of this name, an exception is thrown unless | ||
the `asArray` argument is given as `true` -- then they will be returned as | ||
an Array in the same order they appear in the DN. | ||
Parameters | ||
- `name` -- a String | ||
- `asArray` -- an optional Boolean | ||
### `Identity#toArray()` | ||
Returns the Identity as an Array of DN component objects. This looks like: | ||
```js | ||
[ { | ||
"name": "cn", | ||
"value": "Joe Bloggs" | ||
}, | ||
{ | ||
"name": "o", | ||
"value": "Organisation Ltd" | ||
} ] | ||
``` | ||
Each object has a `name` and a `value` property. The returned objects may be | ||
safely modified. | ||
Errors | ||
@@ -640,0 +728,0 @@ ------ |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
214130
2.42%5525
1.77%787
12.59%+ Added
+ Added
+ Added
+ Added