var BigInteger=require("../libs/jsbn"),crypt=require("crypto"),constants=require("constants"),SIGN_INFO_HEAD={md2:Buffer.from("3020300c06082a864886f70d020205000410","hex"),md5:Buffer.from("3020300c06082a864886f70d020505000410","hex"),sha1:Buffer.from("3021300906052b0e03021a05000414","hex"),sha224:Buffer.from("302d300d06096086480165030402040500041c","hex"),sha256:Buffer.from("3031300d060960864801650304020105000420","hex"),sha384:Buffer.from("3041300d060960864801650304020205000430","hex"),sha512:Buffer.from("3051300d060960864801650304020305000440","hex"),ripemd160:Buffer.from("3021300906052b2403020105000414","hex"),rmd160:Buffer.from("3021300906052b2403020105000414","hex")},SIGN_ALG_TO_HASH_ALIASES={ripemd160:"rmd160"},DEFAULT_HASH_FUNCTION="sha256";module.exports={isEncryption:!0,isSignature:!0},module.exports.makeScheme=function(e,t){function n(e,t){this.key=e,this.options=t}return n.prototype.maxMessageLength=function(){return this.options.encryptionSchemeOptions&&this.options.encryptionSchemeOptions.padding==constants.RSA_NO_PADDING?this.key.encryptedDataLength:this.key.encryptedDataLength-11},n.prototype.encPad=function(e,t){var n;if(t=t||{},e.length>this.key.maxMessageLength)throw new Error("Message too long for RSA (n="+this.key.encryptedDataLength+", l="+e.length+")");if(this.options.encryptionSchemeOptions&&this.options.encryptionSchemeOptions.padding==constants.RSA_NO_PADDING)return(n=Buffer.alloc(this.key.maxMessageLength-e.length)).fill(0),Buffer.concat([n,e]);if(1===t.type)return(n=Buffer.alloc(this.key.encryptedDataLength-e.length-1)).fill(255,0,n.length-1),n[0]=1,n[n.length-1]=0,Buffer.concat([n,e]);(n=Buffer.alloc(this.key.encryptedDataLength-e.length))[0]=0,n[1]=2;for(var r=crypt.randomBytes(n.length-3),o=0;o<r.length;o++){for(var i=r[o];0===i;)i=crypt.randomBytes(1)[0];n[o+2]=i}return n[n.length-1]=0,Buffer.concat([n,e])},n.prototype.encUnPad=function(e,t){t=t||{};var n=0;if(this.options.encryptionSchemeOptions&&this.options.encryptionSchemeOptions.padding==constants.RSA_NO_PADDING)return"function"==typeof e.lastIndexOf?e.slice(e.lastIndexOf("\0")+1,e.length):e.slice(String.prototype.lastIndexOf.call(e,"\0")+1,e.length);if(e.length<4)return null;if(1===t.type){if(0!==e[0]&&1!==e[1])return null;for(n=3;0!==e[n];)if(255!=e[n]||++n>=e.length)return null}else{if(0!==e[0]&&2!==e[1])return null;for(n=3;0!==e[n];)if(++n>=e.length)return null}return e.slice(n+1,e.length)},n.prototype.sign=function(e){var t=this.options.signingSchemeOptions.hash||DEFAULT_HASH_FUNCTION;if("browser"===this.options.environment){t=SIGN_ALG_TO_HASH_ALIASES[t]||t;var n=crypt.createHash(t);n.update(e);var r=this.pkcs1pad(n.digest(),t);return this.key.$doPrivate(new BigInteger(r)).toBuffer(this.key.encryptedDataLength)}var o=crypt.createSign("RSA-"+t.toUpperCase());return o.update(e),o.sign(this.options.rsaUtils.exportKey("private"))},n.prototype.verify=function(e,t,n){if(this.options.encryptionSchemeOptions&&this.options.encryptionSchemeOptions.padding==constants.RSA_NO_PADDING)return!1;var r=this.options.signingSchemeOptions.hash||DEFAULT_HASH_FUNCTION;if("browser"===this.options.environment){r=SIGN_ALG_TO_HASH_ALIASES[r]||r,n&&(t=Buffer.from(t,n));var o=crypt.createHash(r);o.update(e);var i=this.pkcs1pad(o.digest(),r);return this.key.$doPublic(new BigInteger(t)).toBuffer().toString("hex")==i.toString("hex")}var s=crypt.createVerify("RSA-"+r.toUpperCase());return s.update(e),s.verify(this.options.rsaUtils.exportKey("public"),t,n)},n.prototype.pkcs0pad=function(e){var t=Buffer.alloc(this.key.maxMessageLength-e.length);return t.fill(0),Buffer.concat([t,e])},n.prototype.pkcs0unpad=function(e){return"function"==typeof e.lastIndexOf?e.slice(e.lastIndexOf("\0")+1,e.length):e.slice(String.prototype.lastIndexOf.call(e,"\0")+1,e.length)},n.prototype.pkcs1pad=function(e,t){var n=SIGN_INFO_HEAD[t];if(!n)throw Error("Unsupported hash algorithm");var r=Buffer.concat([n,e]);if(r.length+10>this.key.encryptedDataLength)throw Error("Key is too short for signing algorithm ("+t+")");var o=Buffer.alloc(this.key.encryptedDataLength-r.length-1);return o.fill(255,0,o.length-1),o[0]=1,o[o.length-1]=0,Buffer.concat([o,r])},new n(e,t)};