var parseKeys = require('parse-asn1'); var mgf = require('./mgf'); var xor = require('./xor'); var bn = require('bn.js'); var crt = require('browserify-rsa'); var createHash = require('create-hash'); var withPublic = require('./withPublic'); module.exports = function privateDecrypt(private_key, enc, reverse) { var padding; if (private_key.padding) { padding = private_key.padding; } else if (reverse) { padding = 1; } else { padding = 4; } var key = parseKeys(private_key); var k = key.modulus.byteLength(); if (enc.length > k || new bn(enc).cmp(key.modulus) >= 0) { throw new Error('decryption error'); } var msg; if (reverse) { msg = withPublic(new bn(enc), key); } else { msg = crt(enc, key); } var zBuffer = new Buffer(k - msg.length); zBuffer.fill(0); msg = Buffer.concat([zBuffer, msg], k); if (padding === 4) { return oaep(key, msg); } else if (padding === 1) { return pkcs1(key, msg, reverse); } else if (padding === 3) { return msg; } else { throw new Error('unknown padding'); } }; function oaep(key, msg){ var n = key.modulus; var k = key.modulus.byteLength(); var mLen = msg.length; var iHash = createHash('sha1').update(new Buffer('')).digest(); var hLen = iHash.length; var hLen2 = 2 * hLen; if (msg[0] !== 0) { throw new Error('decryption error'); } var maskedSeed = msg.slice(1, hLen + 1); var maskedDb = msg.slice(hLen + 1); var seed = xor(maskedSeed, mgf(maskedDb, hLen)); var db = xor(maskedDb, mgf(seed, k - hLen - 1)); if (compare(iHash, db.slice(0, hLen))) { throw new Error('decryption error'); } var i = hLen; while (db[i] === 0) { i++; } if (db[i++] !== 1) { throw new Error('decryption error'); } return db.slice(i); } function pkcs1(key, msg, reverse){ var p1 = msg.slice(0, 2); var i = 2; var status = 0; while (msg[i++] !== 0) { if (i >= msg.length) { status++; break; } } var ps = msg.slice(2, i - 1); var p2 = msg.slice(i - 1, i); if ((p1.toString('hex') !== '0002' && !reverse) || (p1.toString('hex') !== '0001' && reverse)){ status++; } if (ps.length < 8) { status++; } if (status) { throw new Error('decryption error'); } return msg.slice(i); } function compare(a, b){ a = new Buffer(a); b = new Buffer(b); var dif = 0; var len = a.length; if (a.length !== b.length) { dif++; len = Math.min(a.length, b.length); } var i = -1; while (++i < len) { dif += (a[i] ^ b[i]); } return dif; }
# | 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/public-encrypt/privateDecrypt.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. |