import parseKeys from "../parse-asn1"; import mgf from "./mgf"; import xor from "./xor"; import BN from "../bn.js"; import crt from "../browserify-rsa"; import createHash from "../create-hash"; import withPublic from "./withPublic"; function oaep(key, msg) { var k = key.modulus.byteLength(); var iHash = createHash('sha1').update(Buffer.alloc(0)).digest(); var hLen = iHash.length; 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); 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 = Buffer.from(a); b = Buffer.from(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; } export default (function privateDecrypt(privateKey, enc, reverse) { var padding; if (privateKey.padding) { padding = privateKey.padding; } else if (reverse) { padding = 1; } else { padding = 4; } var key = parseKeys(privateKey); 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 = Buffer.alloc(k - msg.length); 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'); } });