Wed Mar 14 04:56:40 CET 2018

This commit is contained in:
c9jenkinsv3 2018-03-14 04:56:40 +01:00
parent a8b05daac7
commit 6bbc0c6a4a
35 changed files with 881 additions and 218 deletions

View File

@ -47605,166 +47605,205 @@ define("plugins/c9.ide.clipboard/clipboard",[], function(require, exports, modul
define("plugins/c9.ide.save/autosave",[], function(require, exports, module) {
main.consumes = [
"Plugin", "c9", "ui", "layout", "tooltip",
"anims", "menus", "tabManager", "save",
"preferences.experimental"
"Plugin", "c9", "settings", "tabManager", "preferences.experimental", "save", "apf"
];
main.provides = ["autosave"];
return main;
function main(options, imports, register) {
var c9 = imports.c9;
var Plugin = imports.Plugin;
var apf = imports.apf;
var save = imports.save;
var tooltip = imports.tooltip;
var tabs = imports.tabManager;
var experimental = imports["preferences.experimental"];
var prefs = imports["preferences.experimental"];
var Plugin = imports.Plugin;
var settings = imports.settings;
var lang = require("ace/lib/lang");
var plugin = new Plugin("Ajax.org", main.consumes);
var INTERVAL = 60000;
var CHANGE_TIMEOUT = 500;
var CHANGE_TIMEOUT = options.changeTimeout || 1000;
var SLOW_CHANGE_TIMEOUT = options.slowChangeTimeout || 30000;
var SLOW_SAVE_THRESHOLD = 100 * 1024; // 100KB
var docChangeTimeout = null;
var btnSave, autosave = true, saveInterval;
var enabled = options.testing
|| experimental.addExperiment("autosave", false, "Files/Auto-Save");
var docChangeTimeout;
var lastSaveTime = 0;
var sessionId;
var autosave;
var saveWhenIdle;
var loaded = false;
function load() {
if (loaded || !enabled) return false;
loaded = true;
c9.on("stateChange", function(e) {
if (e.state & c9.STORAGE && !(e.last & c9.STORAGE))
check();
}, plugin);
save.getElement("btnSave", function(btn) {
btnSave = btn;
transformButton();
});
tabs.on("tabCreate", function(e) {
var tab = e.tab;
tab.document.undoManager.on("change", function(e) {
if (!autosave || !tab.path)
return;
clearTimeout(docChangeTimeout);
docChangeTimeout = setTimeout(function() {
saveTab(tab);
}, tab.document.meta.$slowSave
? SLOW_CHANGE_TIMEOUT
: CHANGE_TIMEOUT);
}, plugin);
}, plugin);
tabs.on("tabDestroy", function(e) {
if (!e.tab.path)
return;
if (tabs.getTabs().length == 1)
btnSave.hide();
saveTab(e.tab);
}, plugin);
save.on("beforeWarn", function(e) {
if (autosave && !e.tab.document.meta.newfile) {
saveTab(e.tab);
return false;
prefs.add({
"File": {
position: 150,
"Save": {
position: 100,
"Auto-Save Files": {
type: "dropdown",
position: 100,
path: "user/general/@autosave",
width: 130,
items: [
{ caption: "Off", value: false },
{ caption: "On Focus Change", value: "onFocusChange" },
{ caption: "After Delay", value: "afterDelay" },
],
}
}
}
}, plugin);
settings.setDefaults("user/general", [["autosave", false]]);
settings.on("read", onSettingChange, plugin);
settings.on("user/general", onSettingChange, plugin);
save.on("beforeWarn", function(e) {
if (autosave && saveTab(e.tab))
return false;
}, plugin);
}
function transformButton() {
if (!btnSave) return;
if (btnSave.autosave === autosave) return;
function onSettingChange() {
autosave = settings.get("user/general/@autosave");
if (autosave == "off" || autosave == "false")
autosave = false;
if (autosave) {
btnSave.setAttribute("caption", "");
btnSave.setAttribute("margin", "0 20");
btnSave.removeAttribute("tooltip");
btnSave.removeAttribute("command");
apf.setStyleClass(btnSave.$ext, "btnSave");
tooltip.add(btnSave, {
message: "Changes to your file are automatically saved.<br />\
View all your changes through <a href='javascript:void(0)' \
onclick='require(\"ext/revisions/revisions\").toggle();' \
class='revisionsInfoLink'>the Revision History pane</a>. \
Rollback to a previous state, or make comparisons.",
width: "250px",
hideonclick: true
}, plugin);
}
else {
}
btnSave.autosave = autosave;
disable();
if (autosave == "afterDelay")
enableDelay();
if (autosave)
enable();
}
function check() {
if (!autosave) return;
var pages = tabs.getTabs();
for (var tab, i = 0, l = pages.length; i < l; i++) {
if ((tab = pages[i]).document.changed && tab.path)
function enableDelay() {
saveWhenIdle = lang.delayedCall(function() {
var tab = tabs.focussedTab;
var ace = tab && tab.editor && tab.editor.ace;
if (ace && ace.session && sessionId == ace.session.id) {
saveTab(tab);
}
});
}
function enable() {
apf.on("movefocus", scheduleCheck);
tabs.on("tabAfterActivate", scheduleCheck, plugin);
if (saveWhenIdle)
tabs.on("focusSync", attachToTab, plugin);
window.addEventListener("blur", scheduleCheck);
}
function disable() {
sessionId = null;
if (saveWhenIdle) {
saveWhenIdle.cancel();
saveWhenIdle = null;
}
if (docChangeTimeout) {
clearTimeout(docChangeTimeout);
docChangeTimeout = null;
}
apf.off("movefocus", scheduleCheck);
tabs.off("tabAfterActivate", scheduleCheck);
tabs.off("focusSync", attachToTab);
window.removeEventListener("blur", scheduleCheck);
}
function attachToTab(e) {
var ace = e.tab && e.tab.editor && e.tab.editor.ace;
if (ace)
ace.on("beforeEndOperation", beforeEndOperation);
}
function beforeEndOperation(e, ace) {
if (!saveWhenIdle)
return ace.off("beforeEndOperation", beforeEndOperation);
if (!ace.isFocused() && !options.ignoreFocusForTesting)
return;
sessionId = ace.session.id;
if (sessionId && ace.curOp.docChanged && ace.curOp.command.name) {
var timeout = Math.min(Math.max(CHANGE_TIMEOUT, lastSaveTime || 0), SLOW_CHANGE_TIMEOUT);
saveWhenIdle.delay(timeout);
}
}
function scheduleCheck(e) {
if (docChangeTimeout)
return;
var tab;
var fromElement = e.fromElement;
var toElement = e.toElement;
if (e.type == "blur") {
tab = tabs.focussedTab;
}
else if (fromElement) {
var fakePage = fromElement.$fake;
if (toElement && (toElement == fakePage || fromElement == toElement.$fake)) {
fakePage = fromElement.$prevFake || toElement.$prevFake;
if (fakePage)
return;
}
tab = fromElement.cloud9tab || fakePage && fakePage.cloud9tab;
if (!tab || !tab.path)
return;
while (toElement) {
if (/window|menu|item/.test(toElement.localName))
return;
toElement = toElement.parentNode;
}
}
else if (e.lastTab) {
tab = e.lastTab;
}
if (!tab || !tab.path)
return;
docChangeTimeout = setTimeout(function() {
docChangeTimeout = null;
var activeElement = apf.document.activeElement;
var nodeName = activeElement && activeElement.localName;
if (nodeName === "page" && tabs.focussedTab && tabs.focussedTab.path === tab.path)
return;
saveTab(tab);
});
}
function saveTab(tab, force) {
if (!autosave) return;
if (!c9.has(c9.STORAGE)) {
save.setSavingState(tab, "offline");
return;
}
var doc;
if (!force && (!tab.path
|| !(doc = tab.document).changed
|| doc.meta.newfile
|| doc.meta.nofs
|| doc.meta.error
|| doc.meta.$saving))
|| doc.meta.$saving
|| doc.meta.preview
|| !doc.hasValue()))
return;
var value = doc.value;
var slow = value.length > SLOW_SAVE_THRESHOLD;
if (slow && !doc.meta.$slowSave) {
doc.meta.$slowSave = true;
if (!c9.has(c9.STORAGE)) {
save.setSavingState(tab, "offline");
return;
}
doc.meta.$slowSave = slow;
var t = Date.now();
save.save(tab, {
silentsave: true,
timeout: 1,
value: value
}, function() {});
noUi: true,
}, function() {
lastSaveTime = t - Date.now();
});
return true;
}
plugin.on("load", function() {
load();
});
plugin.on("enable", function() {
autosave = true;
transformButton();
});
plugin.on("disable", function() {
autosave = false;
transformButton();
});
plugin.on("unload", function() {
if (saveInterval)
clearInterval(saveInterval);
loaded = false;
disable();
autosave = false;
});
plugin.freezePublicAPI({ });
@ -48278,7 +48317,7 @@ define("plugins/c9.ide.save/save",[], function(require, exports, module) {
doc.meta.$saveBuffer = true;
}
setSavingState(tab, "saving");
setSavingState(tab, "saving", null, options.noUi);
var bookmark = doc.undoManager.position;
var loadStartT = Date.now();
@ -48316,7 +48355,7 @@ define("plugins/c9.ide.save/save",[], function(require, exports, module) {
if (options.path)
tab.path = options.path;
setSavingState(tab, "saved", options.timeout);
setSavingState(tab, "saved", options.timeout, options.noUi);
settings.save();
logger.log("Successfully saved " + path);
}
@ -48403,7 +48442,7 @@ define("plugins/c9.ide.save/save",[], function(require, exports, module) {
}
var stateTimer = null, pageTimers = {};
function setSavingState(tab, state, timeout) {
function setSavingState(tab, state, timeout, silent) {
clearTimeout(stateTimer);
clearTimeout(pageTimers[tab.name]);
@ -48416,6 +48455,12 @@ define("plugins/c9.ide.save/save",[], function(require, exports, module) {
else
delete doc.meta.$saving;
if (!silent)
updateSavingUi();
emit("tabSavingState", { tab: tab });
}
function updateSavingUi(tab, state, timeout) {
if (state == "saving") {
btnSave.show();
@ -48472,7 +48517,6 @@ define("plugins/c9.ide.save/save",[], function(require, exports, module) {
btnSave.setCaption("Not saved");
tab.classList.add("error");
}
emit("tabSavingState", { tab: tab });
}
plugin.on("load", function() {
@ -115300,6 +115344,7 @@ apf.page = function(struct, tagName) {
if (this.relPage) {
this.relPage.$ext.style.display = "";
this.parentNode.$setStyleClass(this.relPage.$ext, "curpage");
this.relPage.$prevFake = this.relPage.$fake;
this.relPage.$fake = this;
@ -115500,6 +115545,7 @@ apf.page = function(struct, tagName) {
if (page && page.type == _self.id) {
page.relPage = _self;
if (page.$active) {
_self.$prevFake = _self.$fake;
_self.$fake = page;
page.$activate();
}
@ -124010,16 +124056,9 @@ apf.window = function(){
(apf.window.activeElement = amlNode).focus(true, e);
this.$settingFocus = null;
apf.dispatchEvent("movefocus", {
toElement: amlNode
});
apf.dispatchEvent("movefocus", e);
};
this.$blur = function(amlNode) {
@ -152332,7 +152371,7 @@ define("plugins/c9.ide.editors/tabmanager",[], function(require, module, exports
if (!loaded || tab.document.meta.preview)
return;
var lastTab = focussedTab;
var lastTab = e.lastTab || focussedTab;
if (!focussedTab || focussedTab.pane == tab.pane && focussedTab != tab)
focusTab(tab, true, true);

View File

@ -36,7 +36,7 @@
"homepage": "https://github.com/isaacs/inherits#readme",
"_id": "inherits@2.0.3",
"_shasum": "633c2c83e3da42a502f52466022480f4208261de",
"_from": "inherits@>=2.0.1 <2.1.0",
"_from": "inherits@>=2.0.0 <3.0.0",
"_npmVersion": "3.10.7",
"_nodeVersion": "6.5.0",
"_npmUser": {

View File

@ -40,7 +40,6 @@
"process"
]
},
"gitHead": "39015d544d4c00c7899fea4c95c2e5bc2720e68e",
"contributors": [
{
"name": "List of Tern contributors. Updated before every release."
@ -241,6 +240,7 @@
"name": "vheon"
}
],
"gitHead": "39015d544d4c00c7899fea4c95c2e5bc2720e68e",
"readme": "# Tern\n\n[![Build Status](https://secure.travis-ci.org/ternjs/tern.png)](http://travis-ci.org/ternjs/tern)\n[![NPM version](https://img.shields.io/npm/v/tern.svg)](https://www.npmjs.org/package/tern) \n[Funding status: ![maintainer happiness](https://marijnhaverbeke.nl/fund/status_s.png?again)](https://marijnhaverbeke.nl/fund/)\n\nThis is [Tern][1]. Tern is a stand-alone, editor-independent\nJavaScript analyzer that can be used to improve the JavaScript\nintegration of existing editors.\n\nThanks to a group of generous [crowd funders][2], Tern is open-source\nsoftware, under an MIT license.\n\nThere are currently plugins available for [Emacs][emacs] (and Emacs\n[company-mode][cmode]), [Vim][vim], [Sublime Text][st], [Eclipse (and general Java API)][ec],\n[Light Table][lt], [Atom][atom] and [gedit][gedit], and built-in support in\n[Brackets][brackets], [Edge Code][edge_code], and [CodeLite](http://codelite.org/).\n\nFor further documentation, see the [project page][1] and the\n[manual][3]. To report issues, use the\n[issue tracker](https://github.com/ternjs/tern/issues). For questions\nand documentation, see the\n[discussion forum](https://discuss.ternjs.net).\n\n[1]: http://ternjs.net\n[2]: http://www.indiegogo.com/projects/tern-intelligent-javascript-editing\n[3]: http://ternjs.net/doc/manual.html\n\n[emacs]: http://ternjs.net/doc/manual.html#emacs\n[ec]: https://github.com/angelozerr/tern.java\n[vim]: https://github.com/ternjs/tern_for_vim\n[st]: https://github.com/ternjs/tern_for_sublime\n[lt]: https://github.com/mortalapeman/LT-TernJS\n[atom]: https://atom.io/packages/atom-ternjs\n[gedit]: https://github.com/Swatinem/tern_for_gedit\n[brackets]: http://brackets.io\n[edge_code]: http://html.adobe.com/edge/code\n[cmode]: https://github.com/proofit404/company-tern\n",
"readmeFilename": "README.md",
"bugs": {
@ -248,7 +248,7 @@
},
"homepage": "https://github.com/ternjs/tern#readme",
"_id": "tern@0.16.1",
"_shasum": "c89ccea2e756f052a4b28e08f67277d846983496",
"_shasum": "e899f56ba505124cce3310ceb8414d5f1583ab38",
"_from": "git+https://github.com/cloud9ide/tern.git#39015d544d4c00c7899fea4c95c2e5bc2720e68e",
"_resolved": "git+https://github.com/cloud9ide/tern.git#39015d544d4c00c7899fea4c95c2e5bc2720e68e"
}

View File

@ -20,7 +20,7 @@
"readme": "# tern_from_ts\n\nTern signatures extracted from typescript signatures.\n\nLicense: MIT\n\nSee also https://github.com/marijnh/tern and https://github.com/borisyankov/DefinitelyTyped\n",
"readmeFilename": "README.md",
"_id": "tern_from_ts@0.0.1",
"_shasum": "82c5150f58103432eaaa6aadd3ecfad8331aad56",
"_shasum": "1fed17d49d8aecdfbd1bfe4a05256105910b00b2",
"_from": "git+https://github.com/cloud9ide/tern_from_ts.git#66df507986bbdd63f3bc4f0c53edb39169ce4f1c",
"_resolved": "git+https://github.com/cloud9ide/tern_from_ts.git#66df507986bbdd63f3bc4f0c53edb39169ce4f1c"
}

File diff suppressed because one or more lines are too long

View File

@ -58,5 +58,6 @@
"tmp": "tmp/inherits-2.0.3.tgz_1473295776489_0.08142363070510328"
},
"directories": {},
"_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz"
"_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"readme": "ERROR: No README data found!"
}

View File

@ -62,6 +62,5 @@
],
"directories": {},
"_shasum": "857fcabfc3397d2625b8228262e86aa7a011b05d",
"_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"readme": "ERROR: No README data found!"
"_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz"
}

View File

@ -55,6 +55,5 @@
}
],
"directories": {},
"_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"readme": "ERROR: No README data found!"
"_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz"
}

View File

@ -1,7 +1,7 @@
#!/usr/bin/env node
// -*- mode: js -*-
// vim: set filetype=javascript :
// Copyright 2015 Joyent, Inc. All rights reserved.
// Copyright 2015 Joyent, Inc. All rights reserved.
var dashdash = require('dashdash');
var sshpk = require('../lib/index');
@ -76,11 +76,12 @@ if (require.main === module) {
console.error('sshpk-conv: converts between SSH key formats\n');
console.error(help);
console.error('\navailable formats:');
console.error(' - pem, pkcs1 eg id_rsa');
console.error(' - ssh eg id_rsa.pub');
console.error(' - pkcs8 format you want for openssl');
console.error(' - openssh like output of ssh-keygen -o');
console.error(' - rfc4253 raw OpenSSH wire format');
console.error(' - pem, pkcs1 eg id_rsa');
console.error(' - ssh eg id_rsa.pub');
console.error(' - pkcs8 format you want for openssl');
console.error(' - openssh like output of ssh-keygen -o');
console.error(' - rfc4253 raw OpenSSH wire format');
console.error(' - dnssec dnssec-keygen format');
process.exit(1);
}

View File

@ -14,9 +14,8 @@ var algInfo = {
sizePart: 'Q'
},
'ed25519': {
parts: ['R'],
normalize: false,
sizePart: 'R'
parts: ['A'],
sizePart: 'A'
}
};
algInfo['curve25519'] = algInfo['ed25519'];
@ -32,8 +31,7 @@ var algPrivInfo = {
parts: ['curve', 'Q', 'd']
},
'ed25519': {
parts: ['R', 'r'],
normalize: false
parts: ['A', 'k']
}
};
algPrivInfo['curve25519'] = algPrivInfo['ed25519'];

View File

@ -79,7 +79,8 @@ function DiffieHellman(key) {
nacl = require('tweetnacl');
if (this._isPriv) {
this._priv = key.part.r.data;
utils.assertCompatible(key, PrivateKey, [1, 5], 'key');
this._priv = key.part.k.data;
}
} else {
@ -143,7 +144,10 @@ DiffieHellman.prototype.setKey = function (pk) {
}
} else if (pk.type === 'curve25519') {
this._priv = pk.part.r.data;
var k = pk.part.k;
if (!pk.part.k)
k = pk.part.r;
this._priv = k.data;
if (this._priv[0] === 0x00)
this._priv = this._priv.slice(1);
this._priv = this._priv.slice(0, 32);
@ -175,13 +179,12 @@ DiffieHellman.prototype.computeSecret = function (otherpk) {
}
} else if (this._algo === 'curve25519') {
pub = otherpk.part.R.data;
pub = otherpk.part.A.data;
while (pub[0] === 0x00 && pub.length > 32)
pub = pub.slice(1);
var priv = this._priv;
assert.strictEqual(pub.length, 32);
assert.strictEqual(this._priv.length, 64);
var priv = this._priv.slice(0, 32);
assert.strictEqual(priv.length, 32);
var secret = nacl.box.before(new Uint8Array(pub),
new Uint8Array(priv));
@ -261,8 +264,8 @@ DiffieHellman.prototype.generateKey = function () {
assert.strictEqual(priv.length, 64);
assert.strictEqual(pub.length, 32);
parts.push({name: 'R', data: pub});
parts.push({name: 'r', data: priv});
parts.push({name: 'A', data: pub});
parts.push({name: 'k', data: priv});
this._key = new PrivateKey({
type: 'curve25519',
parts: parts
@ -327,8 +330,8 @@ function generateED25519() {
assert.strictEqual(pub.length, 32);
var parts = [];
parts.push({name: 'R', data: pub});
parts.push({name: 'r', data: priv});
parts.push({name: 'A', data: pub});
parts.push({name: 'k', data: priv.slice(0, 32)});
var key = new PrivateKey({
type: 'ed25519',
parts: parts
@ -369,7 +372,6 @@ function generateECDSA(curve) {
parts: parts
});
return (key);
} else {
if (ecdh === undefined)
ecdh = require('ecc-jsbn');

View File

@ -56,7 +56,7 @@ Verifier.prototype.verify = function (signature, fmt) {
return (nacl.sign.detached.verify(
new Uint8Array(Buffer.concat(this.chunks)),
new Uint8Array(sig),
new Uint8Array(this.key.part.R.data)));
new Uint8Array(this.key.part.A.data)));
};
function Signer(key, hashAlgo) {
@ -88,7 +88,8 @@ Signer.prototype.update = function (chunk) {
Signer.prototype.sign = function () {
var sig = nacl.sign.detached(
new Uint8Array(Buffer.concat(this.chunks)),
new Uint8Array(this.key.part.r.data));
new Uint8Array(Buffer.concat([
this.key.part.k.data, this.key.part.A.data])));
var sigBuf = new Buffer(sig);
var sigObj = Signature.parse(sigBuf, 'ed25519', 'raw');
sigObj.hashAlgorithm = 'sha512';

View File

@ -13,6 +13,9 @@ var PrivateKey = require('../private-key');
var pem = require('./pem');
var ssh = require('./ssh');
var rfc4253 = require('./rfc4253');
var dnssec = require('./dnssec');
var DNSSEC_PRIVKEY_HEADER_PREFIX = 'Private-key-format: v1';
function read(buf, options) {
if (typeof (buf) === 'string') {
@ -22,6 +25,8 @@ function read(buf, options) {
return (ssh.read(buf, options));
if (buf.match(/^\s*ecdsa-/))
return (ssh.read(buf, options));
if (findDNSSECHeader(buf))
return (dnssec.read(buf, options));
buf = new Buffer(buf, 'binary');
} else {
assert.buffer(buf);
@ -29,6 +34,8 @@ function read(buf, options) {
return (pem.read(buf, options));
if (findSSHHeader(buf))
return (ssh.read(buf, options));
if (findDNSSECHeader(buf))
return (dnssec.read(buf, options));
}
if (buf.readUInt32BE(0) < buf.length)
return (rfc4253.read(buf, options));
@ -68,6 +75,32 @@ function findPEMHeader(buf) {
return (true);
}
function findDNSSECHeader(buf) {
// private case first
if (buf.length <= DNSSEC_PRIVKEY_HEADER_PREFIX.length)
return (false);
var headerCheck = buf.slice(0, DNSSEC_PRIVKEY_HEADER_PREFIX.length);
if (headerCheck.toString('ascii') === DNSSEC_PRIVKEY_HEADER_PREFIX)
return (true);
// public-key RFC3110 ?
// 'domain.com. IN KEY ...' or 'domain.com. IN DNSKEY ...'
// skip any comment-lines
if (typeof (buf) !== 'string') {
buf = buf.toString('ascii');
}
var lines = buf.split('\n');
var line = 0;
/* JSSTYLED */
while (lines[line].match(/^\;/))
line++;
if (lines[line].toString('ascii').match(/\. IN KEY /))
return (true);
if (lines[line].toString('ascii').match(/\. IN DNSKEY /))
return (true);
return (false);
}
function write(key, options) {
throw (new Error('"auto" format cannot be used for writing'));
}

View File

@ -0,0 +1,286 @@
// Copyright 2017 Joyent, Inc.
module.exports = {
read: read,
write: write
};
var assert = require('assert-plus');
var Key = require('../key');
var PrivateKey = require('../private-key');
var utils = require('../utils');
var SSHBuffer = require('../ssh-buffer');
var Dhe = require('../dhe');
var supportedAlgos = {
'rsa-sha1' : 5,
'rsa-sha256' : 8,
'rsa-sha512' : 10,
'ecdsa-p256-sha256' : 13,
'ecdsa-p384-sha384' : 14
/*
* ed25519 is hypothetically supported with id 15
* but the common tools available don't appear to be
* capable of generating/using ed25519 keys
*/
};
var supportedAlgosById = {};
Object.keys(supportedAlgos).forEach(function (k) {
supportedAlgosById[supportedAlgos[k]] = k.toUpperCase();
});
function read(buf, options) {
if (typeof (buf) !== 'string') {
assert.buffer(buf, 'buf');
buf = buf.toString('ascii');
}
var lines = buf.split('\n');
if (lines[0].match(/^Private-key-format\: v1/)) {
var algElems = lines[1].split(' ');
var algoNum = parseInt(algElems[1], 10);
var algoName = algElems[2];
if (!supportedAlgosById[algoNum])
throw (new Error('Unsupported algorithm: ' + algoName));
return (readDNSSECPrivateKey(algoNum, lines.slice(2)));
}
// skip any comment-lines
var line = 0;
/* JSSTYLED */
while (lines[line].match(/^\;/))
line++;
// we should now have *one single* line left with our KEY on it.
if ((lines[line].match(/\. IN KEY /) ||
lines[line].match(/\. IN DNSKEY /)) && lines[line+1].length === 0) {
return (readRFC3110(lines[line]));
}
throw (new Error('Cannot parse dnssec key'));
}
function readRFC3110(keyString) {
var elems = keyString.split(' ');
//unused var flags = parseInt(elems[3], 10);
//unused var protocol = parseInt(elems[4], 10);
var algorithm = parseInt(elems[5], 10);
if (!supportedAlgosById[algorithm])
throw (new Error('Unsupported algorithm: ' + algorithm));
var base64key = elems.slice(6, elems.length).join();
var keyBuffer = new Buffer(base64key, 'base64');
if (supportedAlgosById[algorithm].match(/^RSA-/)) {
// join the rest of the body into a single base64-blob
var publicExponentLen = keyBuffer.readUInt8(0);
if (publicExponentLen != 3 && publicExponentLen != 1)
throw (new Error('Cannot parse dnssec key: ' +
'unsupported exponent length'));
var publicExponent = keyBuffer.slice(1, publicExponentLen+1);
publicExponent = utils.mpNormalize(publicExponent);
var modulus = keyBuffer.slice(1+publicExponentLen);
modulus = utils.mpNormalize(modulus);
// now, make the key
var rsaKey = {
type: 'rsa',
parts: []
};
rsaKey.parts.push({ name: 'e', data: publicExponent});
rsaKey.parts.push({ name: 'n', data: modulus});
return (new Key(rsaKey));
}
if (supportedAlgosById[algorithm] === 'ECDSA-P384-SHA384' ||
supportedAlgosById[algorithm] === 'ECDSA-P256-SHA256') {
var curve = 'nistp384';
var size = 384;
if (supportedAlgosById[algorithm].match(/^ECDSA-P256-SHA256/)) {
curve = 'nistp256';
size = 256;
}
var ecdsaKey = {
type: 'ecdsa',
curve: curve,
size: size,
parts: [
{name: 'curve', data: new Buffer(curve) },
{name: 'Q', data: utils.ecNormalize(keyBuffer) }
]
};
return (new Key(ecdsaKey));
}
throw (new Error('Unsupported algorithm: ' +
supportedAlgosById[algorithm]));
}
function elementToBuf(e) {
return (new Buffer(e.split(' ')[1], 'base64'));
}
function readDNSSECRSAPrivateKey(elements) {
var rsaParams = {};
elements.forEach(function (element) {
if (element.split(' ')[0] === 'Modulus:')
rsaParams['n'] = elementToBuf(element);
else if (element.split(' ')[0] === 'PublicExponent:')
rsaParams['e'] = elementToBuf(element);
else if (element.split(' ')[0] === 'PrivateExponent:')
rsaParams['d'] = elementToBuf(element);
else if (element.split(' ')[0] === 'Prime1:')
rsaParams['p'] = elementToBuf(element);
else if (element.split(' ')[0] === 'Prime2:')
rsaParams['q'] = elementToBuf(element);
else if (element.split(' ')[0] === 'Exponent1:')
rsaParams['dmodp'] = elementToBuf(element);
else if (element.split(' ')[0] === 'Exponent2:')
rsaParams['dmodq'] = elementToBuf(element);
else if (element.split(' ')[0] === 'Coefficient:')
rsaParams['iqmp'] = elementToBuf(element);
});
// now, make the key
var key = {
type: 'rsa',
parts: [
{ name: 'e', data: utils.mpNormalize(rsaParams['e'])},
{ name: 'n', data: utils.mpNormalize(rsaParams['n'])},
{ name: 'd', data: utils.mpNormalize(rsaParams['d'])},
{ name: 'p', data: utils.mpNormalize(rsaParams['p'])},
{ name: 'q', data: utils.mpNormalize(rsaParams['q'])},
{ name: 'dmodp',
data: utils.mpNormalize(rsaParams['dmodp'])},
{ name: 'dmodq',
data: utils.mpNormalize(rsaParams['dmodq'])},
{ name: 'iqmp',
data: utils.mpNormalize(rsaParams['iqmp'])}
]
};
return (new PrivateKey(key));
}
function readDNSSECPrivateKey(alg, elements) {
if (supportedAlgosById[alg].match(/^RSA-/)) {
return (readDNSSECRSAPrivateKey(elements));
}
if (supportedAlgosById[alg] === 'ECDSA-P384-SHA384' ||
supportedAlgosById[alg] === 'ECDSA-P256-SHA256') {
var d = new Buffer(elements[0].split(' ')[1], 'base64');
var curve = 'nistp384';
var size = 384;
if (supportedAlgosById[alg] === 'ECDSA-P256-SHA256') {
curve = 'nistp256';
size = 256;
}
// DNSSEC generates the public-key on the fly (go calculate it)
var publicKey = utils.publicFromPrivateECDSA(curve, d);
var Q = publicKey.part['Q'].data;
var ecdsaKey = {
type: 'ecdsa',
curve: curve,
size: size,
parts: [
{name: 'curve', data: new Buffer(curve) },
{name: 'd', data: d },
{name: 'Q', data: Q }
]
};
return (new PrivateKey(ecdsaKey));
}
throw (new Error('Unsupported algorithm: ' + supportedAlgosById[alg]));
}
function dnssecTimestamp(date) {
var year = date.getFullYear() + ''; //stringify
var month = (date.getMonth() + 1);
var timestampStr = year + month + date.getUTCDate();
timestampStr += '' + date.getUTCHours() + date.getUTCMinutes();
timestampStr += date.getUTCSeconds();
return (timestampStr);
}
function rsaAlgFromOptions(opts) {
if (!opts || !opts.hashAlgo || opts.hashAlgo === 'sha1')
return ('5 (RSASHA1)');
else if (opts.hashAlgo === 'sha256')
return ('8 (RSASHA256)');
else if (opts.hashAlgo === 'sha512')
return ('10 (RSASHA512)');
else
throw (new Error('Unknown or unsupported hash: ' +
opts.hashAlgo));
}
function writeRSA(key, options) {
// if we're missing parts, add them.
if (!key.part.dmodp || !key.part.dmodq) {
utils.addRSAMissing(key);
}
var out = '';
out += 'Private-key-format: v1.3\n';
out += 'Algorithm: ' + rsaAlgFromOptions(options) + '\n';
var n = utils.mpDenormalize(key.part['n'].data);
out += 'Modulus: ' + n.toString('base64') + '\n';
var e = utils.mpDenormalize(key.part['e'].data);
out += 'PublicExponent: ' + e.toString('base64') + '\n';
var d = utils.mpDenormalize(key.part['d'].data);
out += 'PrivateExponent: ' + d.toString('base64') + '\n';
var p = utils.mpDenormalize(key.part['p'].data);
out += 'Prime1: ' + p.toString('base64') + '\n';
var q = utils.mpDenormalize(key.part['q'].data);
out += 'Prime2: ' + q.toString('base64') + '\n';
var dmodp = utils.mpDenormalize(key.part['dmodp'].data);
out += 'Exponent1: ' + dmodp.toString('base64') + '\n';
var dmodq = utils.mpDenormalize(key.part['dmodq'].data);
out += 'Exponent2: ' + dmodq.toString('base64') + '\n';
var iqmp = utils.mpDenormalize(key.part['iqmp'].data);
out += 'Coefficient: ' + iqmp.toString('base64') + '\n';
// Assume that we're valid as-of now
var timestamp = new Date();
out += 'Created: ' + dnssecTimestamp(timestamp) + '\n';
out += 'Publish: ' + dnssecTimestamp(timestamp) + '\n';
out += 'Activate: ' + dnssecTimestamp(timestamp) + '\n';
return (new Buffer(out, 'ascii'));
}
function writeECDSA(key, options) {
var out = '';
out += 'Private-key-format: v1.3\n';
if (key.curve === 'nistp256') {
out += 'Algorithm: 13 (ECDSAP256SHA256)\n';
} else if (key.curve === 'nistp384') {
out += 'Algorithm: 14 (ECDSAP384SHA384)\n';
} else {
throw (new Error('Unsupported curve'));
}
var base64Key = key.part['d'].data.toString('base64');
out += 'PrivateKey: ' + base64Key + '\n';
// Assume that we're valid as-of now
var timestamp = new Date();
out += 'Created: ' + dnssecTimestamp(timestamp) + '\n';
out += 'Publish: ' + dnssecTimestamp(timestamp) + '\n';
out += 'Activate: ' + dnssecTimestamp(timestamp) + '\n';
return (new Buffer(out, 'ascii'));
}
function write(key, options) {
if (PrivateKey.isPrivateKey(key)) {
if (key.type === 'rsa') {
return (writeRSA(key, options));
} else if (key.type === 'ecdsa') {
return (writeECDSA(key, options));
} else {
throw (new Error('Unsupported algorithm: ' + key.type));
}
} else if (Key.isKey(key)) {
/*
* RFC3110 requires a keyname, and a keytype, which we
* don't really have a mechanism for specifying such
* additional metadata.
*/
throw (new Error('Format "dnssec" only supports ' +
'writing private keys'));
} else {
throw (new Error('key is not a Key or PrivateKey'));
}
}

View File

@ -34,11 +34,11 @@ function read(buf, options, forceType) {
var lines = buf.trim().split('\n');
var m = lines[0].match(/*JSSTYLED*/
/[-]+[ ]*BEGIN ([A-Z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
/[-]+[ ]*BEGIN ([A-Z0-9][A-Za-z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
assert.ok(m, 'invalid PEM header');
var m2 = lines[lines.length - 1].match(/*JSSTYLED*/
/[-]+[ ]*END ([A-Z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
/[-]+[ ]*END ([A-Z0-9][A-Za-z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
assert.ok(m2, 'invalid PEM footer');
/* Begin and end banners must match key type */
@ -135,7 +135,12 @@ function read(buf, options, forceType) {
function write(key, options, type) {
assert.object(key);
var alg = {'ecdsa': 'EC', 'rsa': 'RSA', 'dsa': 'DSA'}[key.type];
var alg = {
'ecdsa': 'EC',
'rsa': 'RSA',
'dsa': 'DSA',
'ed25519': 'EdDSA'
}[key.type];
var header;
var der = new asn1.BerWriter();

View File

@ -55,6 +55,11 @@ function readPkcs1(alg, type, der) {
else if (type === 'public')
return (readPkcs1ECDSAPublic(der));
throw (new Error('Unknown key type: ' + type));
case 'EDDSA':
case 'EdDSA':
if (type === 'private')
return (readPkcs1EdDSAPrivate(der));
throw (new Error(type + ' keys not supported with EdDSA'));
default:
throw (new Error('Unknown key algo: ' + alg));
}
@ -134,6 +139,31 @@ function readPkcs1DSAPrivate(der) {
return (new PrivateKey(key));
}
function readPkcs1EdDSAPrivate(der) {
var version = readMPInt(der, 'version');
assert.strictEqual(version.readUInt8(0), 1);
// private key
var k = der.readString(asn1.Ber.OctetString, true);
der.readSequence(0xa0);
var oid = der.readOID();
assert.strictEqual(oid, '1.3.101.112', 'the ed25519 curve identifier');
der.readSequence(0xa1);
var A = utils.readBitString(der);
var key = {
type: 'ed25519',
parts: [
{ name: 'A', data: utils.zeroPadToLength(A, 32) },
{ name: 'k', data: k }
]
};
return (new PrivateKey(key));
}
function readPkcs1DSAPublic(der) {
var y = readMPInt(der, 'y');
var p = readMPInt(der, 'p');
@ -236,6 +266,12 @@ function writePkcs1(der, key) {
else
writePkcs1ECDSAPublic(der, key);
break;
case 'ed25519':
if (PrivateKey.isPrivateKey(key))
writePkcs1EdDSAPrivate(der, key);
else
writePkcs1EdDSAPublic(der, key);
break;
default:
throw (new Error('Unknown key algo: ' + key.type));
}
@ -318,3 +354,23 @@ function writePkcs1ECDSAPrivate(der, key) {
der.writeBuffer(Q, asn1.Ber.BitString);
der.endSequence();
}
function writePkcs1EdDSAPrivate(der, key) {
var ver = new Buffer(1);
ver[0] = 1;
der.writeBuffer(ver, asn1.Ber.Integer);
der.writeBuffer(key.part.k.data, asn1.Ber.OctetString);
der.startSequence(0xa0);
der.writeOID('1.3.101.112');
der.endSequence();
der.startSequence(0xa1);
utils.writeBitString(der, key.part.A.data);
der.endSequence();
}
function writePkcs1EdDSAPublic(der, key) {
throw (new Error('Public keys are not supported for EdDSA PKCS#1'));
}

View File

@ -62,6 +62,18 @@ function readPkcs8(alg, type, der) {
return (readPkcs8ECDSAPublic(der));
else
return (readPkcs8ECDSAPrivate(der));
case '1.3.101.112':
if (type === 'public') {
return (readPkcs8EdDSAPublic(der));
} else {
return (readPkcs8EdDSAPrivate(der));
}
case '1.3.101.110':
if (type === 'public') {
return (readPkcs8X25519Public(der));
} else {
return (readPkcs8X25519Private(der));
}
default:
throw (new Error('Unknown key type OID ' + oid));
}
@ -322,6 +334,83 @@ function readPkcs8ECDSAPublic(der) {
return (new Key(key));
}
function readPkcs8EdDSAPublic(der) {
if (der.peek() === 0x00)
der.readByte();
var A = utils.readBitString(der);
var key = {
type: 'ed25519',
parts: [
{ name: 'A', data: utils.zeroPadToLength(A, 32) }
]
};
return (new Key(key));
}
function readPkcs8X25519Public(der) {
var A = utils.readBitString(der);
var key = {
type: 'curve25519',
parts: [
{ name: 'A', data: utils.zeroPadToLength(A, 32) }
]
};
return (new Key(key));
}
function readPkcs8EdDSAPrivate(der) {
if (der.peek() === 0x00)
der.readByte();
der.readSequence(asn1.Ber.OctetString);
var k = der.readString(asn1.Ber.OctetString, true);
k = utils.zeroPadToLength(k, 32);
var A;
if (der.peek() === asn1.Ber.BitString) {
A = utils.readBitString(der);
A = utils.zeroPadToLength(A, 32);
} else {
A = utils.calculateED25519Public(k);
}
var key = {
type: 'ed25519',
parts: [
{ name: 'A', data: utils.zeroPadToLength(A, 32) },
{ name: 'k', data: utils.zeroPadToLength(k, 32) }
]
};
return (new PrivateKey(key));
}
function readPkcs8X25519Private(der) {
if (der.peek() === 0x00)
der.readByte();
der.readSequence(asn1.Ber.OctetString);
var k = der.readString(asn1.Ber.OctetString, true);
k = utils.zeroPadToLength(k, 32);
var A = utils.calculateX25519Public(k);
var key = {
type: 'curve25519',
parts: [
{ name: 'A', data: utils.zeroPadToLength(A, 32) },
{ name: 'k', data: utils.zeroPadToLength(k, 32) }
]
};
return (new PrivateKey(key));
}
function writePkcs8(der, key) {
der.startSequence();
@ -354,6 +443,13 @@ function writePkcs8(der, key) {
else
writePkcs8ECDSAPublic(key, der);
break;
case 'ed25519':
der.writeOID('1.3.101.112');
if (PrivateKey.isPrivateKey(key))
throw (new Error('Ed25519 private keys in pkcs8 ' +
'format are not supported'));
writePkcs8EdDSAPublic(key, der);
break;
default:
throw (new Error('Unsupported key type: ' + key.type));
}
@ -503,3 +599,18 @@ function writePkcs8ECDSAPrivate(key, der) {
der.endSequence();
der.endSequence();
}
function writePkcs8EdDSAPublic(key, der) {
der.endSequence();
utils.writeBitString(der, key.part.A.data);
}
function writePkcs8EdDSAPrivate(key, der) {
der.endSequence();
var k = utils.mpNormalize(key.part.k.data, true);
der.startSequence(asn1.Ber.OctetString);
der.writeBuffer(k, asn1.Ber.OctetString);
der.endSequence();
}

View File

@ -97,12 +97,25 @@ function read(partial, type, buf, options) {
var normalized = true;
for (var i = 0; i < algInfo.parts.length; ++i) {
parts[i].name = algInfo.parts[i];
if (parts[i].name !== 'curve' &&
algInfo.normalize !== false) {
var p = parts[i];
var nd = utils.mpNormalize(p.data);
if (nd !== p.data) {
var p = parts[i];
p.name = algInfo.parts[i];
/*
* OpenSSH stores ed25519 "private" keys as seed + public key
* concat'd together (k followed by A). We want to keep them
* separate for other formats that don't do this.
*/
if (key.type === 'ed25519' && p.name === 'k')
p.data = p.data.slice(0, 32);
if (p.name !== 'curve' && algInfo.normalize !== false) {
var nd;
if (key.type === 'ed25519') {
nd = utils.zeroPadToLength(p.data, 32);
} else {
nd = utils.mpNormalize(p.data);
}
if (nd.toString('binary') !==
p.data.toString('binary')) {
p.data = nd;
normalized = false;
}
@ -137,8 +150,14 @@ function write(key, options) {
for (i = 0; i < parts.length; ++i) {
var data = key.part[parts[i]].data;
if (algInfo.normalize !== false)
data = utils.mpNormalize(data);
if (algInfo.normalize !== false) {
if (key.type === 'ed25519')
data = utils.zeroPadToLength(data, 32);
else
data = utils.mpNormalize(data);
}
if (key.type === 'ed25519' && parts[i] === 'k')
data = Buffer.concat([data, key.part.A.data]);
buf.writeBuffer(data);
}

View File

@ -14,9 +14,9 @@ var PrivateKey = require('../private-key');
var sshpriv = require('./ssh-private');
/*JSSTYLED*/
var SSHKEY_RE = /^([a-z0-9-]+)[ \t]+([a-zA-Z0-9+\/]+[=]*)([\n \t]+([^\n]+))?$/;
var SSHKEY_RE = /^([a-z0-9-]+)[ \t]+([a-zA-Z0-9+\/]+[=]*)([ \t]+([^ \t][^\n]*[\n]*)?)?$/;
/*JSSTYLED*/
var SSHKEY_RE2 = /^([a-z0-9-]+)[ \t]+([a-zA-Z0-9+\/ \t\n]+[=]*)(.*)$/;
var SSHKEY_RE2 = /^([a-z0-9-]+)[ \t\n]+([a-zA-Z0-9+\/][a-zA-Z0-9+\/ \t\n=]*)([^a-zA-Z0-9+\/ \t\n=].*)?$/;
function read(buf, options) {
if (typeof (buf) !== 'string') {
@ -71,7 +71,7 @@ function read(buf, options) {
* chars from the beginning up to this point in the the string.
* Then offset in this and try to make up for missing = chars.
*/
var data = m[2] + m[3];
var data = m[2] + (m[3] ? m[3] : '');
var realOffset = Math.ceil(ret.consumed / 3) * 4;
data = data.slice(0, realOffset - 2). /*JSSTYLED*/
replace(/[^a-zA-Z0-9+\/=]/g, '') +

View File

@ -70,7 +70,8 @@ var SIGN_ALGS = {
'ecdsa-sha1': '1.2.840.10045.4.1',
'ecdsa-sha256': '1.2.840.10045.4.3.2',
'ecdsa-sha384': '1.2.840.10045.4.3.3',
'ecdsa-sha512': '1.2.840.10045.4.3.4'
'ecdsa-sha512': '1.2.840.10045.4.3.4',
'ed25519-sha512': '1.3.101.112'
};
Object.keys(SIGN_ALGS).forEach(function (k) {
SIGN_ALGS[SIGN_ALGS[k]] = k;
@ -522,6 +523,8 @@ function writeTBSCert(cert, der) {
der.startSequence();
der.writeOID(SIGN_ALGS[sig.algo]);
if (sig.algo.match(/^rsa-/))
der.writeNull();
der.endSequence();
cert.issuer.toAsn1(der);

View File

@ -136,14 +136,25 @@ Identity.prototype.toAsn1 = function (der, tag) {
/*
* If we fit in a PrintableString, use that. Otherwise use an
* IA5String or UTF8String.
*
* If this identity was parsed from a DN, use the ASN.1 types
* from the original representation (otherwise this might not
* be a full match for the original in some validators).
*/
if (c.value.match(NOT_IA5)) {
if (c.asn1type === asn1.Ber.Utf8String ||
c.value.match(NOT_IA5)) {
var v = new Buffer(c.value, 'utf8');
der.writeBuffer(v, asn1.Ber.Utf8String);
} else if (c.value.match(NOT_PRINTABLE)) {
} else if (c.asn1type === asn1.Ber.IA5String ||
c.value.match(NOT_PRINTABLE)) {
der.writeString(c.value, asn1.Ber.IA5String);
} else {
der.writeString(c.value, asn1.Ber.PrintableString);
var type = asn1.Ber.PrintableString;
if (c.asn1type !== undefined)
type = c.asn1type;
der.writeString(c.value, type);
}
der.endSequence();
der.endSequence();
@ -253,7 +264,7 @@ Identity.parseAsn1 = function (der, top) {
default:
throw (new Error('Unknown asn1 type ' + type));
}
components.push({ oid: oid, value: value });
components.push({ oid: oid, asn1type: type, value: value });
der._offset = after;
}
der._offset = end;

View File

@ -31,6 +31,7 @@ formats['rfc4253'] = require('./formats/rfc4253');
formats['ssh'] = require('./formats/ssh');
formats['ssh-private'] = require('./formats/ssh-private');
formats['openssh'] = formats['ssh-private'];
formats['dnssec'] = require('./formats/dnssec');
function Key(opts) {
assert.object(opts, 'options');
@ -105,7 +106,6 @@ Key.prototype.hash = function (algo) {
if (this._hashCache[algo])
return (this._hashCache[algo]);
var hash = crypto.createHash(algo).
update(this.toBuffer('rfc4253')).digest();
this._hashCache[algo] = hash;
@ -256,8 +256,9 @@ Key.isKey = function (obj, ver) {
* [1,3] -- added defaultHashAlgorithm
* [1,4] -- added ed support, createDH
* [1,5] -- first explicitly tagged version
* [1,6] -- changed ed25519 part names
*/
Key.prototype._sshpkApiVersion = [1, 5];
Key.prototype._sshpkApiVersion = [1, 6];
Key._oldVersionDetect = function (obj) {
assert.func(obj.toBuffer);

View File

@ -37,6 +37,7 @@ formats['rfc4253'] = require('./formats/rfc4253');
formats['ssh-private'] = require('./formats/ssh-private');
formats['openssh'] = formats['ssh-private'];
formats['ssh'] = formats['ssh-private'];
formats['dnssec'] = require('./formats/dnssec');
function PrivateKey(opts) {
assert.object(opts, 'options');
@ -91,40 +92,36 @@ PrivateKey.prototype.derive = function (newType) {
if (nacl === undefined)
nacl = require('tweetnacl');
priv = this.part.r.data;
priv = this.part.k.data;
if (priv[0] === 0x00)
priv = priv.slice(1);
priv = priv.slice(0, 32);
pair = nacl.box.keyPair.fromSecretKey(new Uint8Array(priv));
pub = new Buffer(pair.publicKey);
priv = Buffer.concat([priv, pub]);
return (new PrivateKey({
type: 'curve25519',
parts: [
{ name: 'R', data: utils.mpNormalize(pub) },
{ name: 'r', data: priv }
{ name: 'A', data: utils.mpNormalize(pub) },
{ name: 'k', data: utils.mpNormalize(priv) }
]
}));
} else if (this.type === 'curve25519' && newType === 'ed25519') {
if (nacl === undefined)
nacl = require('tweetnacl');
priv = this.part.r.data;
priv = this.part.k.data;
if (priv[0] === 0x00)
priv = priv.slice(1);
priv = priv.slice(0, 32);
pair = nacl.sign.keyPair.fromSeed(new Uint8Array(priv));
pub = new Buffer(pair.publicKey);
priv = Buffer.concat([priv, pub]);
return (new PrivateKey({
type: 'ed25519',
parts: [
{ name: 'R', data: utils.mpNormalize(pub) },
{ name: 'r', data: priv }
{ name: 'A', data: utils.mpNormalize(pub) },
{ name: 'k', data: utils.mpNormalize(priv) }
]
}));
}
@ -238,8 +235,9 @@ PrivateKey.generate = function (type, options) {
* [1,2] -- added defaultHashAlgorithm
* [1,3] -- added derive, ed, createDH
* [1,4] -- first tagged version
* [1,5] -- changed ed25519 part names and format
*/
PrivateKey.prototype._sshpkApiVersion = [1, 4];
PrivateKey.prototype._sshpkApiVersion = [1, 5];
PrivateKey._oldVersionDetect = function (obj) {
assert.func(obj.toPublic);

View File

@ -4,18 +4,31 @@ module.exports = {
bufferSplit: bufferSplit,
addRSAMissing: addRSAMissing,
calculateDSAPublic: calculateDSAPublic,
calculateED25519Public: calculateED25519Public,
calculateX25519Public: calculateX25519Public,
mpNormalize: mpNormalize,
mpDenormalize: mpDenormalize,
ecNormalize: ecNormalize,
countZeros: countZeros,
assertCompatible: assertCompatible,
isCompatible: isCompatible,
opensslKeyDeriv: opensslKeyDeriv,
opensshCipherInfo: opensshCipherInfo
opensshCipherInfo: opensshCipherInfo,
publicFromPrivateECDSA: publicFromPrivateECDSA,
zeroPadToLength: zeroPadToLength,
writeBitString: writeBitString,
readBitString: readBitString
};
var assert = require('assert-plus');
var PrivateKey = require('./private-key');
var Key = require('./key');
var crypto = require('crypto');
var algs = require('./algs');
var asn1 = require('asn1');
var ec, jsbn;
var nacl;
var MAX_CLASS_DEPTH = 3;
@ -178,6 +191,24 @@ function ecNormalize(buf, addZero) {
return (b);
}
function readBitString(der, tag) {
if (tag === undefined)
tag = asn1.Ber.BitString;
var buf = der.readString(tag, true);
assert.strictEqual(buf[0], 0x00, 'bit strings with unused bits are ' +
'not supported (0x' + buf[0].toString(16) + ')');
return (buf.slice(1));
}
function writeBitString(der, buf, tag) {
if (tag === undefined)
tag = asn1.Ber.BitString;
var b = new Buffer(buf.length + 1);
b[0] = 0x00;
buf.copy(b, 1);
der.writeBuffer(b, tag);
}
function mpNormalize(buf) {
assert.buffer(buf);
while (buf.length > 1 && buf[0] === 0x00 && (buf[1] & 0x80) === 0x00)
@ -191,6 +222,29 @@ function mpNormalize(buf) {
return (buf);
}
function mpDenormalize(buf) {
assert.buffer(buf);
while (buf.length > 1 && buf[0] === 0x00)
buf = buf.slice(1);
return (buf);
}
function zeroPadToLength(buf, len) {
assert.buffer(buf);
assert.number(len);
while (buf.length > len) {
assert.equal(buf[0], 0x00);
buf = buf.slice(1);
}
while (buf.length < len) {
var b = new Buffer(buf.length + 1);
b[0] = 0x00;
buf.copy(b, 1);
buf = b;
}
return (buf);
}
function bigintToMpBuf(bigint) {
var buf = new Buffer(bigint.toByteArray());
buf = mpNormalize(buf);
@ -215,6 +269,26 @@ function calculateDSAPublic(g, p, x) {
return (ybuf);
}
function calculateED25519Public(k) {
assert.buffer(k);
if (nacl === undefined)
nacl = require('tweetnacl');
var kp = nacl.sign.keyPair.fromSeed(new Uint8Array(k));
return (new Buffer(kp.publicKey));
}
function calculateX25519Public(k) {
assert.buffer(k);
if (nacl === undefined)
nacl = require('tweetnacl');
var kp = nacl.box.keyPair.fromSeed(new Uint8Array(k));
return (new Buffer(kp.publicKey));
}
function addRSAMissing(key) {
assert.object(key);
assertCompatible(key, PrivateKey, [1, 1]);
@ -246,6 +320,32 @@ function addRSAMissing(key) {
}
}
function publicFromPrivateECDSA(curveName, priv) {
assert.string(curveName, 'curveName');
assert.buffer(priv);
if (ec === undefined)
ec = require('ecc-jsbn/lib/ec');
if (jsbn === undefined)
jsbn = require('jsbn').BigInteger;
var params = algs.curves[curveName];
var p = new jsbn(params.p);
var a = new jsbn(params.a);
var b = new jsbn(params.b);
var curve = new ec.ECCurveFp(p, a, b);
var G = curve.decodePointHex(params.G.toString('hex'));
var d = new jsbn(mpNormalize(priv));
var pub = G.multiply(d);
pub = new Buffer(curve.encodePointHex(pub), 'hex');
var parts = [];
parts.push({name: 'curve', data: new Buffer(curveName)});
parts.push({name: 'Q', data: pub});
var key = new Key({type: 'ecdsa', curve: curve, parts: parts});
return (key);
}
function opensshCipherInfo(cipher) {
var inf = {};
switch (cipher) {

View File

@ -1,6 +1,6 @@
{
"name": "sshpk",
"version": "1.13.1",
"version": "1.14.1",
"description": "A library for finding and using SSH public keys",
"main": "lib/index.js",
"scripts": {
@ -72,9 +72,9 @@
"sshpk-sign": "bin/sshpk-sign",
"sshpk-verify": "bin/sshpk-verify"
},
"gitHead": "a17ec8861242649038dcdba8f8d7df5edf2ddb8c",
"_id": "sshpk@1.13.1",
"_shasum": "512df6da6287144316dc4c18fe1cf1d940739be3",
"gitHead": "6edb37cb986b7ddaf0d346440d37287cc059bfee",
"_id": "sshpk@1.14.1",
"_shasum": "130f5975eddad963f1d56f92b9ac6c51fa9f83eb",
"_from": "sshpk@>=1.7.0 <2.0.0",
"_npmVersion": "4.2.0",
"_nodeVersion": "0.12.18",
@ -83,8 +83,10 @@
"email": "alex@cooperi.net"
},
"dist": {
"shasum": "512df6da6287144316dc4c18fe1cf1d940739be3",
"tarball": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz"
"shasum": "130f5975eddad963f1d56f92b9ac6c51fa9f83eb",
"tarball": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz",
"fileCount": 35,
"unpackedSize": 208057
},
"maintainers": [
{
@ -94,7 +96,7 @@
],
"_npmOperationalInternal": {
"host": "s3://npm-registry-packages",
"tmp": "tmp/sshpk-1.13.1.tgz_1496888143718_0.9964376483112574"
"tmp": "tmp/sshpk_1.14.1_1520899928205_0.6230534223468485"
},
"_resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz"
"_resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz"
}

2
node_modules/nak/package.json generated vendored
View File

@ -52,7 +52,7 @@
},
"homepage": "https://github.com/gjtorikian/nak#readme",
"_id": "nak@0.3.3",
"_shasum": "24bf64f51c0bd9f5e13d193db392c1b2764d7e87",
"_shasum": "7c9ec82f0c5985b45ce6ba3947351651105ce8d8",
"_from": "git+https://github.com/cloud9ide/nak.git#6deef931594",
"_resolved": "git+https://github.com/cloud9ide/nak.git#6deef931594787edd167040f7352e3e7533430e4"
}

View File

@ -62,6 +62,5 @@
],
"directories": {},
"_shasum": "de3f98543dbf96082be48ad1a0c7cda836301dcf",
"_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
"readme": "ERROR: No README data found!"
"_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz"
}

View File

@ -58,6 +58,5 @@
"email": "mail@substack.net"
}
],
"_resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
"readme": "ERROR: No README data found!"
"_resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz"
}

5
node_modules/optimist/package.json generated vendored
View File

@ -16,7 +16,7 @@
},
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/substack/node-optimist.git"
"url": "http://github.com/substack/node-optimist.git"
},
"keywords": [
"argument",
@ -59,6 +59,5 @@
],
"directories": {},
"_shasum": "da3ea74686fa21a19a111c326e90eb15a0196686",
"_resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
"readme": "ERROR: No README data found!"
"_resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz"
}

View File

@ -36,7 +36,7 @@
"homepage": "https://github.com/isaacs/inherits#readme",
"_id": "inherits@2.0.3",
"_shasum": "633c2c83e3da42a502f52466022480f4208261de",
"_from": "inherits@>=2.0.1 <2.1.0",
"_from": "inherits@>=2.0.0 <3.0.0",
"_npmVersion": "3.10.7",
"_nodeVersion": "6.5.0",
"_npmUser": {

4
node_modules/tern/package.json generated vendored
View File

@ -40,7 +40,6 @@
"process"
]
},
"gitHead": "39015d544d4c00c7899fea4c95c2e5bc2720e68e",
"contributors": [
{
"name": "List of Tern contributors. Updated before every release."
@ -241,6 +240,7 @@
"name": "vheon"
}
],
"gitHead": "39015d544d4c00c7899fea4c95c2e5bc2720e68e",
"readme": "# Tern\n\n[![Build Status](https://secure.travis-ci.org/ternjs/tern.png)](http://travis-ci.org/ternjs/tern)\n[![NPM version](https://img.shields.io/npm/v/tern.svg)](https://www.npmjs.org/package/tern) \n[Funding status: ![maintainer happiness](https://marijnhaverbeke.nl/fund/status_s.png?again)](https://marijnhaverbeke.nl/fund/)\n\nThis is [Tern][1]. Tern is a stand-alone, editor-independent\nJavaScript analyzer that can be used to improve the JavaScript\nintegration of existing editors.\n\nThanks to a group of generous [crowd funders][2], Tern is open-source\nsoftware, under an MIT license.\n\nThere are currently plugins available for [Emacs][emacs] (and Emacs\n[company-mode][cmode]), [Vim][vim], [Sublime Text][st], [Eclipse (and general Java API)][ec],\n[Light Table][lt], [Atom][atom] and [gedit][gedit], and built-in support in\n[Brackets][brackets], [Edge Code][edge_code], and [CodeLite](http://codelite.org/).\n\nFor further documentation, see the [project page][1] and the\n[manual][3]. To report issues, use the\n[issue tracker](https://github.com/ternjs/tern/issues). For questions\nand documentation, see the\n[discussion forum](https://discuss.ternjs.net).\n\n[1]: http://ternjs.net\n[2]: http://www.indiegogo.com/projects/tern-intelligent-javascript-editing\n[3]: http://ternjs.net/doc/manual.html\n\n[emacs]: http://ternjs.net/doc/manual.html#emacs\n[ec]: https://github.com/angelozerr/tern.java\n[vim]: https://github.com/ternjs/tern_for_vim\n[st]: https://github.com/ternjs/tern_for_sublime\n[lt]: https://github.com/mortalapeman/LT-TernJS\n[atom]: https://atom.io/packages/atom-ternjs\n[gedit]: https://github.com/Swatinem/tern_for_gedit\n[brackets]: http://brackets.io\n[edge_code]: http://html.adobe.com/edge/code\n[cmode]: https://github.com/proofit404/company-tern\n",
"readmeFilename": "README.md",
"bugs": {
@ -248,7 +248,7 @@
},
"homepage": "https://github.com/ternjs/tern#readme",
"_id": "tern@0.16.1",
"_shasum": "c89ccea2e756f052a4b28e08f67277d846983496",
"_shasum": "e899f56ba505124cce3310ceb8414d5f1583ab38",
"_from": "git+https://github.com/cloud9ide/tern.git#39015d544d4c00c7899fea4c95c2e5bc2720e68e",
"_resolved": "git+https://github.com/cloud9ide/tern.git#39015d544d4c00c7899fea4c95c2e5bc2720e68e"
}

View File

@ -20,7 +20,7 @@
"readme": "# tern_from_ts\n\nTern signatures extracted from typescript signatures.\n\nLicense: MIT\n\nSee also https://github.com/marijnh/tern and https://github.com/borisyankov/DefinitelyTyped\n",
"readmeFilename": "README.md",
"_id": "tern_from_ts@0.0.1",
"_shasum": "82c5150f58103432eaaa6aadd3ecfad8331aad56",
"_shasum": "1fed17d49d8aecdfbd1bfe4a05256105910b00b2",
"_from": "git+https://github.com/cloud9ide/tern_from_ts.git#66df507986bbdd63f3bc4f0c53edb39169ce4f1c",
"_resolved": "git+https://github.com/cloud9ide/tern_from_ts.git#66df507986bbdd63f3bc4f0c53edb39169ce4f1c"
}

View File

@ -49,5 +49,5 @@
},
"devDependencies": {},
"licenses": [],
"revision": "2af1c7c68e612d417f80d9feaf436da488e19103"
"revision": "59eb6c51d6f72522362c3e540101f976851fb883"
}

View File

@ -349,7 +349,8 @@ define(function(require, exports, module) {
"preferences.experimental": {
addExperiment: function() {
return false;
}
},
add: function() {},
},
"ace.gotoline": {},
"ace.stripws": {

View File

@ -1 +1 @@
1520864858
1520999796