// much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js var createHmac = require('create-hmac') var crt = require('browserify-rsa') var curves = require('./curves') var elliptic = require('elliptic') var parseKeys = require('parse-asn1') var BN = require('bn.js') var EC = elliptic.ec function sign (hash, key, hashType, signType) { var priv = parseKeys(key) if (priv.curve) { if (signType !== 'ecdsa') throw new Error('wrong private key type') return ecSign(hash, priv) } else if (priv.type === 'dsa') { if (signType !== 'dsa') { throw new Error('wrong private key type') } return dsaSign(hash, priv, hashType) } else { if (signType !== 'rsa') throw new Error('wrong private key type') } var len = priv.modulus.byteLength() var pad = [ 0, 1 ] while (hash.length + pad.length + 1 < len) { pad.push(0xff) } pad.push(0x00) var i = -1 while (++i < hash.length) { pad.push(hash[i]) } var out = crt(pad, priv) return out } function ecSign (hash, priv) { var curveId = curves[priv.curve.join('.')] if (!curveId) throw new Error('unknown curve ' + priv.curve.join('.')) var curve = new EC(curveId) var key = curve.genKeyPair() key._importPrivate(priv.privateKey) var out = key.sign(hash) return new Buffer(out.toDER()) } function dsaSign (hash, priv, algo) { var x = priv.params.priv_key var p = priv.params.p var q = priv.params.q var g = priv.params.g var r = new BN(0) var k var H = bits2int(hash, q).mod(q) var s = false var kv = getKey(x, q, hash, algo) while (s === false) { k = makeKey(q, kv, algo) r = makeR(g, k, p, q) s = k.invm(q).imul(H.add(x.mul(r))).mod(q) if (!s.cmpn(0)) { s = false r = new BN(0) } } return toDER(r, s) } function toDER (r, s) { r = r.toArray() s = s.toArray() // Pad values if (r[0] & 0x80) { r = [ 0 ].concat(r) } // Pad values if (s[0] & 0x80) { s = [0].concat(s) } var total = r.length + s.length + 4 var res = [ 0x30, total, 0x02, r.length ] res = res.concat(r, [ 0x02, s.length ], s) return new Buffer(res) } function getKey (x, q, hash, algo) { x = new Buffer(x.toArray()) if (x.length < q.byteLength()) { var zeros = new Buffer(q.byteLength() - x.length) zeros.fill(0) x = Buffer.concat([zeros, x]) } var hlen = hash.length var hbits = bits2octets(hash, q) var v = new Buffer(hlen) v.fill(1) var k = new Buffer(hlen) k.fill(0) k = createHmac(algo, k) .update(v) .update(new Buffer([0])) .update(x) .update(hbits) .digest() v = createHmac(algo, k) .update(v) .digest() k = createHmac(algo, k) .update(v) .update(new Buffer([1])) .update(x) .update(hbits) .digest() v = createHmac(algo, k) .update(v) .digest() return { k: k, v: v } } function bits2int (obits, q) { var bits = new BN(obits) var shift = (obits.length << 3) - q.bitLength() if (shift > 0) { bits.ishrn(shift) } return bits } function bits2octets (bits, q) { bits = bits2int(bits, q) bits = bits.mod(q) var out = new Buffer(bits.toArray()) if (out.length < q.byteLength()) { var zeros = new Buffer(q.byteLength() - out.length) zeros.fill(0) out = Buffer.concat([zeros, out]) } return out } function makeKey (q, kv, algo) { var t, k do { t = new Buffer('') while (t.length * 8 < q.bitLength()) { kv.v = createHmac(algo, kv.k) .update(kv.v) .digest() t = Buffer.concat([t, kv.v]) } k = bits2int(t, q) kv.k = createHmac(algo, kv.k) .update(kv.v) .update(new Buffer([0])) .digest() kv.v = createHmac(algo, kv.k) .update(kv.v) .digest() } while (k.cmp(q) !== -1) return k } function makeR (g, k, p, q) { return g.toRed(BN.mont(p)).redPow(k).fromRed().mod(q) } module.exports = sign module.exports.getKey = getKey module.exports.makeKey = makeKey
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 19553 | swellard | Move and rename clients | ||
//guest/perforce_software/helix-web-services/main/source/clients/2016.1.0/javascript/node_modules/browserify-sign/sign.js | |||||
#1 | 18810 | tjuricek |
First-pass at JavaScript client SDK. JavaScript requires Node with Gulp to "browserfy" the library. It's the easiest way I found to use the swagger-js project; bundle up a wrapping method. There is no JavaScript reference guide. The swagger-js doesn't really document what they do very well, actually. Overall I'm not particularly impressed by swagger-js, it was hard to even figure out what the right method syntax was. We may want to invest time in doing it better. This required setting CORS response headers, which are currently defaulted to a fairly insecure setting. |