Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

completely untested key thing

  • Loading branch information...
commit 61c67b33b25aab70b78fc45ab0ccfd757da03c53 0 parents
@substack authored
Showing with 134 additions and 0 deletions.
  1. +44 −0 dss.js
  2. +1 −0  index.js
  3. +89 −0 key.js
44 dss.js
@@ -0,0 +1,44 @@
+var bigint = require('bigint');
+var put = require('put');
+var assert = require('assert');
+
+// Generate two primes p and q to the Digital Signature Standard (DSS)
+// http://www.itl.nist.gov/fipspubs/fip186.htm appendix 2.2
+
+exports.generate = function () {
+ var q = bigint(2).pow(159).add(1).rand(bigint(2).pow(160)).nextPrime();
+ var L = 512 + 64 * Math.floor(Math.random() * 8);
+
+ do {
+ var X = bigint(2).pow(L-1).add(1).rand(bigint(2).pow(L));
+ var c = X.mod(q.mul(2));
+ var p = X.sub(c.sub(1)); // p is congruent to 1 % 2q somehow!
+ } while (p.lt(bigint.pow(2, L - 1)) || p.probPrime(50) === false)
+
+ assert.ok(q.gt(bigint.pow(2,159)), 'q > 2**159');
+ assert.ok(q.lt(bigint.pow(2,160)), 'q < 2**160');
+ assert.ok(p.gt(bigint.pow(2,L-1)), 'p > 2**(L-1)');
+ assert.ok(q.lt(bigint.pow(2,L)), 'p < 2**L');
+ assert.ok(q.mul(p.sub(1).div(q)).add(1).eq(p), 'q divides p - 1');
+
+ do {
+ var e = p.sub(1).div(q);
+ var h = p.sub(2).rand().add(1);
+ var g = h.powm(e, p);
+ } while (g.eq(1))
+
+ var x = q.sub(1).rand().add(1); // private key
+ var y = g.powm(x, p); // public key
+ var f = g.powm(y, p);
+
+ return {
+ // p, q, and g can be shared and re-used
+ p : p, q : q, g : g, y : y,
+
+ session : function () {
+ return {
+ k : function (e) { return e.powm(y, p) },
+ };
+ },
+ };
+};
1  index.js
@@ -0,0 +1 @@
+exports.dss = require('./dss');
89 key.js
@@ -0,0 +1,89 @@
+var Buffers = require('buffers');
+
+module.exports = Key;
+
+function Key (keyData, format) {
+ if (!(this instanceof Key)) return new Key(keyData, format);
+ this.algorithm = format.split('-')[0];
+
+ if (typeof keyData === 'string') {
+ var encoding = format && format.split('-')[1] || 'base64';
+ this.data = new Buffer(keyData, encoding);
+ }
+ else if (Buffer.isBuffer(keyData)) {
+ this.data = keyData;
+ }
+ else {
+ throw new Error('keyData must be a string or Buffer');
+ }
+}
+
+Key.pack = function (algorithm) {
+ var bufs = [].slice.call(arguments, 1)
+ .map(function (bigi) { return bigi.toBuffer('mpint') });
+ var packed = Buffers(bufs).slice();
+ return new Key(packed, algorithm);
+};
+
+Key.parse = function (body) {
+ var ssh2 = body.match(/^-----BEGIN (\S+) (PRIVATE|PUBLIC) KEY-----\n/);
+ if (ssh2) {
+ return new Key(
+ body
+ .toString()
+ .split('\n')
+ .slice(1,-2)
+ .filter(function (line) { return !line.match(/:/) })
+ .join('')
+ .replace(/\s+/g,'')
+ , ssh2[1]
+ );
+ }
+
+ var openssh = body.match(/^ssh-(\S+)\s+(\S+)/);
+ if (openssh) {
+ return new Key(openssh[2], openssh[1]);
+ }
+
+ return undefined;
+};
+
+Key.prototype.toString = function (encoding) {
+ return this.fields
+ .reduce(function (put, x) {
+ return put.put(x.toBuffer('mpint'))
+ }, Put().word32be(id.length).put(new Buffer(id)))
+ .buffer().toString(encoding || 'base64')
+ ;
+};
+
+Key.prototype.format = function (format, privOrPub, cols) {
+ var fmt = (format || 'ssh2').toLowerCase();
+ if (fmt === 'ssh2') {
+ var p = (privOrPub || '').toUpperCase();
+ if (p !== 'PRIVATE' && p !== 'PUBLIC') {
+ throw new Error('Must specify private or public for ssh2');
+ }
+
+ var algo = this.algorithm.toUpperCase();
+
+ var wrapped = [];
+ for (var i = 0; i < this.data.length; i += 64) {
+ wrapped.push(this.data.slice(
+ i, Math.min(this.data.length, i + 64)
+ ));
+ }
+
+ return [
+ [ '-----BEGIN', algo, p, 'KEY-----' ].join(' '),
+ wrapped.join('\n'),
+ [ '-----END', algo, p, 'KEY-----' ].join(' '),
+ ].join('\n');
+ }
+ else if (fmt === 'openssh') {
+ var id = this.algorithm;
+ if (id === 'dsa') id = 'dss';
+ return [ 'ssh-' + id, this.data, email || '' ].join(' ') + '\r\n';
+ }
+ else throw new Error('Unrecognized format ' + format.toString());
+};
Please sign in to comment.
Something went wrong with that request. Please try again.