7746 lines
205 KiB
JavaScript
7746 lines
205 KiB
JavaScript
|
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ethers = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||
|
// See: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
|
||
|
// See: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
|
||
|
|
||
|
/*
|
||
|
var secp256k1 = (function() {
|
||
|
var secp256k1 = require('elliptic/lib/elliptic/presetcurves/secp256k1-nopre');
|
||
|
var PresetCurve = require('elliptic/lib/elliptic/presetcurve');
|
||
|
var EC = require('elliptic/lib/elliptic/ec');
|
||
|
|
||
|
return new EC(new PresetCurve(secp256k1));
|
||
|
})();
|
||
|
*/
|
||
|
|
||
|
var secp256k1 = new (require('elliptic')).ec('secp256k1');
|
||
|
|
||
|
var wordlist = (function() {
|
||
|
var words = require('./words.json');
|
||
|
return words.replace(/([A-Z])/g, ' $1').toLowerCase().substring(1).split(' ');
|
||
|
})();
|
||
|
|
||
|
var utils = (function() {
|
||
|
var convert = require('ethers-utils/convert.js');
|
||
|
|
||
|
var sha2 = require('ethers-utils/sha2');
|
||
|
|
||
|
var hmac = require('ethers-utils/hmac');
|
||
|
|
||
|
return {
|
||
|
defineProperty: require('ethers-utils/properties.js').defineProperty,
|
||
|
|
||
|
arrayify: convert.arrayify,
|
||
|
bigNumberify: require('ethers-utils/bignumber.js').bigNumberify,
|
||
|
hexlify: convert.hexlify,
|
||
|
|
||
|
toUtf8Bytes: require('ethers-utils/utf8.js').toUtf8Bytes,
|
||
|
|
||
|
sha256: sha2.sha256,
|
||
|
createSha512Hmac: hmac.createSha512Hmac,
|
||
|
|
||
|
pbkdf2: require('ethers-utils/pbkdf2.js'),
|
||
|
}
|
||
|
})();
|
||
|
|
||
|
// "Bitcoin seed"
|
||
|
var MasterSecret = utils.toUtf8Bytes('Bitcoin seed');
|
||
|
|
||
|
var HardenedBit = 0x80000000;
|
||
|
|
||
|
// Returns a byte with the MSB bits set
|
||
|
function getUpperMask(bits) {
|
||
|
return ((1 << bits) - 1) << (8 - bits);
|
||
|
}
|
||
|
|
||
|
// Returns a byte with the LSB bits set
|
||
|
function getLowerMask(bits) {
|
||
|
return (1 << bits) - 1;
|
||
|
}
|
||
|
|
||
|
function HDNode(keyPair, chainCode, index, depth) {
|
||
|
if (!(this instanceof HDNode)) { throw new Error('missing new'); }
|
||
|
|
||
|
utils.defineProperty(this, '_keyPair', keyPair);
|
||
|
|
||
|
utils.defineProperty(this, 'privateKey', utils.hexlify(keyPair.priv.toArray('be', 32)));
|
||
|
utils.defineProperty(this, 'publicKey', '0x' + keyPair.getPublic(true, 'hex'));
|
||
|
|
||
|
utils.defineProperty(this, 'chainCode', utils.hexlify(chainCode));
|
||
|
|
||
|
utils.defineProperty(this, 'index', index);
|
||
|
utils.defineProperty(this, 'depth', depth);
|
||
|
}
|
||
|
|
||
|
utils.defineProperty(HDNode.prototype, '_derive', function(index) {
|
||
|
|
||
|
// Public parent key -> public child key
|
||
|
if (!this.privateKey) {
|
||
|
if (index >= HardenedBit) { throw new Error('cannot derive child of neutered node'); }
|
||
|
throw new Error('not implemented');
|
||
|
}
|
||
|
|
||
|
var data = new Uint8Array(37);
|
||
|
|
||
|
if (index & HardenedBit) {
|
||
|
// Data = 0x00 || ser_256(k_par)
|
||
|
data.set(utils.arrayify(this.privateKey), 1);
|
||
|
|
||
|
} else {
|
||
|
// Data = ser_p(point(k_par))
|
||
|
data.set(this._keyPair.getPublic().encode(null, true));
|
||
|
}
|
||
|
|
||
|
// Data += ser_32(i)
|
||
|
for (var i = 24; i >= 0; i -= 8) { data[33 + (i >> 3)] = ((index >> (24 - i)) & 0xff); }
|
||
|
|
||
|
var I = utils.createSha512Hmac(this.chainCode).update(data).digest();
|
||
|
var IL = utils.bigNumberify(I.slice(0, 32));
|
||
|
var IR = I.slice(32);
|
||
|
|
||
|
var ki = IL.add('0x' + this._keyPair.getPrivate('hex')).mod('0x' + secp256k1.curve.n.toString(16));
|
||
|
|
||
|
return new HDNode(secp256k1.keyFromPrivate(utils.arrayify(ki)), I.slice(32), index, this.depth + 1);
|
||
|
});
|
||
|
|
||
|
utils.defineProperty(HDNode.prototype, 'derivePath', function(path) {
|
||
|
var components = path.split('/');
|
||
|
|
||
|
if (components.length === 0 || (components[0] === 'm' && this.depth !== 0)) {
|
||
|
throw new Error('invalid path');
|
||
|
}
|
||
|
|
||
|
if (components[0] === 'm') { components.shift(); }
|
||
|
|
||
|
var result = this;
|
||
|
for (var i = 0; i < components.length; i++) {
|
||
|
var component = components[i];
|
||
|
if (component.match(/^[0-9]+'$/)) {
|
||
|
var index = parseInt(component.substring(0, component.length - 1));
|
||
|
if (index >= HardenedBit) { throw new Error('invalid path index - ' + component); }
|
||
|
result = result._derive(HardenedBit + index);
|
||
|
} else if (component.match(/^[0-9]+$/)) {
|
||
|
var index = parseInt(component);
|
||
|
if (index >= HardenedBit) { throw new Error('invalid path index - ' + component); }
|
||
|
result = result._derive(index);
|
||
|
} else {
|
||
|
throw new Error('invlaid path component - ' + component);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
});
|
||
|
|
||
|
utils.defineProperty(HDNode, 'fromMnemonic', function(mnemonic) {
|
||
|
// Check that the checksum s valid (will throw an error)
|
||
|
mnemonicToEntropy(mnemonic);
|
||
|
|
||
|
return HDNode.fromSeed(mnemonicToSeed(mnemonic));
|
||
|
});
|
||
|
|
||
|
utils.defineProperty(HDNode, 'fromSeed', function(seed) {
|
||
|
seed = utils.arrayify(seed);
|
||
|
if (seed.length < 16 || seed.length > 64) { throw new Error('invalid seed'); }
|
||
|
|
||
|
var I = utils.createSha512Hmac(MasterSecret).update(seed).digest();
|
||
|
|
||
|
return new HDNode(secp256k1.keyFromPrivate(I.slice(0, 32)), I.slice(32), 0, 0, 0);
|
||
|
});
|
||
|
|
||
|
function mnemonicToSeed(mnemonic, password) {
|
||
|
|
||
|
if (!password) {
|
||
|
password = '';
|
||
|
|
||
|
} else if (password.normalize) {
|
||
|
password = password.normalize('NFKD');
|
||
|
|
||
|
} else {
|
||
|
for (var i = 0; i < password.length; i++) {
|
||
|
var c = password.charCodeAt(i);
|
||
|
if (c < 32 || c > 127) { throw new Error('passwords with non-ASCII characters not supported in this environment'); }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
mnemonic = utils.toUtf8Bytes(mnemonic, 'NFKD');
|
||
|
var salt = utils.toUtf8Bytes('mnemonic' + password, 'NFKD');
|
||
|
|
||
|
return utils.hexlify(utils.pbkdf2(mnemonic, salt, 2048, 64, utils.createSha512Hmac));
|
||
|
}
|
||
|
|
||
|
function mnemonicToEntropy(mnemonic) {
|
||
|
var words = mnemonic.toLowerCase().split(' ');
|
||
|
if ((words.length % 3) !== 0) { throw new Error('invalid mnemonic'); }
|
||
|
|
||
|
var entropy = new Uint8Array(Math.ceil(11 * words.length / 8));
|
||
|
|
||
|
var offset = 0;
|
||
|
for (var i = 0; i < words.length; i++) {
|
||
|
var index = wordlist.indexOf(words[i]);
|
||
|
if (index === -1) { throw new Error('invalid mnemonic'); }
|
||
|
|
||
|
for (var bit = 0; bit < 11; bit++) {
|
||
|
if (index & (1 << (10 - bit))) {
|
||
|
entropy[offset >> 3] |= (1 << (7 - (offset % 8)));
|
||
|
}
|
||
|
offset++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var entropyBits = 32 * words.length / 3;
|
||
|
|
||
|
var checksumBits = words.length / 3;
|
||
|
var checksumMask = getUpperMask(checksumBits);
|
||
|
|
||
|
var checksum = utils.arrayify(utils.sha256(entropy.slice(0, entropyBits / 8)))[0];
|
||
|
checksum &= checksumMask;
|
||
|
|
||
|
if (checksum !== (entropy[entropy.length - 1] & checksumMask)) {
|
||
|
throw new Error('invalid checksum');
|
||
|
}
|
||
|
|
||
|
return utils.hexlify(entropy.slice(0, entropyBits / 8));
|
||
|
}
|
||
|
|
||
|
function entropyToMnemonic(entropy) {
|
||
|
entropy = utils.arrayify(entropy);
|
||
|
|
||
|
if ((entropy.length % 4) !== 0 || entropy.length < 16 || entropy.length > 32) {
|
||
|
throw new Error('invalid entropy');
|
||
|
}
|
||
|
|
||
|
var words = [0];
|
||
|
|
||
|
var remainingBits = 11;
|
||
|
for (var i = 0; i < entropy.length; i++) {
|
||
|
|
||
|
// Consume the whole byte (with still more to go)
|
||
|
if (remainingBits > 8) {
|
||
|
words[words.length - 1] <<= 8;
|
||
|
words[words.length - 1] |= entropy[i];
|
||
|
|
||
|
remainingBits -= 8;
|
||
|
|
||
|
// This byte will complete an 11-bit index
|
||
|
} else {
|
||
|
words[words.length - 1] <<= remainingBits;
|
||
|
words[words.length - 1] |= entropy[i] >> (8 - remainingBits);
|
||
|
|
||
|
// Start the next word
|
||
|
words.push(entropy[i] & getLowerMask(8 - remainingBits));
|
||
|
|
||
|
remainingBits += 3;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Compute the checksum bits
|
||
|
var checksum = utils.arrayify(utils.sha256(entropy))[0];
|
||
|
var checksumBits = entropy.length / 4;
|
||
|
checksum &= getUpperMask(checksumBits);
|
||
|
|
||
|
// Shift the checksum into the word indices
|
||
|
words[words.length - 1] <<= checksumBits;
|
||
|
words[words.length - 1] |= (checksum >> (8 - checksumBits));
|
||
|
|
||
|
// Convert indices into words
|
||
|
for (var i = 0; i < words.length; i++) {
|
||
|
words[i] = wordlist[words[i]];
|
||
|
}
|
||
|
|
||
|
return words.join(' ');
|
||
|
}
|
||
|
|
||
|
function validMnemonic(mnemonic) {
|
||
|
try {
|
||
|
mnemonicToEntropy(mnemonic);
|
||
|
return true;
|
||
|
} catch (error) { }
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
fromMnemonic: HDNode.fromMnemonic,
|
||
|
fromSeed: HDNode.fromSeed,
|
||
|
|
||
|
mnemonicToEntropy: mnemonicToEntropy,
|
||
|
entropyToMnemonic: entropyToMnemonic,
|
||
|
mnemonicToSeed: mnemonicToSeed,
|
||
|
|
||
|
validMnemonic: validMnemonic,
|
||
|
};
|
||
|
|
||
|
|
||
|
},{"./words.json":2,"elliptic":6,"ethers-utils/bignumber.js":30,"ethers-utils/convert.js":31,"ethers-utils/hmac":32,"ethers-utils/pbkdf2.js":41,"ethers-utils/properties.js":42,"ethers-utils/sha2":43,"ethers-utils/utf8.js":44}],2:[function(require,module,exports){
|
||
|
module.exports="AbandonAbilityAbleAboutAboveAbsentAbsorbAbstractAbsurdAbuseAccessAccidentAccountAccuseAchieveAcidAcousticAcquireAcrossActActionActorActressActualAdaptAddAddictAddressAdjustAdmitAdultAdvanceAdviceAerobicAffairAffordAfraidAgainAgeAgentAgreeAheadAimAirAirportAisleAlarmAlbumAlcoholAlertAlienAllAlleyAllowAlmostAloneAlphaAlreadyAlsoAlterAlwaysAmateurAmazingAmongAmountAmusedAnalystAnchorAncientAngerAngleAngryAnimalAnkleAnnounceAnnualAnotherAnswerAntennaAntiqueAnxietyAnyApartApologyAppearAppleApproveAprilArchArcticAreaArenaArgueArmArmedArmorArmyAroundArrangeArrestArriveArrowArtArtefactArtistArtworkAskAspectAssaultAssetAssistAssumeAsthmaAthleteAtomAttackAttendAttitudeAttractAuctionAuditAugustAuntAuthorAutoAutumnAverageAvocadoAvoidAwakeAwareAwayAwesomeAwfulAwkwardAxisBabyBachelorBaconBadgeBagBalanceBalconyBallBambooBananaBannerBarBarelyBargainBarrelBaseBasicBasketBattleBeachBeanBeautyBecauseBecomeBeefBeforeBeginBehaveBehindBelieveBelowBeltBenchBenefitBestBetrayBetterBetweenBeyondBicycleBidBikeBindBiologyBirdBirthBitterBlackBladeBlameBlanketBlastBleakBlessBlindBloodBlossomBlouseBlueBlurBlushBoardBoatBodyBoilBombBoneBonusBookBoostBorderBoringBorrowBossBottomBounceBoxBoyBracketBrainBrandBrassBraveBreadBreezeBrickBridgeBriefBrightBringBriskBroccoliBrokenBronzeBroomBrotherBrownBrushBubbleBuddyBudgetBuffaloBuildBulbBulkBulletBundleBunkerBurdenBurgerBurstBusBusinessBusyButterBuyerBuzzCabbageCabinCableCactusCageCakeCallCalmCameraCampCanCanalCancelCandyCannonCanoeCanvasCanyonCapableCapitalCaptainCarCarbonCardCargoCarpetCarryCartCaseCashCasinoCastleCasualCatCatalogCatchCategoryCattleCaughtCauseCautionCaveCeilingCeleryCementCensusCenturyCerealCertainChairChalkChampionChangeChaosChapterChargeChaseChatCheapCheckCheeseChefCherryChestChickenChiefChildChimneyChoiceChooseChronicChuckleChunkChurnCigarCinnamonCircleCitizenCityCivilClaimClapClarifyClawClayCleanClerkCleverClickClientCliffClimbClinicClipClockClogCloseClothCloudClownClubClumpClusterClutchCoachCoastCoconutCodeCoffeeCoilCoinCollectColorColumnCombineComeComfortComicCommonCompanyConcertConductConfirmCongressConnectConsiderControlConvinceCookCoolCopperCopyCoralCoreCornCorrectCostCottonCouchCountryCoupleCourseCousinCoverCoyoteCrackCradleCraftCramCraneCrashCraterCrawlCrazyCreamCreditCreekCrewCricketCrimeCrispCriticCropCrossCrouchCrowdCrucialCruelCruiseCrumbleCrunchCrushCryCrystalCubeCultureCupCupboardCuriousCurrentCurtainCurveCushionCustomCuteCycleDadDamageDampDanceDangerDaringDashDaughterDawnDayDealDebateDebrisDecadeDecemberDecideDeclineDecorateDecreaseDeerDefenseDefineDefyDegreeDelayDeliverDemandDemiseDenialDentistDenyDepartDependDepositDepthDeputyDeriveDescribeDesertDesignDeskDespairDestroyDetailDetectDevelopDeviceDevoteDiagramDialDiamondDiaryDiceDieselDietDifferDigitalDignityDilemmaDinnerDinosaurDirectDirtDisagreeDiscoverDiseaseDishDismissDisorderDisplayDistanceDivertDivideDivorceDizzyDoctorDocumentDogDollDolphinDomainDonateDonkeyDonorDoorDoseDoubleDoveDraftDragonDramaDrasticDrawDreamDressDriftDrillDrinkDripDriveDropDrumDryDuckDumbDuneDuringDustDutchDutyDwarfDynamicEagerEagleEarlyEarnEarthEasilyEastEasyEchoEcologyEconomyEdgeEditEducateEffortEggEightEitherElbowElderElectricElegantElementElephantElevatorEliteElseEmbarkEmbodyEmbraceEmergeEmotionEmployEmpowerEmptyEnableEnactEndEndlessEndorseEnemyEnergyEnforceEngageEngineEnhanceEnjoyEnlistEnoughEnrichEnrollEnsureEnterEntireEntryEnvelopeEpisodeEqualEquipEraEraseErodeErosionErrorEruptEscapeEssayEssenceEstateEternalEthicsEvidenceEvilEvokeEvolveExactExampleExcessExchangeExciteExcludeExcuseExecuteExerciseExhaustExhibitExileExistExitExoticExpandExpectExpireExplainExposeExpressExtendExtraEyeEyebrowFabricFaceFacultyFadeFaintFaithFallFalseFameFamilyFamousFanFancyFantasyFarmFashionFatFatalFatherFatigueFaultFavoriteFeatureFebruaryFederalFeeFeedFeelFemaleFenceFestivalFetchFeverFewFiberFictionFieldFigureFileFilmFilterFinalFindFineFingerFinishFireFirmFirstFiscalFishFitFitnessFixFlagFlameFlashFlatFlavorFleeFlightFlipFloatFlockFloorFlowerFluidFlushFlyFoamFocusFogFoilFoldFollowFoodFootForceForestForgetForkFortuneForumForwardFossilFosterFoundFox
|
||
|
|
||
|
},{}],3:[function(require,module,exports){
|
||
|
(function (module, exports) {
|
||
|
'use strict';
|
||
|
|
||
|
// Utils
|
||
|
function assert (val, msg) {
|
||
|
if (!val) throw new Error(msg || 'Assertion failed');
|
||
|
}
|
||
|
|
||
|
// Could use `inherits` module, but don't want to move from single file
|
||
|
// architecture yet.
|
||
|
function inherits (ctor, superCtor) {
|
||
|
ctor.super_ = superCtor;
|
||
|
var TempCtor = function () {};
|
||
|
TempCtor.prototype = superCtor.prototype;
|
||
|
ctor.prototype = new TempCtor();
|
||
|
ctor.prototype.constructor = ctor;
|
||
|
}
|
||
|
|
||
|
// BN
|
||
|
|
||
|
function BN (number, base, endian) {
|
||
|
if (BN.isBN(number)) {
|
||
|
return number;
|
||
|
}
|
||
|
|
||
|
this.negative = 0;
|
||
|
this.words = null;
|
||
|
this.length = 0;
|
||
|
|
||
|
// Reduction context
|
||
|
this.red = null;
|
||
|
|
||
|
if (number !== null) {
|
||
|
if (base === 'le' || base === 'be') {
|
||
|
endian = base;
|
||
|
base = 10;
|
||
|
}
|
||
|
|
||
|
this._init(number || 0, base || 10, endian || 'be');
|
||
|
}
|
||
|
}
|
||
|
if (typeof module === 'object') {
|
||
|
module.exports = BN;
|
||
|
} else {
|
||
|
exports.BN = BN;
|
||
|
}
|
||
|
|
||
|
BN.BN = BN;
|
||
|
BN.wordSize = 26;
|
||
|
|
||
|
var Buffer;
|
||
|
try {
|
||
|
Buffer = require('buf' + 'fer').Buffer;
|
||
|
} catch (e) {
|
||
|
}
|
||
|
|
||
|
BN.isBN = function isBN (num) {
|
||
|
if (num instanceof BN) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return num !== null && typeof num === 'object' &&
|
||
|
num.constructor.wordSize === BN.wordSize && Array.isArray(num.words);
|
||
|
};
|
||
|
|
||
|
BN.max = function max (left, right) {
|
||
|
if (left.cmp(right) > 0) return left;
|
||
|
return right;
|
||
|
};
|
||
|
|
||
|
BN.min = function min (left, right) {
|
||
|
if (left.cmp(right) < 0) return left;
|
||
|
return right;
|
||
|
};
|
||
|
|
||
|
BN.prototype._init = function init (number, base, endian) {
|
||
|
if (typeof number === 'number') {
|
||
|
return this._initNumber(number, base, endian);
|
||
|
}
|
||
|
|
||
|
if (typeof number === 'object') {
|
||
|
return this._initArray(number, base, endian);
|
||
|
}
|
||
|
|
||
|
if (base === 'hex') {
|
||
|
base = 16;
|
||
|
}
|
||
|
assert(base === (base | 0) && base >= 2 && base <= 36);
|
||
|
|
||
|
number = number.toString().replace(/\s+/g, '');
|
||
|
var start = 0;
|
||
|
if (number[0] === '-') {
|
||
|
start++;
|
||
|
}
|
||
|
|
||
|
if (base === 16) {
|
||
|
this._parseHex(number, start);
|
||
|
} else {
|
||
|
this._parseBase(number, base, start);
|
||
|
}
|
||
|
|
||
|
if (number[0] === '-') {
|
||
|
this.negative = 1;
|
||
|
}
|
||
|
|
||
|
this.strip();
|
||
|
|
||
|
if (endian !== 'le') return;
|
||
|
|
||
|
this._initArray(this.toArray(), base, endian);
|
||
|
};
|
||
|
|
||
|
BN.prototype._initNumber = function _initNumber (number, base, endian) {
|
||
|
if (number < 0) {
|
||
|
this.negative = 1;
|
||
|
number = -number;
|
||
|
}
|
||
|
if (number < 0x4000000) {
|
||
|
this.words = [ number & 0x3ffffff ];
|
||
|
this.length = 1;
|
||
|
} else if (number < 0x10000000000000) {
|
||
|
this.words = [
|
||
|
number & 0x3ffffff,
|
||
|
(number / 0x4000000) & 0x3ffffff
|
||
|
];
|
||
|
this.length = 2;
|
||
|
} else {
|
||
|
assert(number < 0x20000000000000); // 2 ^ 53 (unsafe)
|
||
|
this.words = [
|
||
|
number & 0x3ffffff,
|
||
|
(number / 0x4000000) & 0x3ffffff,
|
||
|
1
|
||
|
];
|
||
|
this.length = 3;
|
||
|
}
|
||
|
|
||
|
if (endian !== 'le') return;
|
||
|
|
||
|
// Reverse the bytes
|
||
|
this._initArray(this.toArray(), base, endian);
|
||
|
};
|
||
|
|
||
|
BN.prototype._initArray = function _initArray (number, base, endian) {
|
||
|
// Perhaps a Uint8Array
|
||
|
assert(typeof number.length === 'number');
|
||
|
if (number.length <= 0) {
|
||
|
this.words = [ 0 ];
|
||
|
this.length = 1;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
this.length = Math.ceil(number.length / 3);
|
||
|
this.words = new Array(this.length);
|
||
|
for (var i = 0; i < this.length; i++) {
|
||
|
this.words[i] = 0;
|
||
|
}
|
||
|
|
||
|
var j, w;
|
||
|
var off = 0;
|
||
|
if (endian === 'be') {
|
||
|
for (i = number.length - 1, j = 0; i >= 0; i -= 3) {
|
||
|
w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16);
|
||
|
this.words[j] |= (w << off) & 0x3ffffff;
|
||
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
||
|
off += 24;
|
||
|
if (off >= 26) {
|
||
|
off -= 26;
|
||
|
j++;
|
||
|
}
|
||
|
}
|
||
|
} else if (endian === 'le') {
|
||
|
for (i = 0, j = 0; i < number.length; i += 3) {
|
||
|
w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16);
|
||
|
this.words[j] |= (w << off) & 0x3ffffff;
|
||
|
this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff;
|
||
|
off += 24;
|
||
|
if (off >= 26) {
|
||
|
off -= 26;
|
||
|
j++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return this.strip();
|
||
|
};
|
||
|
|
||
|
function parseHex (str, start, end) {
|
||
|
var r = 0;
|
||
|
var len = Math.min(str.length, end);
|
||
|
for (var i = start; i < len; i++) {
|
||
|
var c = str.charCodeAt(i) - 48;
|
||
|
|
||
|
r <<= 4;
|
||
|
|
||
|
// 'a' - 'f'
|
||
|
if (c >= 49 && c <= 54) {
|
||
|
r |= c - 49 + 0xa;
|
||
|
|
||
|
// 'A' - 'F'
|
||
|
} else if (c >= 17 && c <= 22) {
|
||
|
r |= c - 17 + 0xa;
|
||
|
|
||
|
// '0' - '9'
|
||
|
} else {
|
||
|
r |= c & 0xf;
|
||
|
}
|
||
|
}
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
BN.prototype._parseHex = function _parseHex (number, start) {
|
||
|
// Create possibly bigger array to ensure that it fits the number
|
||
|
this.length = Math.ceil((number.length - start) / 6);
|
||
|
this.words = new Array(this.length);
|
||
|
for (var i = 0; i < this.length; i++) {
|
||
|
this.words[i] = 0;
|
||
|
}
|
||
|
|
||
|
var j, w;
|
||
|
// Scan 24-bit chunks and add them to the number
|
||
|
var off = 0;
|
||
|
for (i = number.length - 6, j = 0; i >= start; i -= 6) {
|
||
|
w = parseHex(number, i, i + 6);
|
||
|
this.words[j] |= (w << off) & 0x3ffffff;
|
||
|
// NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb
|
||
|
this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
|
||
|
off += 24;
|
||
|
if (off >= 26) {
|
||
|
off -= 26;
|
||
|
j++;
|
||
|
}
|
||
|
}
|
||
|
if (i + 6 !== start) {
|
||
|
w = parseHex(number, start, i + 6);
|
||
|
this.words[j] |= (w << off) & 0x3ffffff;
|
||
|
this.words[j + 1] |= w >>> (26 - off) & 0x3fffff;
|
||
|
}
|
||
|
this.strip();
|
||
|
};
|
||
|
|
||
|
function parseBase (str, start, end, mul) {
|
||
|
var r = 0;
|
||
|
var len = Math.min(str.length, end);
|
||
|
for (var i = start; i < len; i++) {
|
||
|
var c = str.charCodeAt(i) - 48;
|
||
|
|
||
|
r *= mul;
|
||
|
|
||
|
// 'a'
|
||
|
if (c >= 49) {
|
||
|
r += c - 49 + 0xa;
|
||
|
|
||
|
// 'A'
|
||
|
} else if (c >= 17) {
|
||
|
r += c - 17 + 0xa;
|
||
|
|
||
|
// '0' - '9'
|
||
|
} else {
|
||
|
r += c;
|
||
|
}
|
||
|
}
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
BN.prototype._parseBase = function _parseBase (number, base, start) {
|
||
|
// Initialize as zero
|
||
|
this.words = [ 0 ];
|
||
|
this.length = 1;
|
||
|
|
||
|
// Find length of limb in base
|
||
|
for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) {
|
||
|
limbLen++;
|
||
|
}
|
||
|
limbLen--;
|
||
|
limbPow = (limbPow / base) | 0;
|
||
|
|
||
|
var total = number.length - start;
|
||
|
var mod = total % limbLen;
|
||
|
var end = Math.min(total, total - mod) + start;
|
||
|
|
||
|
var word = 0;
|
||
|
for (var i = start; i < end; i += limbLen) {
|
||
|
word = parseBase(number, i, i + limbLen, base);
|
||
|
|
||
|
this.imuln(limbPow);
|
||
|
if (this.words[0] + word < 0x4000000) {
|
||
|
this.words[0] += word;
|
||
|
} else {
|
||
|
this._iaddn(word);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (mod !== 0) {
|
||
|
var pow = 1;
|
||
|
word = parseBase(number, i, number.length, base);
|
||
|
|
||
|
for (i = 0; i < mod; i++) {
|
||
|
pow *= base;
|
||
|
}
|
||
|
|
||
|
this.imuln(pow);
|
||
|
if (this.words[0] + word < 0x4000000) {
|
||
|
this.words[0] += word;
|
||
|
} else {
|
||
|
this._iaddn(word);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
BN.prototype.copy = function copy (dest) {
|
||
|
dest.words = new Array(this.length);
|
||
|
for (var i = 0; i < this.length; i++) {
|
||
|
dest.words[i] = this.words[i];
|
||
|
}
|
||
|
dest.length = this.length;
|
||
|
dest.negative = this.negative;
|
||
|
dest.red = this.red;
|
||
|
};
|
||
|
|
||
|
BN.prototype.clone = function clone () {
|
||
|
var r = new BN(null);
|
||
|
this.copy(r);
|
||
|
return r;
|
||
|
};
|
||
|
|
||
|
BN.prototype._expand = function _expand (size) {
|
||
|
while (this.length < size) {
|
||
|
this.words[this.length++] = 0;
|
||
|
}
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
// Remove leading `0` from `this`
|
||
|
BN.prototype.strip = function strip () {
|
||
|
while (this.length > 1 && this.words[this.length - 1] === 0) {
|
||
|
this.length--;
|
||
|
}
|
||
|
return this._normSign();
|
||
|
};
|
||
|
|
||
|
BN.prototype._normSign = function _normSign () {
|
||
|
// -0 = 0
|
||
|
if (this.length === 1 && this.words[0] === 0) {
|
||
|
this.negative = 0;
|
||
|
}
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
BN.prototype.inspect = function inspect () {
|
||
|
return (this.red ? '<BN-R: ' : '<BN: ') + this.toString(16) + '>';
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
|
||
|
var zeros = [];
|
||
|
var groupSizes = [];
|
||
|
var groupBases = [];
|
||
|
|
||
|
var s = '';
|
||
|
var i = -1;
|
||
|
while (++i < BN.wordSize) {
|
||
|
zeros[i] = s;
|
||
|
s += '0';
|
||
|
}
|
||
|
groupSizes[0] = 0;
|
||
|
groupSizes[1] = 0;
|
||
|
groupBases[0] = 0;
|
||
|
groupBases[1] = 0;
|
||
|
var base = 2 - 1;
|
||
|
while (++base < 36 + 1) {
|
||
|
var groupSize = 0;
|
||
|
var groupBase = 1;
|
||
|
while (groupBase < (1 << BN.wordSize) / base) {
|
||
|
groupBase *= base;
|
||
|
groupSize += 1;
|
||
|
}
|
||
|
groupSizes[base] = groupSize;
|
||
|
groupBases[base] = groupBase;
|
||
|
}
|
||
|
|
||
|
*/
|
||
|
|
||
|
var zeros = [
|
||
|
'',
|
||
|
'0',
|
||
|
'00',
|
||
|
'000',
|
||
|
'0000',
|
||
|
'00000',
|
||
|
'000000',
|
||
|
'0000000',
|
||
|
'00000000',
|
||
|
'000000000',
|
||
|
'0000000000',
|
||
|
'00000000000',
|
||
|
'000000000000',
|
||
|
'0000000000000',
|
||
|
'00000000000000',
|
||
|
'000000000000000',
|
||
|
'0000000000000000',
|
||
|
'00000000000000000',
|
||
|
'000000000000000000',
|
||
|
'0000000000000000000',
|
||
|
'00000000000000000000',
|
||
|
'000000000000000000000',
|
||
|
'0000000000000000000000',
|
||
|
'00000000000000000000000',
|
||
|
'000000000000000000000000',
|
||
|
'0000000000000000000000000'
|
||
|
];
|
||
|
|
||
|
var groupSizes = [
|
||
|
0, 0,
|
||
|
25, 16, 12, 11, 10, 9, 8,
|
||
|
8, 7, 7, 7, 7, 6, 6,
|
||
|
6, 6, 6, 6, 6, 5, 5,
|
||
|
5, 5, 5, 5, 5, 5, 5,
|
||
|
5, 5, 5, 5, 5, 5, 5
|
||
|
];
|
||
|
|
||
|
var groupBases = [
|
||
|
0, 0,
|
||
|
33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216,
|
||
|
43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625,
|
||
|
16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632,
|
||
|
6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149,
|
||
|
24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176
|
||
|
];
|
||
|
|
||
|
BN.prototype.toString = function toString (base, padding) {
|
||
|
base = base || 10;
|
||
|
padding = padding | 0 || 1;
|
||
|
|
||
|
var out;
|
||
|
if (base === 16 || base === 'hex') {
|
||
|
out = '';
|
||
|
var off = 0;
|
||
|
var carry = 0;
|
||
|
for (var i = 0; i < this.length; i++) {
|
||
|
var w = this.words[i];
|
||
|
var word = (((w << off) | carry) & 0xffffff).toString(16);
|
||
|
carry = (w >>> (24 - off)) & 0xffffff;
|
||
|
if (carry !== 0 || i !== this.length - 1) {
|
||
|
out = zeros[6 - word.length] + word + out;
|
||
|
} else {
|
||
|
out = word + out;
|
||
|
}
|
||
|
off += 2;
|
||
|
if (off >= 26) {
|
||
|
off -= 26;
|
||
|
i--;
|
||
|
}
|
||
|
}
|
||
|
if (carry !== 0) {
|
||
|
out = carry.toString(16) + out;
|
||
|
}
|
||
|
while (out.length % padding !== 0) {
|
||
|
out = '0' + out;
|
||
|
}
|
||
|
if (this.negative !== 0) {
|
||
|
out = '-' + out;
|
||
|
}
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
if (base === (base | 0) && base >= 2 && base <= 36) {
|
||
|
// var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base));
|
||
|
var groupSize = groupSizes[base];
|
||
|
// var groupBase = Math.pow(base, groupSize);
|
||
|
var groupBase = groupBases[base];
|
||
|
out = '';
|
||
|
var c = this.clone();
|
||
|
c.negative = 0;
|
||
|
while (!c.isZero()) {
|
||
|
var r = c.modn(groupBase).toString(base);
|
||
|
c = c.idivn(groupBase);
|
||
|
|
||
|
if (!c.isZero()) {
|
||
|
out = zeros[groupSize - r.length] + r + out;
|
||
|
} else {
|
||
|
out = r + out;
|
||
|
}
|
||
|
}
|
||
|
if (this.isZero()) {
|
||
|
out = '0' + out;
|
||
|
}
|
||
|
while (out.length % padding !== 0) {
|
||
|
out = '0' + out;
|
||
|
}
|
||
|
if (this.negative !== 0) {
|
||
|
out = '-' + out;
|
||
|
}
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
assert(false, 'Base should be between 2 and 36');
|
||
|
};
|
||
|
|
||
|
BN.prototype.toNumber = function toNumber () {
|
||
|
var ret = this.words[0];
|
||
|
if (this.length === 2) {
|
||
|
ret += this.words[1] * 0x4000000;
|
||
|
} else if (this.length === 3 && this.words[2] === 0x01) {
|
||
|
// NOTE: at this stage it is known that the top bit is set
|
||
|
ret += 0x10000000000000 + (this.words[1] * 0x4000000);
|
||
|
} else if (this.length > 2) {
|
||
|
assert(false, 'Number can only safely store up to 53 bits');
|
||
|
}
|
||
|
return (this.negative !== 0) ? -ret : ret;
|
||
|
};
|
||
|
|
||
|
BN.prototype.toJSON = function toJSON () {
|
||
|
return this.toString(16);
|
||
|
};
|
||
|
|
||
|
BN.prototype.toBuffer = function toBuffer (endian, length) {
|
||
|
assert(typeof Buffer !== 'undefined');
|
||
|
return this.toArrayLike(Buffer, endian, length);
|
||
|
};
|
||
|
|
||
|
BN.prototype.toArray = function toArray (endian, length) {
|
||
|
return this.toArrayLike(Array, endian, length);
|
||
|
};
|
||
|
|
||
|
BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) {
|
||
|
var byteLength = this.byteLength();
|
||
|
var reqLength = length || Math.max(1, byteLength);
|
||
|
assert(byteLength <= reqLength, 'byte array longer than desired length');
|
||
|
assert(reqLength > 0, 'Requested array length <= 0');
|
||
|
|
||
|
this.strip();
|
||
|
var littleEndian = endian === 'le';
|
||
|
var res = new ArrayType(reqLength);
|
||
|
|
||
|
var b, i;
|
||
|
var q = this.clone();
|
||
|
if (!littleEndian) {
|
||
|
// Assume big-endian
|
||
|
for (i = 0; i < reqLength - byteLength; i++) {
|
||
|
res[i] = 0;
|
||
|
}
|
||
|
|
||
|
for (i = 0; !q.isZero(); i++) {
|
||
|
b = q.andln(0xff);
|
||
|
q.iushrn(8);
|
||
|
|
||
|
res[reqLength - i - 1] = b;
|
||
|
}
|
||
|
} else {
|
||
|
for (i = 0; !q.isZero(); i++) {
|
||
|
b = q.andln(0xff);
|
||
|
q.iushrn(8);
|
||
|
|
||
|
res[i] = b;
|
||
|
}
|
||
|
|
||
|
for (; i < reqLength; i++) {
|
||
|
res[i] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
if (Math.clz32) {
|
||
|
BN.prototype._countBits = function _countBits (w) {
|
||
|
return 32 - Math.clz32(w);
|
||
|
};
|
||
|
} else {
|
||
|
BN.prototype._countBits = function _countBits (w) {
|
||
|
var t = w;
|
||
|
var r = 0;
|
||
|
if (t >= 0x1000) {
|
||
|
r += 13;
|
||
|
t >>>= 13;
|
||
|
}
|
||
|
if (t >= 0x40) {
|
||
|
r += 7;
|
||
|
t >>>= 7;
|
||
|
}
|
||
|
if (t >= 0x8) {
|
||
|
r += 4;
|
||
|
t >>>= 4;
|
||
|
}
|
||
|
if (t >= 0x02) {
|
||
|
r += 2;
|
||
|
t >>>= 2;
|
||
|
}
|
||
|
return r + t;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
BN.prototype._zeroBits = function _zeroBits (w) {
|
||
|
// Short-cut
|
||
|
if (w === 0) return 26;
|
||
|
|
||
|
var t = w;
|
||
|
var r = 0;
|
||
|
if ((t & 0x1fff) === 0) {
|
||
|
r += 13;
|
||
|
t >>>= 13;
|
||
|
}
|
||
|
if ((t & 0x7f) === 0) {
|
||
|
r += 7;
|
||
|
t >>>= 7;
|
||
|
}
|
||
|
if ((t & 0xf) === 0) {
|
||
|
r += 4;
|
||
|
t >>>= 4;
|
||
|
}
|
||
|
if ((t & 0x3) === 0) {
|
||
|
r += 2;
|
||
|
t >>>= 2;
|
||
|
}
|
||
|
if ((t & 0x1) === 0) {
|
||
|
r++;
|
||
|
}
|
||
|
return r;
|
||
|
};
|
||
|
|
||
|
// Return number of used bits in a BN
|
||
|
BN.prototype.bitLength = function bitLength () {
|
||
|
var w = this.words[this.length - 1];
|
||
|
var hi = this._countBits(w);
|
||
|
return (this.length - 1) * 26 + hi;
|
||
|
};
|
||
|
|
||
|
function toBitArray (num) {
|
||
|
var w = new Array(num.bitLength());
|
||
|
|
||
|
for (var bit = 0; bit < w.length; bit++) {
|
||
|
var off = (bit / 26) | 0;
|
||
|
var wbit = bit % 26;
|
||
|
|
||
|
w[bit] = (num.words[off] & (1 << wbit)) >>> wbit;
|
||
|
}
|
||
|
|
||
|
return w;
|
||
|
}
|
||
|
|
||
|
// Number of trailing zero bits
|
||
|
BN.prototype.zeroBits = function zeroBits () {
|
||
|
if (this.isZero()) return 0;
|
||
|
|
||
|
var r = 0;
|
||
|
for (var i = 0; i < this.length; i++) {
|
||
|
var b = this._zeroBits(this.words[i]);
|
||
|
r += b;
|
||
|
if (b !== 26) break;
|
||
|
}
|
||
|
return r;
|
||
|
};
|
||
|
|
||
|
BN.prototype.byteLength = function byteLength () {
|
||
|
return Math.ceil(this.bitLength() / 8);
|
||
|
};
|
||
|
|
||
|
BN.prototype.toTwos = function toTwos (width) {
|
||
|
if (this.negative !== 0) {
|
||
|
return this.abs().inotn(width).iaddn(1);
|
||
|
}
|
||
|
return this.clone();
|
||
|
};
|
||
|
|
||
|
BN.prototype.fromTwos = function fromTwos (width) {
|
||
|
if (this.testn(width - 1)) {
|
||
|
return this.notn(width).iaddn(1).ineg();
|
||
|
}
|
||
|
return this.clone();
|
||
|
};
|
||
|
|
||
|
BN.prototype.isNeg = function isNeg () {
|
||
|
return this.negative !== 0;
|
||
|
};
|
||
|
|
||
|
// Return negative clone of `this`
|
||
|
BN.prototype.neg = function neg () {
|
||
|
return this.clone().ineg();
|
||
|
};
|
||
|
|
||
|
BN.prototype.ineg = function ineg () {
|
||
|
if (!this.isZero()) {
|
||
|
this.negative ^= 1;
|
||
|
}
|
||
|
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
// Or `num` with `this` in-place
|
||
|
BN.prototype.iuor = function iuor (num) {
|
||
|
while (this.length < num.length) {
|
||
|
this.words[this.length++] = 0;
|
||
|
}
|
||
|
|
||
|
for (var i = 0; i < num.length; i++) {
|
||
|
this.words[i] = this.words[i] | num.words[i];
|
||
|
}
|
||
|
|
||
|
return this.strip();
|
||
|
};
|
||
|
|
||
|
BN.prototype.ior = function ior (num) {
|
||
|
assert((this.negative | num.negative) === 0);
|
||
|
return this.iuor(num);
|
||
|
};
|
||
|
|
||
|
// Or `num` with `this`
|
||
|
BN.prototype.or = function or (num) {
|
||
|
if (this.length > num.length) return this.clone().ior(num);
|
||
|
return num.clone().ior(this);
|
||
|
};
|
||
|
|
||
|
BN.prototype.uor = function uor (num) {
|
||
|
if (this.length > num.length) return this.clone().iuor(num);
|
||
|
return num.clone().iuor(this);
|
||
|
};
|
||
|
|
||
|
// And `num` with `this` in-place
|
||
|
BN.prototype.iuand = function iuand (num) {
|
||
|
// b = min-length(num, this)
|
||
|
var b;
|
||
|
if (this.length > num.length) {
|
||
|
b = num;
|
||
|
} else {
|
||
|
b = this;
|
||
|
}
|
||
|
|
||
|
for (var i = 0; i < b.length; i++) {
|
||
|
this.words[i] = this.words[i] & num.words[i];
|
||
|
}
|
||
|
|
||
|
this.length = b.length;
|
||
|
|
||
|
return this.strip();
|
||
|
};
|
||
|
|
||
|
BN.prototype.iand = function iand (num) {
|
||
|
assert((this.negative | num.negative) === 0);
|
||
|
return this.iuand(num);
|
||
|
};
|
||
|
|
||
|
// And `num` with `this`
|
||
|
BN.prototype.and = function and (num) {
|
||
|
if (this.length > num.length) return this.clone().iand(num);
|
||
|
return num.clone().iand(this);
|
||
|
};
|
||
|
|
||
|
BN.prototype.uand = function uand (num) {
|
||
|
if (this.length > num.length) return this.clone().iuand(num);
|
||
|
return num.clone().iuand(this);
|
||
|
};
|
||
|
|
||
|
// Xor `num` with `this` in-place
|
||
|
BN.prototype.iuxor = function iuxor (num) {
|
||
|
// a.length > b.length
|
||
|
var a;
|
||
|
var b;
|
||
|
if (this.length > num.length) {
|
||
|
a = this;
|
||
|
b = num;
|
||
|
} else {
|
||
|
a = num;
|
||
|
b = this;
|
||
|
}
|
||
|
|
||
|
for (var i = 0; i < b.length; i++) {
|
||
|
this.words[i] = a.words[i] ^ b.words[i];
|
||
|
}
|
||
|
|
||
|
if (this !== a) {
|
||
|
for (; i < a.length; i++) {
|
||
|
this.words[i] = a.words[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.length = a.length;
|
||
|
|
||
|
return this.strip();
|
||
|
};
|
||
|
|
||
|
BN.prototype.ixor = function ixor (num) {
|
||
|
assert((this.negative | num.negative) === 0);
|
||
|
return this.iuxor(num);
|
||
|
};
|
||
|
|
||
|
// Xor `num` with `this`
|
||
|
BN.prototype.xor = function xor (num) {
|
||
|
if (this.length > num.length) return this.clone().ixor(num);
|
||
|
return num.clone().ixor(this);
|
||
|
};
|
||
|
|
||
|
BN.prototype.uxor = function uxor (num) {
|
||
|
if (this.length > num.length) return this.clone().iuxor(num);
|
||
|
return num.clone().iuxor(this);
|
||
|
};
|
||
|
|
||
|
// Not ``this`` with ``width`` bitwidth
|
||
|
BN.prototype.inotn = function inotn (width) {
|
||
|
assert(typeof width === 'number' && width >= 0);
|
||
|
|
||
|
var bytesNeeded = Math.ceil(width / 26) | 0;
|
||
|
var bitsLeft = width % 26;
|
||
|
|
||
|
// Extend the buffer with leading zeroes
|
||
|
this._expand(bytesNeeded);
|
||
|
|
||
|
if (bitsLeft > 0) {
|
||
|
bytesNeeded--;
|
||
|
}
|
||
|
|
||
|
// Handle complete words
|
||
|
for (var i = 0; i < bytesNeeded; i++) {
|
||
|
this.words[i] = ~this.words[i] & 0x3ffffff;
|
||
|
}
|
||
|
|
||
|
// Handle the residue
|
||
|
if (bitsLeft > 0) {
|
||
|
this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft));
|
||
|
}
|
||
|
|
||
|
// And remove leading zeroes
|
||
|
return this.strip();
|
||
|
};
|
||
|
|
||
|
BN.prototype.notn = function notn (width) {
|
||
|
return this.clone().inotn(width);
|
||
|
};
|
||
|
|
||
|
// Set `bit` of `this`
|
||
|
BN.prototype.setn = function setn (bit, val) {
|
||
|
assert(typeof bit === 'number' && bit >= 0);
|
||
|
|
||
|
var off = (bit / 26) | 0;
|
||
|
var wbit = bit % 26;
|
||
|
|
||
|
this._expand(off + 1);
|
||
|
|
||
|
if (val) {
|
||
|
this.words[off] = this.words[off] | (1 << wbit);
|
||
|
} else {
|
||
|
this.words[off] = this.words[off] & ~(1 << wbit);
|
||
|
}
|
||
|
|
||
|
return this.strip();
|
||
|
};
|
||
|
|
||
|
// Add `num` to `this` in-place
|
||
|
BN.prototype.iadd = function iadd (num) {
|
||
|
var r;
|
||
|
|
||
|
// negative + positive
|
||
|
if (this.negative !== 0 && num.negative === 0) {
|
||
|
this.negative = 0;
|
||
|
r = this.isub(num);
|
||
|
this.negative ^= 1;
|
||
|
return this._normSign();
|
||
|
|
||
|
// positive + negative
|
||
|
} else if (this.negative === 0 && num.negative !== 0) {
|
||
|
num.negative = 0;
|
||
|
r = this.isub(num);
|
||
|
num.negative = 1;
|
||
|
return r._normSign();
|
||
|
}
|
||
|
|
||
|
// a.length > b.length
|
||
|
var a, b;
|
||
|
if (this.length > num.length) {
|
||
|
a = this;
|
||
|
b = num;
|
||
|
} else {
|
||
|
a = num;
|
||
|
b = this;
|
||
|
}
|
||
|
|
||
|
var carry = 0;
|
||
|
for (var i = 0; i < b.length; i++) {
|
||
|
r = (a.words[i] | 0) + (b.words[i] | 0) + carry;
|
||
|
this.words[i] = r & 0x3ffffff;
|
||
|
carry = r >>> 26;
|
||
|
}
|
||
|
for (; carry !== 0 && i < a.length; i++) {
|
||
|
r = (a.words[i] | 0) + carry;
|
||
|
this.words[i] = r & 0x3ffffff;
|
||
|
carry = r >>> 26;
|
||
|
}
|
||
|
|
||
|
this.length = a.length;
|
||
|
if (carry !== 0) {
|
||
|
this.words[this.length] = carry;
|
||
|
this.length++;
|
||
|
// Copy the rest of the words
|
||
|
} else if (a !== this) {
|
||
|
for (; i < a.length; i++) {
|
||
|
this.words[i] = a.words[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
// Add `num` to `this`
|
||
|
BN.prototype.add = function add (num) {
|
||
|
var res;
|
||
|
if (num.negative !== 0 && this.negative === 0) {
|
||
|
num.negative = 0;
|
||
|
res = this.sub(num);
|
||
|
num.negative ^= 1;
|
||
|
return res;
|
||
|
} else if (num.negative === 0 && this.negative !== 0) {
|
||
|
this.negative = 0;
|
||
|
res = num.sub(this);
|
||
|
this.negative = 1;
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
if (this.length > num.length) return this.clone().iadd(num);
|
||
|
|
||
|
return num.clone().iadd(this);
|
||
|
};
|
||
|
|
||
|
// Subtract `num` from `this` in-place
|
||
|
BN.prototype.isub = function isub (num) {
|
||
|
// this - (-num) = this + num
|
||
|
if (num.negative !== 0) {
|
||
|
num.negative = 0;
|
||
|
var r = this.iadd(num);
|
||
|
num.negative = 1;
|
||
|
return r._normSign();
|
||
|
|
||
|
// -this - num = -(this + num)
|
||
|
} else if (this.negative !== 0) {
|
||
|
this.negative = 0;
|
||
|
this.iadd(num);
|
||
|
this.negative = 1;
|
||
|
return this._normSign();
|
||
|
}
|
||
|
|
||
|
// At this point both numbers are positive
|
||
|
var cmp = this.cmp(num);
|
||
|
|
||
|
// Optimization - zeroify
|
||
|
if (cmp === 0) {
|
||
|
this.negative = 0;
|
||
|
this.length = 1;
|
||
|
this.words[0] = 0;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
// a > b
|
||
|
var a, b;
|
||
|
if (cmp > 0) {
|
||
|
a = this;
|
||
|
b = num;
|
||
|
} else {
|
||
|
a = num;
|
||
|
b = this;
|
||
|
}
|
||
|
|
||
|
var carry = 0;
|
||
|
for (var i = 0; i < b.length; i++) {
|
||
|
r = (a.words[i] | 0) - (b.words[i] | 0) + carry;
|
||
|
carry = r >> 26;
|
||
|
this.words[i] = r & 0x3ffffff;
|
||
|
}
|
||
|
for (; carry !== 0 && i < a.length; i++) {
|
||
|
r = (a.words[i] | 0) + carry;
|
||
|
carry = r >> 26;
|
||
|
this.words[i] = r & 0x3ffffff;
|
||
|
}
|
||
|
|
||
|
// Copy rest of the words
|
||
|
if (carry === 0 && i < a.length && a !== this) {
|
||
|
for (; i < a.length; i++) {
|
||
|
this.words[i] = a.words[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.length = Math.max(this.length, i);
|
||
|
|
||
|
if (a !== this) {
|
||
|
this.negative = 1;
|
||
|
}
|
||
|
|
||
|
return this.strip();
|
||
|
};
|
||
|
|
||
|
// Subtract `num` from `this`
|
||
|
BN.prototype.sub = function sub (num) {
|
||
|
return this.clone().isub(num);
|
||
|
};
|
||
|
|
||
|
function smallMulTo (self, num, out) {
|
||
|
out.negative = num.negative ^ self.negative;
|
||
|
var len = (self.length + num.length) | 0;
|
||
|
out.length = len;
|
||
|
len = (len - 1) | 0;
|
||
|
|
||
|
// Peel one iteration (compiler can't do it, because of code complexity)
|
||
|
var a = self.words[0] | 0;
|
||
|
var b = num.words[0] | 0;
|
||
|
var r = a * b;
|
||
|
|
||
|
var lo = r & 0x3ffffff;
|
||
|
var carry = (r / 0x4000000) | 0;
|
||
|
out.words[0] = lo;
|
||
|
|
||
|
for (var k = 1; k < len; k++) {
|
||
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
||
|
// note that ncarry could be >= 0x3ffffff
|
||
|
var ncarry = carry >>> 26;
|
||
|
var rword = carry & 0x3ffffff;
|
||
|
var maxJ = Math.min(k, num.length - 1);
|
||
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
||
|
var i = (k - j) | 0;
|
||
|
a = self.words[i] | 0;
|
||
|
b = num.words[j] | 0;
|
||
|
r = a * b + rword;
|
||
|
ncarry += (r / 0x4000000) | 0;
|
||
|
rword = r & 0x3ffffff;
|
||
|
}
|
||
|
out.words[k] = rword | 0;
|
||
|
carry = ncarry | 0;
|
||
|
}
|
||
|
if (carry !== 0) {
|
||
|
out.words[k] = carry | 0;
|
||
|
} else {
|
||
|
out.length--;
|
||
|
}
|
||
|
|
||
|
return out.strip();
|
||
|
}
|
||
|
|
||
|
// TODO(indutny): it may be reasonable to omit it for users who don't need
|
||
|
// to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit
|
||
|
// multiplication (like elliptic secp256k1).
|
||
|
var comb10MulTo = function comb10MulTo (self, num, out) {
|
||
|
var a = self.words;
|
||
|
var b = num.words;
|
||
|
var o = out.words;
|
||
|
var c = 0;
|
||
|
var lo;
|
||
|
var mid;
|
||
|
var hi;
|
||
|
var a0 = a[0] | 0;
|
||
|
var al0 = a0 & 0x1fff;
|
||
|
var ah0 = a0 >>> 13;
|
||
|
var a1 = a[1] | 0;
|
||
|
var al1 = a1 & 0x1fff;
|
||
|
var ah1 = a1 >>> 13;
|
||
|
var a2 = a[2] | 0;
|
||
|
var al2 = a2 & 0x1fff;
|
||
|
var ah2 = a2 >>> 13;
|
||
|
var a3 = a[3] | 0;
|
||
|
var al3 = a3 & 0x1fff;
|
||
|
var ah3 = a3 >>> 13;
|
||
|
var a4 = a[4] | 0;
|
||
|
var al4 = a4 & 0x1fff;
|
||
|
var ah4 = a4 >>> 13;
|
||
|
var a5 = a[5] | 0;
|
||
|
var al5 = a5 & 0x1fff;
|
||
|
var ah5 = a5 >>> 13;
|
||
|
var a6 = a[6] | 0;
|
||
|
var al6 = a6 & 0x1fff;
|
||
|
var ah6 = a6 >>> 13;
|
||
|
var a7 = a[7] | 0;
|
||
|
var al7 = a7 & 0x1fff;
|
||
|
var ah7 = a7 >>> 13;
|
||
|
var a8 = a[8] | 0;
|
||
|
var al8 = a8 & 0x1fff;
|
||
|
var ah8 = a8 >>> 13;
|
||
|
var a9 = a[9] | 0;
|
||
|
var al9 = a9 & 0x1fff;
|
||
|
var ah9 = a9 >>> 13;
|
||
|
var b0 = b[0] | 0;
|
||
|
var bl0 = b0 & 0x1fff;
|
||
|
var bh0 = b0 >>> 13;
|
||
|
var b1 = b[1] | 0;
|
||
|
var bl1 = b1 & 0x1fff;
|
||
|
var bh1 = b1 >>> 13;
|
||
|
var b2 = b[2] | 0;
|
||
|
var bl2 = b2 & 0x1fff;
|
||
|
var bh2 = b2 >>> 13;
|
||
|
var b3 = b[3] | 0;
|
||
|
var bl3 = b3 & 0x1fff;
|
||
|
var bh3 = b3 >>> 13;
|
||
|
var b4 = b[4] | 0;
|
||
|
var bl4 = b4 & 0x1fff;
|
||
|
var bh4 = b4 >>> 13;
|
||
|
var b5 = b[5] | 0;
|
||
|
var bl5 = b5 & 0x1fff;
|
||
|
var bh5 = b5 >>> 13;
|
||
|
var b6 = b[6] | 0;
|
||
|
var bl6 = b6 & 0x1fff;
|
||
|
var bh6 = b6 >>> 13;
|
||
|
var b7 = b[7] | 0;
|
||
|
var bl7 = b7 & 0x1fff;
|
||
|
var bh7 = b7 >>> 13;
|
||
|
var b8 = b[8] | 0;
|
||
|
var bl8 = b8 & 0x1fff;
|
||
|
var bh8 = b8 >>> 13;
|
||
|
var b9 = b[9] | 0;
|
||
|
var bl9 = b9 & 0x1fff;
|
||
|
var bh9 = b9 >>> 13;
|
||
|
|
||
|
out.negative = self.negative ^ num.negative;
|
||
|
out.length = 19;
|
||
|
/* k = 0 */
|
||
|
lo = Math.imul(al0, bl0);
|
||
|
mid = Math.imul(al0, bh0);
|
||
|
mid = (mid + Math.imul(ah0, bl0)) | 0;
|
||
|
hi = Math.imul(ah0, bh0);
|
||
|
var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0;
|
||
|
w0 &= 0x3ffffff;
|
||
|
/* k = 1 */
|
||
|
lo = Math.imul(al1, bl0);
|
||
|
mid = Math.imul(al1, bh0);
|
||
|
mid = (mid + Math.imul(ah1, bl0)) | 0;
|
||
|
hi = Math.imul(ah1, bh0);
|
||
|
lo = (lo + Math.imul(al0, bl1)) | 0;
|
||
|
mid = (mid + Math.imul(al0, bh1)) | 0;
|
||
|
mid = (mid + Math.imul(ah0, bl1)) | 0;
|
||
|
hi = (hi + Math.imul(ah0, bh1)) | 0;
|
||
|
var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0;
|
||
|
w1 &= 0x3ffffff;
|
||
|
/* k = 2 */
|
||
|
lo = Math.imul(al2, bl0);
|
||
|
mid = Math.imul(al2, bh0);
|
||
|
mid = (mid + Math.imul(ah2, bl0)) | 0;
|
||
|
hi = Math.imul(ah2, bh0);
|
||
|
lo = (lo + Math.imul(al1, bl1)) | 0;
|
||
|
mid = (mid + Math.imul(al1, bh1)) | 0;
|
||
|
mid = (mid + Math.imul(ah1, bl1)) | 0;
|
||
|
hi = (hi + Math.imul(ah1, bh1)) | 0;
|
||
|
lo = (lo + Math.imul(al0, bl2)) | 0;
|
||
|
mid = (mid + Math.imul(al0, bh2)) | 0;
|
||
|
mid = (mid + Math.imul(ah0, bl2)) | 0;
|
||
|
hi = (hi + Math.imul(ah0, bh2)) | 0;
|
||
|
var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0;
|
||
|
w2 &= 0x3ffffff;
|
||
|
/* k = 3 */
|
||
|
lo = Math.imul(al3, bl0);
|
||
|
mid = Math.imul(al3, bh0);
|
||
|
mid = (mid + Math.imul(ah3, bl0)) | 0;
|
||
|
hi = Math.imul(ah3, bh0);
|
||
|
lo = (lo + Math.imul(al2, bl1)) | 0;
|
||
|
mid = (mid + Math.imul(al2, bh1)) | 0;
|
||
|
mid = (mid + Math.imul(ah2, bl1)) | 0;
|
||
|
hi = (hi + Math.imul(ah2, bh1)) | 0;
|
||
|
lo = (lo + Math.imul(al1, bl2)) | 0;
|
||
|
mid = (mid + Math.imul(al1, bh2)) | 0;
|
||
|
mid = (mid + Math.imul(ah1, bl2)) | 0;
|
||
|
hi = (hi + Math.imul(ah1, bh2)) | 0;
|
||
|
lo = (lo + Math.imul(al0, bl3)) | 0;
|
||
|
mid = (mid + Math.imul(al0, bh3)) | 0;
|
||
|
mid = (mid + Math.imul(ah0, bl3)) | 0;
|
||
|
hi = (hi + Math.imul(ah0, bh3)) | 0;
|
||
|
var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0;
|
||
|
w3 &= 0x3ffffff;
|
||
|
/* k = 4 */
|
||
|
lo = Math.imul(al4, bl0);
|
||
|
mid = Math.imul(al4, bh0);
|
||
|
mid = (mid + Math.imul(ah4, bl0)) | 0;
|
||
|
hi = Math.imul(ah4, bh0);
|
||
|
lo = (lo + Math.imul(al3, bl1)) | 0;
|
||
|
mid = (mid + Math.imul(al3, bh1)) | 0;
|
||
|
mid = (mid + Math.imul(ah3, bl1)) | 0;
|
||
|
hi = (hi + Math.imul(ah3, bh1)) | 0;
|
||
|
lo = (lo + Math.imul(al2, bl2)) | 0;
|
||
|
mid = (mid + Math.imul(al2, bh2)) | 0;
|
||
|
mid = (mid + Math.imul(ah2, bl2)) | 0;
|
||
|
hi = (hi + Math.imul(ah2, bh2)) | 0;
|
||
|
lo = (lo + Math.imul(al1, bl3)) | 0;
|
||
|
mid = (mid + Math.imul(al1, bh3)) | 0;
|
||
|
mid = (mid + Math.imul(ah1, bl3)) | 0;
|
||
|
hi = (hi + Math.imul(ah1, bh3)) | 0;
|
||
|
lo = (lo + Math.imul(al0, bl4)) | 0;
|
||
|
mid = (mid + Math.imul(al0, bh4)) | 0;
|
||
|
mid = (mid + Math.imul(ah0, bl4)) | 0;
|
||
|
hi = (hi + Math.imul(ah0, bh4)) | 0;
|
||
|
var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0;
|
||
|
w4 &= 0x3ffffff;
|
||
|
/* k = 5 */
|
||
|
lo = Math.imul(al5, bl0);
|
||
|
mid = Math.imul(al5, bh0);
|
||
|
mid = (mid + Math.imul(ah5, bl0)) | 0;
|
||
|
hi = Math.imul(ah5, bh0);
|
||
|
lo = (lo + Math.imul(al4, bl1)) | 0;
|
||
|
mid = (mid + Math.imul(al4, bh1)) | 0;
|
||
|
mid = (mid + Math.imul(ah4, bl1)) | 0;
|
||
|
hi = (hi + Math.imul(ah4, bh1)) | 0;
|
||
|
lo = (lo + Math.imul(al3, bl2)) | 0;
|
||
|
mid = (mid + Math.imul(al3, bh2)) | 0;
|
||
|
mid = (mid + Math.imul(ah3, bl2)) | 0;
|
||
|
hi = (hi + Math.imul(ah3, bh2)) | 0;
|
||
|
lo = (lo + Math.imul(al2, bl3)) | 0;
|
||
|
mid = (mid + Math.imul(al2, bh3)) | 0;
|
||
|
mid = (mid + Math.imul(ah2, bl3)) | 0;
|
||
|
hi = (hi + Math.imul(ah2, bh3)) | 0;
|
||
|
lo = (lo + Math.imul(al1, bl4)) | 0;
|
||
|
mid = (mid + Math.imul(al1, bh4)) | 0;
|
||
|
mid = (mid + Math.imul(ah1, bl4)) | 0;
|
||
|
hi = (hi + Math.imul(ah1, bh4)) | 0;
|
||
|
lo = (lo + Math.imul(al0, bl5)) | 0;
|
||
|
mid = (mid + Math.imul(al0, bh5)) | 0;
|
||
|
mid = (mid + Math.imul(ah0, bl5)) | 0;
|
||
|
hi = (hi + Math.imul(ah0, bh5)) | 0;
|
||
|
var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0;
|
||
|
w5 &= 0x3ffffff;
|
||
|
/* k = 6 */
|
||
|
lo = Math.imul(al6, bl0);
|
||
|
mid = Math.imul(al6, bh0);
|
||
|
mid = (mid + Math.imul(ah6, bl0)) | 0;
|
||
|
hi = Math.imul(ah6, bh0);
|
||
|
lo = (lo + Math.imul(al5, bl1)) | 0;
|
||
|
mid = (mid + Math.imul(al5, bh1)) | 0;
|
||
|
mid = (mid + Math.imul(ah5, bl1)) | 0;
|
||
|
hi = (hi + Math.imul(ah5, bh1)) | 0;
|
||
|
lo = (lo + Math.imul(al4, bl2)) | 0;
|
||
|
mid = (mid + Math.imul(al4, bh2)) | 0;
|
||
|
mid = (mid + Math.imul(ah4, bl2)) | 0;
|
||
|
hi = (hi + Math.imul(ah4, bh2)) | 0;
|
||
|
lo = (lo + Math.imul(al3, bl3)) | 0;
|
||
|
mid = (mid + Math.imul(al3, bh3)) | 0;
|
||
|
mid = (mid + Math.imul(ah3, bl3)) | 0;
|
||
|
hi = (hi + Math.imul(ah3, bh3)) | 0;
|
||
|
lo = (lo + Math.imul(al2, bl4)) | 0;
|
||
|
mid = (mid + Math.imul(al2, bh4)) | 0;
|
||
|
mid = (mid + Math.imul(ah2, bl4)) | 0;
|
||
|
hi = (hi + Math.imul(ah2, bh4)) | 0;
|
||
|
lo = (lo + Math.imul(al1, bl5)) | 0;
|
||
|
mid = (mid + Math.imul(al1, bh5)) | 0;
|
||
|
mid = (mid + Math.imul(ah1, bl5)) | 0;
|
||
|
hi = (hi + Math.imul(ah1, bh5)) | 0;
|
||
|
lo = (lo + Math.imul(al0, bl6)) | 0;
|
||
|
mid = (mid + Math.imul(al0, bh6)) | 0;
|
||
|
mid = (mid + Math.imul(ah0, bl6)) | 0;
|
||
|
hi = (hi + Math.imul(ah0, bh6)) | 0;
|
||
|
var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0;
|
||
|
w6 &= 0x3ffffff;
|
||
|
/* k = 7 */
|
||
|
lo = Math.imul(al7, bl0);
|
||
|
mid = Math.imul(al7, bh0);
|
||
|
mid = (mid + Math.imul(ah7, bl0)) | 0;
|
||
|
hi = Math.imul(ah7, bh0);
|
||
|
lo = (lo + Math.imul(al6, bl1)) | 0;
|
||
|
mid = (mid + Math.imul(al6, bh1)) | 0;
|
||
|
mid = (mid + Math.imul(ah6, bl1)) | 0;
|
||
|
hi = (hi + Math.imul(ah6, bh1)) | 0;
|
||
|
lo = (lo + Math.imul(al5, bl2)) | 0;
|
||
|
mid = (mid + Math.imul(al5, bh2)) | 0;
|
||
|
mid = (mid + Math.imul(ah5, bl2)) | 0;
|
||
|
hi = (hi + Math.imul(ah5, bh2)) | 0;
|
||
|
lo = (lo + Math.imul(al4, bl3)) | 0;
|
||
|
mid = (mid + Math.imul(al4, bh3)) | 0;
|
||
|
mid = (mid + Math.imul(ah4, bl3)) | 0;
|
||
|
hi = (hi + Math.imul(ah4, bh3)) | 0;
|
||
|
lo = (lo + Math.imul(al3, bl4)) | 0;
|
||
|
mid = (mid + Math.imul(al3, bh4)) | 0;
|
||
|
mid = (mid + Math.imul(ah3, bl4)) | 0;
|
||
|
hi = (hi + Math.imul(ah3, bh4)) | 0;
|
||
|
lo = (lo + Math.imul(al2, bl5)) | 0;
|
||
|
mid = (mid + Math.imul(al2, bh5)) | 0;
|
||
|
mid = (mid + Math.imul(ah2, bl5)) | 0;
|
||
|
hi = (hi + Math.imul(ah2, bh5)) | 0;
|
||
|
lo = (lo + Math.imul(al1, bl6)) | 0;
|
||
|
mid = (mid + Math.imul(al1, bh6)) | 0;
|
||
|
mid = (mid + Math.imul(ah1, bl6)) | 0;
|
||
|
hi = (hi + Math.imul(ah1, bh6)) | 0;
|
||
|
lo = (lo + Math.imul(al0, bl7)) | 0;
|
||
|
mid = (mid + Math.imul(al0, bh7)) | 0;
|
||
|
mid = (mid + Math.imul(ah0, bl7)) | 0;
|
||
|
hi = (hi + Math.imul(ah0, bh7)) | 0;
|
||
|
var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0;
|
||
|
w7 &= 0x3ffffff;
|
||
|
/* k = 8 */
|
||
|
lo = Math.imul(al8, bl0);
|
||
|
mid = Math.imul(al8, bh0);
|
||
|
mid = (mid + Math.imul(ah8, bl0)) | 0;
|
||
|
hi = Math.imul(ah8, bh0);
|
||
|
lo = (lo + Math.imul(al7, bl1)) | 0;
|
||
|
mid = (mid + Math.imul(al7, bh1)) | 0;
|
||
|
mid = (mid + Math.imul(ah7, bl1)) | 0;
|
||
|
hi = (hi + Math.imul(ah7, bh1)) | 0;
|
||
|
lo = (lo + Math.imul(al6, bl2)) | 0;
|
||
|
mid = (mid + Math.imul(al6, bh2)) | 0;
|
||
|
mid = (mid + Math.imul(ah6, bl2)) | 0;
|
||
|
hi = (hi + Math.imul(ah6, bh2)) | 0;
|
||
|
lo = (lo + Math.imul(al5, bl3)) | 0;
|
||
|
mid = (mid + Math.imul(al5, bh3)) | 0;
|
||
|
mid = (mid + Math.imul(ah5, bl3)) | 0;
|
||
|
hi = (hi + Math.imul(ah5, bh3)) | 0;
|
||
|
lo = (lo + Math.imul(al4, bl4)) | 0;
|
||
|
mid = (mid + Math.imul(al4, bh4)) | 0;
|
||
|
mid = (mid + Math.imul(ah4, bl4)) | 0;
|
||
|
hi = (hi + Math.imul(ah4, bh4)) | 0;
|
||
|
lo = (lo + Math.imul(al3, bl5)) | 0;
|
||
|
mid = (mid + Math.imul(al3, bh5)) | 0;
|
||
|
mid = (mid + Math.imul(ah3, bl5)) | 0;
|
||
|
hi = (hi + Math.imul(ah3, bh5)) | 0;
|
||
|
lo = (lo + Math.imul(al2, bl6)) | 0;
|
||
|
mid = (mid + Math.imul(al2, bh6)) | 0;
|
||
|
mid = (mid + Math.imul(ah2, bl6)) | 0;
|
||
|
hi = (hi + Math.imul(ah2, bh6)) | 0;
|
||
|
lo = (lo + Math.imul(al1, bl7)) | 0;
|
||
|
mid = (mid + Math.imul(al1, bh7)) | 0;
|
||
|
mid = (mid + Math.imul(ah1, bl7)) | 0;
|
||
|
hi = (hi + Math.imul(ah1, bh7)) | 0;
|
||
|
lo = (lo + Math.imul(al0, bl8)) | 0;
|
||
|
mid = (mid + Math.imul(al0, bh8)) | 0;
|
||
|
mid = (mid + Math.imul(ah0, bl8)) | 0;
|
||
|
hi = (hi + Math.imul(ah0, bh8)) | 0;
|
||
|
var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0;
|
||
|
w8 &= 0x3ffffff;
|
||
|
/* k = 9 */
|
||
|
lo = Math.imul(al9, bl0);
|
||
|
mid = Math.imul(al9, bh0);
|
||
|
mid = (mid + Math.imul(ah9, bl0)) | 0;
|
||
|
hi = Math.imul(ah9, bh0);
|
||
|
lo = (lo + Math.imul(al8, bl1)) | 0;
|
||
|
mid = (mid + Math.imul(al8, bh1)) | 0;
|
||
|
mid = (mid + Math.imul(ah8, bl1)) | 0;
|
||
|
hi = (hi + Math.imul(ah8, bh1)) | 0;
|
||
|
lo = (lo + Math.imul(al7, bl2)) | 0;
|
||
|
mid = (mid + Math.imul(al7, bh2)) | 0;
|
||
|
mid = (mid + Math.imul(ah7, bl2)) | 0;
|
||
|
hi = (hi + Math.imul(ah7, bh2)) | 0;
|
||
|
lo = (lo + Math.imul(al6, bl3)) | 0;
|
||
|
mid = (mid + Math.imul(al6, bh3)) | 0;
|
||
|
mid = (mid + Math.imul(ah6, bl3)) | 0;
|
||
|
hi = (hi + Math.imul(ah6, bh3)) | 0;
|
||
|
lo = (lo + Math.imul(al5, bl4)) | 0;
|
||
|
mid = (mid + Math.imul(al5, bh4)) | 0;
|
||
|
mid = (mid + Math.imul(ah5, bl4)) | 0;
|
||
|
hi = (hi + Math.imul(ah5, bh4)) | 0;
|
||
|
lo = (lo + Math.imul(al4, bl5)) | 0;
|
||
|
mid = (mid + Math.imul(al4, bh5)) | 0;
|
||
|
mid = (mid + Math.imul(ah4, bl5)) | 0;
|
||
|
hi = (hi + Math.imul(ah4, bh5)) | 0;
|
||
|
lo = (lo + Math.imul(al3, bl6)) | 0;
|
||
|
mid = (mid + Math.imul(al3, bh6)) | 0;
|
||
|
mid = (mid + Math.imul(ah3, bl6)) | 0;
|
||
|
hi = (hi + Math.imul(ah3, bh6)) | 0;
|
||
|
lo = (lo + Math.imul(al2, bl7)) | 0;
|
||
|
mid = (mid + Math.imul(al2, bh7)) | 0;
|
||
|
mid = (mid + Math.imul(ah2, bl7)) | 0;
|
||
|
hi = (hi + Math.imul(ah2, bh7)) | 0;
|
||
|
lo = (lo + Math.imul(al1, bl8)) | 0;
|
||
|
mid = (mid + Math.imul(al1, bh8)) | 0;
|
||
|
mid = (mid + Math.imul(ah1, bl8)) | 0;
|
||
|
hi = (hi + Math.imul(ah1, bh8)) | 0;
|
||
|
lo = (lo + Math.imul(al0, bl9)) | 0;
|
||
|
mid = (mid + Math.imul(al0, bh9)) | 0;
|
||
|
mid = (mid + Math.imul(ah0, bl9)) | 0;
|
||
|
hi = (hi + Math.imul(ah0, bh9)) | 0;
|
||
|
var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0;
|
||
|
w9 &= 0x3ffffff;
|
||
|
/* k = 10 */
|
||
|
lo = Math.imul(al9, bl1);
|
||
|
mid = Math.imul(al9, bh1);
|
||
|
mid = (mid + Math.imul(ah9, bl1)) | 0;
|
||
|
hi = Math.imul(ah9, bh1);
|
||
|
lo = (lo + Math.imul(al8, bl2)) | 0;
|
||
|
mid = (mid + Math.imul(al8, bh2)) | 0;
|
||
|
mid = (mid + Math.imul(ah8, bl2)) | 0;
|
||
|
hi = (hi + Math.imul(ah8, bh2)) | 0;
|
||
|
lo = (lo + Math.imul(al7, bl3)) | 0;
|
||
|
mid = (mid + Math.imul(al7, bh3)) | 0;
|
||
|
mid = (mid + Math.imul(ah7, bl3)) | 0;
|
||
|
hi = (hi + Math.imul(ah7, bh3)) | 0;
|
||
|
lo = (lo + Math.imul(al6, bl4)) | 0;
|
||
|
mid = (mid + Math.imul(al6, bh4)) | 0;
|
||
|
mid = (mid + Math.imul(ah6, bl4)) | 0;
|
||
|
hi = (hi + Math.imul(ah6, bh4)) | 0;
|
||
|
lo = (lo + Math.imul(al5, bl5)) | 0;
|
||
|
mid = (mid + Math.imul(al5, bh5)) | 0;
|
||
|
mid = (mid + Math.imul(ah5, bl5)) | 0;
|
||
|
hi = (hi + Math.imul(ah5, bh5)) | 0;
|
||
|
lo = (lo + Math.imul(al4, bl6)) | 0;
|
||
|
mid = (mid + Math.imul(al4, bh6)) | 0;
|
||
|
mid = (mid + Math.imul(ah4, bl6)) | 0;
|
||
|
hi = (hi + Math.imul(ah4, bh6)) | 0;
|
||
|
lo = (lo + Math.imul(al3, bl7)) | 0;
|
||
|
mid = (mid + Math.imul(al3, bh7)) | 0;
|
||
|
mid = (mid + Math.imul(ah3, bl7)) | 0;
|
||
|
hi = (hi + Math.imul(ah3, bh7)) | 0;
|
||
|
lo = (lo + Math.imul(al2, bl8)) | 0;
|
||
|
mid = (mid + Math.imul(al2, bh8)) | 0;
|
||
|
mid = (mid + Math.imul(ah2, bl8)) | 0;
|
||
|
hi = (hi + Math.imul(ah2, bh8)) | 0;
|
||
|
lo = (lo + Math.imul(al1, bl9)) | 0;
|
||
|
mid = (mid + Math.imul(al1, bh9)) | 0;
|
||
|
mid = (mid + Math.imul(ah1, bl9)) | 0;
|
||
|
hi = (hi + Math.imul(ah1, bh9)) | 0;
|
||
|
var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0;
|
||
|
w10 &= 0x3ffffff;
|
||
|
/* k = 11 */
|
||
|
lo = Math.imul(al9, bl2);
|
||
|
mid = Math.imul(al9, bh2);
|
||
|
mid = (mid + Math.imul(ah9, bl2)) | 0;
|
||
|
hi = Math.imul(ah9, bh2);
|
||
|
lo = (lo + Math.imul(al8, bl3)) | 0;
|
||
|
mid = (mid + Math.imul(al8, bh3)) | 0;
|
||
|
mid = (mid + Math.imul(ah8, bl3)) | 0;
|
||
|
hi = (hi + Math.imul(ah8, bh3)) | 0;
|
||
|
lo = (lo + Math.imul(al7, bl4)) | 0;
|
||
|
mid = (mid + Math.imul(al7, bh4)) | 0;
|
||
|
mid = (mid + Math.imul(ah7, bl4)) | 0;
|
||
|
hi = (hi + Math.imul(ah7, bh4)) | 0;
|
||
|
lo = (lo + Math.imul(al6, bl5)) | 0;
|
||
|
mid = (mid + Math.imul(al6, bh5)) | 0;
|
||
|
mid = (mid + Math.imul(ah6, bl5)) | 0;
|
||
|
hi = (hi + Math.imul(ah6, bh5)) | 0;
|
||
|
lo = (lo + Math.imul(al5, bl6)) | 0;
|
||
|
mid = (mid + Math.imul(al5, bh6)) | 0;
|
||
|
mid = (mid + Math.imul(ah5, bl6)) | 0;
|
||
|
hi = (hi + Math.imul(ah5, bh6)) | 0;
|
||
|
lo = (lo + Math.imul(al4, bl7)) | 0;
|
||
|
mid = (mid + Math.imul(al4, bh7)) | 0;
|
||
|
mid = (mid + Math.imul(ah4, bl7)) | 0;
|
||
|
hi = (hi + Math.imul(ah4, bh7)) | 0;
|
||
|
lo = (lo + Math.imul(al3, bl8)) | 0;
|
||
|
mid = (mid + Math.imul(al3, bh8)) | 0;
|
||
|
mid = (mid + Math.imul(ah3, bl8)) | 0;
|
||
|
hi = (hi + Math.imul(ah3, bh8)) | 0;
|
||
|
lo = (lo + Math.imul(al2, bl9)) | 0;
|
||
|
mid = (mid + Math.imul(al2, bh9)) | 0;
|
||
|
mid = (mid + Math.imul(ah2, bl9)) | 0;
|
||
|
hi = (hi + Math.imul(ah2, bh9)) | 0;
|
||
|
var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0;
|
||
|
w11 &= 0x3ffffff;
|
||
|
/* k = 12 */
|
||
|
lo = Math.imul(al9, bl3);
|
||
|
mid = Math.imul(al9, bh3);
|
||
|
mid = (mid + Math.imul(ah9, bl3)) | 0;
|
||
|
hi = Math.imul(ah9, bh3);
|
||
|
lo = (lo + Math.imul(al8, bl4)) | 0;
|
||
|
mid = (mid + Math.imul(al8, bh4)) | 0;
|
||
|
mid = (mid + Math.imul(ah8, bl4)) | 0;
|
||
|
hi = (hi + Math.imul(ah8, bh4)) | 0;
|
||
|
lo = (lo + Math.imul(al7, bl5)) | 0;
|
||
|
mid = (mid + Math.imul(al7, bh5)) | 0;
|
||
|
mid = (mid + Math.imul(ah7, bl5)) | 0;
|
||
|
hi = (hi + Math.imul(ah7, bh5)) | 0;
|
||
|
lo = (lo + Math.imul(al6, bl6)) | 0;
|
||
|
mid = (mid + Math.imul(al6, bh6)) | 0;
|
||
|
mid = (mid + Math.imul(ah6, bl6)) | 0;
|
||
|
hi = (hi + Math.imul(ah6, bh6)) | 0;
|
||
|
lo = (lo + Math.imul(al5, bl7)) | 0;
|
||
|
mid = (mid + Math.imul(al5, bh7)) | 0;
|
||
|
mid = (mid + Math.imul(ah5, bl7)) | 0;
|
||
|
hi = (hi + Math.imul(ah5, bh7)) | 0;
|
||
|
lo = (lo + Math.imul(al4, bl8)) | 0;
|
||
|
mid = (mid + Math.imul(al4, bh8)) | 0;
|
||
|
mid = (mid + Math.imul(ah4, bl8)) | 0;
|
||
|
hi = (hi + Math.imul(ah4, bh8)) | 0;
|
||
|
lo = (lo + Math.imul(al3, bl9)) | 0;
|
||
|
mid = (mid + Math.imul(al3, bh9)) | 0;
|
||
|
mid = (mid + Math.imul(ah3, bl9)) | 0;
|
||
|
hi = (hi + Math.imul(ah3, bh9)) | 0;
|
||
|
var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0;
|
||
|
w12 &= 0x3ffffff;
|
||
|
/* k = 13 */
|
||
|
lo = Math.imul(al9, bl4);
|
||
|
mid = Math.imul(al9, bh4);
|
||
|
mid = (mid + Math.imul(ah9, bl4)) | 0;
|
||
|
hi = Math.imul(ah9, bh4);
|
||
|
lo = (lo + Math.imul(al8, bl5)) | 0;
|
||
|
mid = (mid + Math.imul(al8, bh5)) | 0;
|
||
|
mid = (mid + Math.imul(ah8, bl5)) | 0;
|
||
|
hi = (hi + Math.imul(ah8, bh5)) | 0;
|
||
|
lo = (lo + Math.imul(al7, bl6)) | 0;
|
||
|
mid = (mid + Math.imul(al7, bh6)) | 0;
|
||
|
mid = (mid + Math.imul(ah7, bl6)) | 0;
|
||
|
hi = (hi + Math.imul(ah7, bh6)) | 0;
|
||
|
lo = (lo + Math.imul(al6, bl7)) | 0;
|
||
|
mid = (mid + Math.imul(al6, bh7)) | 0;
|
||
|
mid = (mid + Math.imul(ah6, bl7)) | 0;
|
||
|
hi = (hi + Math.imul(ah6, bh7)) | 0;
|
||
|
lo = (lo + Math.imul(al5, bl8)) | 0;
|
||
|
mid = (mid + Math.imul(al5, bh8)) | 0;
|
||
|
mid = (mid + Math.imul(ah5, bl8)) | 0;
|
||
|
hi = (hi + Math.imul(ah5, bh8)) | 0;
|
||
|
lo = (lo + Math.imul(al4, bl9)) | 0;
|
||
|
mid = (mid + Math.imul(al4, bh9)) | 0;
|
||
|
mid = (mid + Math.imul(ah4, bl9)) | 0;
|
||
|
hi = (hi + Math.imul(ah4, bh9)) | 0;
|
||
|
var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0;
|
||
|
w13 &= 0x3ffffff;
|
||
|
/* k = 14 */
|
||
|
lo = Math.imul(al9, bl5);
|
||
|
mid = Math.imul(al9, bh5);
|
||
|
mid = (mid + Math.imul(ah9, bl5)) | 0;
|
||
|
hi = Math.imul(ah9, bh5);
|
||
|
lo = (lo + Math.imul(al8, bl6)) | 0;
|
||
|
mid = (mid + Math.imul(al8, bh6)) | 0;
|
||
|
mid = (mid + Math.imul(ah8, bl6)) | 0;
|
||
|
hi = (hi + Math.imul(ah8, bh6)) | 0;
|
||
|
lo = (lo + Math.imul(al7, bl7)) | 0;
|
||
|
mid = (mid + Math.imul(al7, bh7)) | 0;
|
||
|
mid = (mid + Math.imul(ah7, bl7)) | 0;
|
||
|
hi = (hi + Math.imul(ah7, bh7)) | 0;
|
||
|
lo = (lo + Math.imul(al6, bl8)) | 0;
|
||
|
mid = (mid + Math.imul(al6, bh8)) | 0;
|
||
|
mid = (mid + Math.imul(ah6, bl8)) | 0;
|
||
|
hi = (hi + Math.imul(ah6, bh8)) | 0;
|
||
|
lo = (lo + Math.imul(al5, bl9)) | 0;
|
||
|
mid = (mid + Math.imul(al5, bh9)) | 0;
|
||
|
mid = (mid + Math.imul(ah5, bl9)) | 0;
|
||
|
hi = (hi + Math.imul(ah5, bh9)) | 0;
|
||
|
var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0;
|
||
|
w14 &= 0x3ffffff;
|
||
|
/* k = 15 */
|
||
|
lo = Math.imul(al9, bl6);
|
||
|
mid = Math.imul(al9, bh6);
|
||
|
mid = (mid + Math.imul(ah9, bl6)) | 0;
|
||
|
hi = Math.imul(ah9, bh6);
|
||
|
lo = (lo + Math.imul(al8, bl7)) | 0;
|
||
|
mid = (mid + Math.imul(al8, bh7)) | 0;
|
||
|
mid = (mid + Math.imul(ah8, bl7)) | 0;
|
||
|
hi = (hi + Math.imul(ah8, bh7)) | 0;
|
||
|
lo = (lo + Math.imul(al7, bl8)) | 0;
|
||
|
mid = (mid + Math.imul(al7, bh8)) | 0;
|
||
|
mid = (mid + Math.imul(ah7, bl8)) | 0;
|
||
|
hi = (hi + Math.imul(ah7, bh8)) | 0;
|
||
|
lo = (lo + Math.imul(al6, bl9)) | 0;
|
||
|
mid = (mid + Math.imul(al6, bh9)) | 0;
|
||
|
mid = (mid + Math.imul(ah6, bl9)) | 0;
|
||
|
hi = (hi + Math.imul(ah6, bh9)) | 0;
|
||
|
var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0;
|
||
|
w15 &= 0x3ffffff;
|
||
|
/* k = 16 */
|
||
|
lo = Math.imul(al9, bl7);
|
||
|
mid = Math.imul(al9, bh7);
|
||
|
mid = (mid + Math.imul(ah9, bl7)) | 0;
|
||
|
hi = Math.imul(ah9, bh7);
|
||
|
lo = (lo + Math.imul(al8, bl8)) | 0;
|
||
|
mid = (mid + Math.imul(al8, bh8)) | 0;
|
||
|
mid = (mid + Math.imul(ah8, bl8)) | 0;
|
||
|
hi = (hi + Math.imul(ah8, bh8)) | 0;
|
||
|
lo = (lo + Math.imul(al7, bl9)) | 0;
|
||
|
mid = (mid + Math.imul(al7, bh9)) | 0;
|
||
|
mid = (mid + Math.imul(ah7, bl9)) | 0;
|
||
|
hi = (hi + Math.imul(ah7, bh9)) | 0;
|
||
|
var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0;
|
||
|
w16 &= 0x3ffffff;
|
||
|
/* k = 17 */
|
||
|
lo = Math.imul(al9, bl8);
|
||
|
mid = Math.imul(al9, bh8);
|
||
|
mid = (mid + Math.imul(ah9, bl8)) | 0;
|
||
|
hi = Math.imul(ah9, bh8);
|
||
|
lo = (lo + Math.imul(al8, bl9)) | 0;
|
||
|
mid = (mid + Math.imul(al8, bh9)) | 0;
|
||
|
mid = (mid + Math.imul(ah8, bl9)) | 0;
|
||
|
hi = (hi + Math.imul(ah8, bh9)) | 0;
|
||
|
var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0;
|
||
|
w17 &= 0x3ffffff;
|
||
|
/* k = 18 */
|
||
|
lo = Math.imul(al9, bl9);
|
||
|
mid = Math.imul(al9, bh9);
|
||
|
mid = (mid + Math.imul(ah9, bl9)) | 0;
|
||
|
hi = Math.imul(ah9, bh9);
|
||
|
var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;
|
||
|
c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0;
|
||
|
w18 &= 0x3ffffff;
|
||
|
o[0] = w0;
|
||
|
o[1] = w1;
|
||
|
o[2] = w2;
|
||
|
o[3] = w3;
|
||
|
o[4] = w4;
|
||
|
o[5] = w5;
|
||
|
o[6] = w6;
|
||
|
o[7] = w7;
|
||
|
o[8] = w8;
|
||
|
o[9] = w9;
|
||
|
o[10] = w10;
|
||
|
o[11] = w11;
|
||
|
o[12] = w12;
|
||
|
o[13] = w13;
|
||
|
o[14] = w14;
|
||
|
o[15] = w15;
|
||
|
o[16] = w16;
|
||
|
o[17] = w17;
|
||
|
o[18] = w18;
|
||
|
if (c !== 0) {
|
||
|
o[19] = c;
|
||
|
out.length++;
|
||
|
}
|
||
|
return out;
|
||
|
};
|
||
|
|
||
|
// Polyfill comb
|
||
|
if (!Math.imul) {
|
||
|
comb10MulTo = smallMulTo;
|
||
|
}
|
||
|
|
||
|
function bigMulTo (self, num, out) {
|
||
|
out.negative = num.negative ^ self.negative;
|
||
|
out.length = self.length + num.length;
|
||
|
|
||
|
var carry = 0;
|
||
|
var hncarry = 0;
|
||
|
for (var k = 0; k < out.length - 1; k++) {
|
||
|
// Sum all words with the same `i + j = k` and accumulate `ncarry`,
|
||
|
// note that ncarry could be >= 0x3ffffff
|
||
|
var ncarry = hncarry;
|
||
|
hncarry = 0;
|
||
|
var rword = carry & 0x3ffffff;
|
||
|
var maxJ = Math.min(k, num.length - 1);
|
||
|
for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) {
|
||
|
var i = k - j;
|
||
|
var a = self.words[i] | 0;
|
||
|
var b = num.words[j] | 0;
|
||
|
var r = a * b;
|
||
|
|
||
|
var lo = r & 0x3ffffff;
|
||
|
ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0;
|
||
|
lo = (lo + rword) | 0;
|
||
|
rword = lo & 0x3ffffff;
|
||
|
ncarry = (ncarry + (lo >>> 26)) | 0;
|
||
|
|
||
|
hncarry += ncarry >>> 26;
|
||
|
ncarry &= 0x3ffffff;
|
||
|
}
|
||
|
out.words[k] = rword;
|
||
|
carry = ncarry;
|
||
|
ncarry = hncarry;
|
||
|
}
|
||
|
if (carry !== 0) {
|
||
|
out.words[k] = carry;
|
||
|
} else {
|
||
|
out.length--;
|
||
|
}
|
||
|
|
||
|
return out.strip();
|
||
|
}
|
||
|
|
||
|
function jumboMulTo (self, num, out) {
|
||
|
var fftm = new FFTM();
|
||
|
return fftm.mulp(self, num, out);
|
||
|
}
|
||
|
|
||
|
BN.prototype.mulTo = function mulTo (num, out) {
|
||
|
var res;
|
||
|
var len = this.length + num.length;
|
||
|
if (this.length === 10 && num.length === 10) {
|
||
|
res = comb10MulTo(this, num, out);
|
||
|
} else if (len < 63) {
|
||
|
res = smallMulTo(this, num, out);
|
||
|
} else if (len < 1024) {
|
||
|
res = bigMulTo(this, num, out);
|
||
|
} else {
|
||
|
res = jumboMulTo(this, num, out);
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
// Cooley-Tukey algorithm for FFT
|
||
|
// slightly revisited to rely on looping instead of recursion
|
||
|
|
||
|
function FFTM (x, y) {
|
||
|
this.x = x;
|
||
|
this.y = y;
|
||
|
}
|
||
|
|
||
|
FFTM.prototype.makeRBT = function makeRBT (N) {
|
||
|
var t = new Array(N);
|
||
|
var l = BN.prototype._countBits(N) - 1;
|
||
|
for (var i = 0; i < N; i++) {
|
||
|
t[i] = this.revBin(i, l, N);
|
||
|
}
|
||
|
|
||
|
return t;
|
||
|
};
|
||
|
|
||
|
// Returns binary-reversed representation of `x`
|
||
|
FFTM.prototype.revBin = function revBin (x, l, N) {
|
||
|
if (x === 0 || x === N - 1) return x;
|
||
|
|
||
|
var rb = 0;
|
||
|
for (var i = 0; i < l; i++) {
|
||
|
rb |= (x & 1) << (l - i - 1);
|
||
|
x >>= 1;
|
||
|
}
|
||
|
|
||
|
return rb;
|
||
|
};
|
||
|
|
||
|
// Performs "tweedling" phase, therefore 'emulating'
|
||
|
// behaviour of the recursive algorithm
|
||
|
FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) {
|
||
|
for (var i = 0; i < N; i++) {
|
||
|
rtws[i] = rws[rbt[i]];
|
||
|
itws[i] = iws[rbt[i]];
|
||
|
}
|
||
|
};
|
||
|
|
||
|
FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) {
|
||
|
this.permute(rbt, rws, iws, rtws, itws, N);
|
||
|
|
||
|
for (var s = 1; s < N; s <<= 1) {
|
||
|
var l = s << 1;
|
||
|
|
||
|
var rtwdf = Math.cos(2 * Math.PI / l);
|
||
|
var itwdf = Math.sin(2 * Math.PI / l);
|
||
|
|
||
|
for (var p = 0; p < N; p += l) {
|
||
|
var rtwdf_ = rtwdf;
|
||
|
var itwdf_ = itwdf;
|
||
|
|
||
|
for (var j = 0; j < s; j++) {
|
||
|
var re = rtws[p + j];
|
||
|
var ie = itws[p + j];
|
||
|
|
||
|
var ro = rtws[p + j + s];
|
||
|
var io = itws[p + j + s];
|
||
|
|
||
|
var rx = rtwdf_ * ro - itwdf_ * io;
|
||
|
|
||
|
io = rtwdf_ * io + itwdf_ * ro;
|
||
|
ro = rx;
|
||
|
|
||
|
rtws[p + j] = re + ro;
|
||
|
itws[p + j] = ie + io;
|
||
|
|
||
|
rtws[p + j + s] = re - ro;
|
||
|
itws[p + j + s] = ie - io;
|
||
|
|
||
|
/* jshint maxdepth : false */
|
||
|
if (j !== l) {
|
||
|
rx = rtwdf * rtwdf_ - itwdf * itwdf_;
|
||
|
|
||
|
itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_;
|
||
|
rtwdf_ = rx;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
FFTM.prototype.guessLen13b = function guessLen13b (n, m) {
|
||
|
var N = Math.max(m, n) | 1;
|
||
|
var odd = N & 1;
|
||
|
var i = 0;
|
||
|
for (N = N / 2 | 0; N; N = N >>> 1) {
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
return 1 << i + 1 + odd;
|
||
|
};
|
||
|
|
||
|
FFTM.prototype.conjugate = function conjugate (rws, iws, N) {
|
||
|
if (N <= 1) return;
|
||
|
|
||
|
for (var i = 0; i < N / 2; i++) {
|
||
|
var t = rws[i];
|
||
|
|
||
|
rws[i] = rws[N - i - 1];
|
||
|
rws[N - i - 1] = t;
|
||
|
|
||
|
t = iws[i];
|
||
|
|
||
|
iws[i] = -iws[N - i - 1];
|
||
|
iws[N - i - 1] = -t;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
FFTM.prototype.normalize13b = function normalize13b (ws, N) {
|
||
|
var carry = 0;
|
||
|
for (var i = 0; i < N / 2; i++) {
|
||
|
var w = Math.round(ws[2 * i + 1] / N) * 0x2000 +
|
||
|
Math.round(ws[2 * i] / N) +
|
||
|
carry;
|
||
|
|
||
|
ws[i] = w & 0x3ffffff;
|
||
|
|
||
|
if (w < 0x4000000) {
|
||
|
carry = 0;
|
||
|
} else {
|
||
|
carry = w / 0x4000000 | 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ws;
|
||
|
};
|
||
|
|
||
|
FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) {
|
||
|
var carry = 0;
|
||
|
for (var i = 0; i < len; i++) {
|
||
|
carry = carry + (ws[i] | 0);
|
||
|
|
||
|
rws[2 * i] = carry & 0x1fff; carry = carry >>> 13;
|
||
|
rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13;
|
||
|
}
|
||
|
|
||
|
// Pad with zeroes
|
||
|
for (i = 2 * len; i < N; ++i) {
|
||
|
rws[i] = 0;
|
||
|
}
|
||
|
|
||
|
assert(carry === 0);
|
||
|
assert((carry & ~0x1fff) === 0);
|
||
|
};
|
||
|
|
||
|
FFTM.prototype.stub = function stub (N) {
|
||
|
var ph = new Array(N);
|
||
|
for (var i = 0; i < N; i++) {
|
||
|
ph[i] = 0;
|
||
|
}
|
||
|
|
||
|
return ph;
|
||
|
};
|
||
|
|
||
|
FFTM.prototype.mulp = function mulp (x, y, out) {
|
||
|
var N = 2 * this.guessLen13b(x.length, y.length);
|
||
|
|
||
|
var rbt = this.makeRBT(N);
|
||
|
|
||
|
var _ = this.stub(N);
|
||
|
|
||
|
var rws = new Array(N);
|
||
|
var rwst = new Array(N);
|
||
|
var iwst = new Array(N);
|
||
|
|
||
|
var nrws = new Array(N);
|
||
|
var nrwst = new Array(N);
|
||
|
var niwst = new Array(N);
|
||
|
|
||
|
var rmws = out.words;
|
||
|
rmws.length = N;
|
||
|
|
||
|
this.convert13b(x.words, x.length, rws, N);
|
||
|
this.convert13b(y.words, y.length, nrws, N);
|
||
|
|
||
|
this.transform(rws, _, rwst, iwst, N, rbt);
|
||
|
this.transform(nrws, _, nrwst, niwst, N, rbt);
|
||
|
|
||
|
for (var i = 0; i < N; i++) {
|
||
|
var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i];
|
||
|
iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i];
|
||
|
rwst[i] = rx;
|
||
|
}
|
||
|
|
||
|
this.conjugate(rwst, iwst, N);
|
||
|
this.transform(rwst, iwst, rmws, _, N, rbt);
|
||
|
this.conjugate(rmws, _, N);
|
||
|
this.normalize13b(rmws, N);
|
||
|
|
||
|
out.negative = x.negative ^ y.negative;
|
||
|
out.length = x.length + y.length;
|
||
|
return out.strip();
|
||
|
};
|
||
|
|
||
|
// Multiply `this` by `num`
|
||
|
BN.prototype.mul = function mul (num) {
|
||
|
var out = new BN(null);
|
||
|
out.words = new Array(this.length + num.length);
|
||
|
return this.mulTo(num, out);
|
||
|
};
|
||
|
|
||
|
// Multiply employing FFT
|
||
|
BN.prototype.mulf = function mulf (num) {
|
||
|
var out = new BN(null);
|
||
|
out.words = new Array(this.length + num.length);
|
||
|
return jumboMulTo(this, num, out);
|
||
|
};
|
||
|
|
||
|
// In-place Multiplication
|
||
|
BN.prototype.imul = function imul (num) {
|
||
|
return this.clone().mulTo(num, this);
|
||
|
};
|
||
|
|
||
|
BN.prototype.imuln = function imuln (num) {
|
||
|
assert(typeof num === 'number');
|
||
|
assert(num < 0x4000000);
|
||
|
|
||
|
// Carry
|
||
|
var carry = 0;
|
||
|
for (var i = 0; i < this.length; i++) {
|
||
|
var w = (this.words[i] | 0) * num;
|
||
|
var lo = (w & 0x3ffffff) + (carry & 0x3ffffff);
|
||
|
carry >>= 26;
|
||
|
carry += (w / 0x4000000) | 0;
|
||
|
// NOTE: lo is 27bit maximum
|
||
|
carry += lo >>> 26;
|
||
|
this.words[i] = lo & 0x3ffffff;
|
||
|
}
|
||
|
|
||
|
if (carry !== 0) {
|
||
|
this.words[i] = carry;
|
||
|
this.length++;
|
||
|
}
|
||
|
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
BN.prototype.muln = function muln (num) {
|
||
|
return this.clone().imuln(num);
|
||
|
};
|
||
|
|
||
|
// `this` * `this`
|
||
|
BN.prototype.sqr = function sqr () {
|
||
|
return this.mul(this);
|
||
|
};
|
||
|
|
||
|
// `this` * `this` in-place
|
||
|
BN.prototype.isqr = function isqr () {
|
||
|
return this.imul(this.clone());
|
||
|
};
|
||
|
|
||
|
// Math.pow(`this`, `num`)
|
||
|
BN.prototype.pow = function pow (num) {
|
||
|
var w = toBitArray(num);
|
||
|
if (w.length === 0) return new BN(1);
|
||
|
|
||
|
// Skip leading zeroes
|
||
|
var res = this;
|
||
|
for (var i = 0; i < w.length; i++, res = res.sqr()) {
|
||
|
if (w[i] !== 0) break;
|
||
|
}
|
||
|
|
||
|
if (++i < w.length) {
|
||
|
for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) {
|
||
|
if (w[i] === 0) continue;
|
||
|
|
||
|
res = res.mul(q);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
// Shift-left in-place
|
||
|
BN.prototype.iushln = function iushln (bits) {
|
||
|
assert(typeof bits === 'number' && bits >= 0);
|
||
|
var r = bits % 26;
|
||
|
var s = (bits - r) / 26;
|
||
|
var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r);
|
||
|
var i;
|
||
|
|
||
|
if (r !== 0) {
|
||
|
var carry = 0;
|
||
|
|
||
|
for (i = 0; i < this.length; i++) {
|
||
|
var newCarry = this.words[i] & carryMask;
|
||
|
var c = ((this.words[i] | 0) - newCarry) << r;
|
||
|
this.words[i] = c | carry;
|
||
|
carry = newCarry >>> (26 - r);
|
||
|
}
|
||
|
|
||
|
if (carry) {
|
||
|
this.words[i] = carry;
|
||
|
this.length++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (s !== 0) {
|
||
|
for (i = this.length - 1; i >= 0; i--) {
|
||
|
this.words[i + s] = this.words[i];
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < s; i++) {
|
||
|
this.words[i] = 0;
|
||
|
}
|
||
|
|
||
|
this.length += s;
|
||
|
}
|
||
|
|
||
|
return this.strip();
|
||
|
};
|
||
|
|
||
|
BN.prototype.ishln = function ishln (bits) {
|
||
|
// TODO(indutny): implement me
|
||
|
assert(this.negative === 0);
|
||
|
return this.iushln(bits);
|
||
|
};
|
||
|
|
||
|
// Shift-right in-place
|
||
|
// NOTE: `hint` is a lowest bit before trailing zeroes
|
||
|
// NOTE: if `extended` is present - it will be filled with destroyed bits
|
||
|
BN.prototype.iushrn = function iushrn (bits, hint, extended) {
|
||
|
assert(typeof bits === 'number' && bits >= 0);
|
||
|
var h;
|
||
|
if (hint) {
|
||
|
h = (hint - (hint % 26)) / 26;
|
||
|
} else {
|
||
|
h = 0;
|
||
|
}
|
||
|
|
||
|
var r = bits % 26;
|
||
|
var s = Math.min((bits - r) / 26, this.length);
|
||
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
||
|
var maskedWords = extended;
|
||
|
|
||
|
h -= s;
|
||
|
h = Math.max(0, h);
|
||
|
|
||
|
// Extended mode, copy masked part
|
||
|
if (maskedWords) {
|
||
|
for (var i = 0; i < s; i++) {
|
||
|
maskedWords.words[i] = this.words[i];
|
||
|
}
|
||
|
maskedWords.length = s;
|
||
|
}
|
||
|
|
||
|
if (s === 0) {
|
||
|
// No-op, we should not move anything at all
|
||
|
} else if (this.length > s) {
|
||
|
this.length -= s;
|
||
|
for (i = 0; i < this.length; i++) {
|
||
|
this.words[i] = this.words[i + s];
|
||
|
}
|
||
|
} else {
|
||
|
this.words[0] = 0;
|
||
|
this.length = 1;
|
||
|
}
|
||
|
|
||
|
var carry = 0;
|
||
|
for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) {
|
||
|
var word = this.words[i] | 0;
|
||
|
this.words[i] = (carry << (26 - r)) | (word >>> r);
|
||
|
carry = word & mask;
|
||
|
}
|
||
|
|
||
|
// Push carried bits as a mask
|
||
|
if (maskedWords && carry !== 0) {
|
||
|
maskedWords.words[maskedWords.length++] = carry;
|
||
|
}
|
||
|
|
||
|
if (this.length === 0) {
|
||
|
this.words[0] = 0;
|
||
|
this.length = 1;
|
||
|
}
|
||
|
|
||
|
return this.strip();
|
||
|
};
|
||
|
|
||
|
BN.prototype.ishrn = function ishrn (bits, hint, extended) {
|
||
|
// TODO(indutny): implement me
|
||
|
assert(this.negative === 0);
|
||
|
return this.iushrn(bits, hint, extended);
|
||
|
};
|
||
|
|
||
|
// Shift-left
|
||
|
BN.prototype.shln = function shln (bits) {
|
||
|
return this.clone().ishln(bits);
|
||
|
};
|
||
|
|
||
|
BN.prototype.ushln = function ushln (bits) {
|
||
|
return this.clone().iushln(bits);
|
||
|
};
|
||
|
|
||
|
// Shift-right
|
||
|
BN.prototype.shrn = function shrn (bits) {
|
||
|
return this.clone().ishrn(bits);
|
||
|
};
|
||
|
|
||
|
BN.prototype.ushrn = function ushrn (bits) {
|
||
|
return this.clone().iushrn(bits);
|
||
|
};
|
||
|
|
||
|
// Test if n bit is set
|
||
|
BN.prototype.testn = function testn (bit) {
|
||
|
assert(typeof bit === 'number' && bit >= 0);
|
||
|
var r = bit % 26;
|
||
|
var s = (bit - r) / 26;
|
||
|
var q = 1 << r;
|
||
|
|
||
|
// Fast case: bit is much higher than all existing words
|
||
|
if (this.length <= s) return false;
|
||
|
|
||
|
// Check bit and return
|
||
|
var w = this.words[s];
|
||
|
|
||
|
return !!(w & q);
|
||
|
};
|
||
|
|
||
|
// Return only lowers bits of number (in-place)
|
||
|
BN.prototype.imaskn = function imaskn (bits) {
|
||
|
assert(typeof bits === 'number' && bits >= 0);
|
||
|
var r = bits % 26;
|
||
|
var s = (bits - r) / 26;
|
||
|
|
||
|
assert(this.negative === 0, 'imaskn works only with positive numbers');
|
||
|
|
||
|
if (this.length <= s) {
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
if (r !== 0) {
|
||
|
s++;
|
||
|
}
|
||
|
this.length = Math.min(s, this.length);
|
||
|
|
||
|
if (r !== 0) {
|
||
|
var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r);
|
||
|
this.words[this.length - 1] &= mask;
|
||
|
}
|
||
|
|
||
|
return this.strip();
|
||
|
};
|
||
|
|
||
|
// Return only lowers bits of number
|
||
|
BN.prototype.maskn = function maskn (bits) {
|
||
|
return this.clone().imaskn(bits);
|
||
|
};
|
||
|
|
||
|
// Add plain number `num` to `this`
|
||
|
BN.prototype.iaddn = function iaddn (num) {
|
||
|
assert(typeof num === 'number');
|
||
|
assert(num < 0x4000000);
|
||
|
if (num < 0) return this.isubn(-num);
|
||
|
|
||
|
// Possible sign change
|
||
|
if (this.negative !== 0) {
|
||
|
if (this.length === 1 && (this.words[0] | 0) < num) {
|
||
|
this.words[0] = num - (this.words[0] | 0);
|
||
|
this.negative = 0;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
this.negative = 0;
|
||
|
this.isubn(num);
|
||
|
this.negative = 1;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
// Add without checks
|
||
|
return this._iaddn(num);
|
||
|
};
|
||
|
|
||
|
BN.prototype._iaddn = function _iaddn (num) {
|
||
|
this.words[0] += num;
|
||
|
|
||
|
// Carry
|
||
|
for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) {
|
||
|
this.words[i] -= 0x4000000;
|
||
|
if (i === this.length - 1) {
|
||
|
this.words[i + 1] = 1;
|
||
|
} else {
|
||
|
this.words[i + 1]++;
|
||
|
}
|
||
|
}
|
||
|
this.length = Math.max(this.length, i + 1);
|
||
|
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
// Subtract plain number `num` from `this`
|
||
|
BN.prototype.isubn = function isubn (num) {
|
||
|
assert(typeof num === 'number');
|
||
|
assert(num < 0x4000000);
|
||
|
if (num < 0) return this.iaddn(-num);
|
||
|
|
||
|
if (this.negative !== 0) {
|
||
|
this.negative = 0;
|
||
|
this.iaddn(num);
|
||
|
this.negative = 1;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
this.words[0] -= num;
|
||
|
|
||
|
if (this.length === 1 && this.words[0] < 0) {
|
||
|
this.words[0] = -this.words[0];
|
||
|
this.negative = 1;
|
||
|
} else {
|
||
|
// Carry
|
||
|
for (var i = 0; i < this.length && this.words[i] < 0; i++) {
|
||
|
this.words[i] += 0x4000000;
|
||
|
this.words[i + 1] -= 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return this.strip();
|
||
|
};
|
||
|
|
||
|
BN.prototype.addn = function addn (num) {
|
||
|
return this.clone().iaddn(num);
|
||
|
};
|
||
|
|
||
|
BN.prototype.subn = function subn (num) {
|
||
|
return this.clone().isubn(num);
|
||
|
};
|
||
|
|
||
|
BN.prototype.iabs = function iabs () {
|
||
|
this.negative = 0;
|
||
|
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
BN.prototype.abs = function abs () {
|
||
|
return this.clone().iabs();
|
||
|
};
|
||
|
|
||
|
BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) {
|
||
|
var len = num.length + shift;
|
||
|
var i;
|
||
|
|
||
|
this._expand(len);
|
||
|
|
||
|
var w;
|
||
|
var carry = 0;
|
||
|
for (i = 0; i < num.length; i++) {
|
||
|
w = (this.words[i + shift] | 0) + carry;
|
||
|
var right = (num.words[i] | 0) * mul;
|
||
|
w -= right & 0x3ffffff;
|
||
|
carry = (w >> 26) - ((right / 0x4000000) | 0);
|
||
|
this.words[i + shift] = w & 0x3ffffff;
|
||
|
}
|
||
|
for (; i < this.length - shift; i++) {
|
||
|
w = (this.words[i + shift] | 0) + carry;
|
||
|
carry = w >> 26;
|
||
|
this.words[i + shift] = w & 0x3ffffff;
|
||
|
}
|
||
|
|
||
|
if (carry === 0) return this.strip();
|
||
|
|
||
|
// Subtraction overflow
|
||
|
assert(carry === -1);
|
||
|
carry = 0;
|
||
|
for (i = 0; i < this.length; i++) {
|
||
|
w = -(this.words[i] | 0) + carry;
|
||
|
carry = w >> 26;
|
||
|
this.words[i] = w & 0x3ffffff;
|
||
|
}
|
||
|
this.negative = 1;
|
||
|
|
||
|
return this.strip();
|
||
|
};
|
||
|
|
||
|
BN.prototype._wordDiv = function _wordDiv (num, mode) {
|
||
|
var shift = this.length - num.length;
|
||
|
|
||
|
var a = this.clone();
|
||
|
var b = num;
|
||
|
|
||
|
// Normalize
|
||
|
var bhi = b.words[b.length - 1] | 0;
|
||
|
var bhiBits = this._countBits(bhi);
|
||
|
shift = 26 - bhiBits;
|
||
|
if (shift !== 0) {
|
||
|
b = b.ushln(shift);
|
||
|
a.iushln(shift);
|
||
|
bhi = b.words[b.length - 1] | 0;
|
||
|
}
|
||
|
|
||
|
// Initialize quotient
|
||
|
var m = a.length - b.length;
|
||
|
var q;
|
||
|
|
||
|
if (mode !== 'mod') {
|
||
|
q = new BN(null);
|
||
|
q.length = m + 1;
|
||
|
q.words = new Array(q.length);
|
||
|
for (var i = 0; i < q.length; i++) {
|
||
|
q.words[i] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var diff = a.clone()._ishlnsubmul(b, 1, m);
|
||
|
if (diff.negative === 0) {
|
||
|
a = diff;
|
||
|
if (q) {
|
||
|
q.words[m] = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (var j = m - 1; j >= 0; j--) {
|
||
|
var qj = (a.words[b.length + j] | 0) * 0x4000000 +
|
||
|
(a.words[b.length + j - 1] | 0);
|
||
|
|
||
|
// NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max
|
||
|
// (0x7ffffff)
|
||
|
qj = Math.min((qj / bhi) | 0, 0x3ffffff);
|
||
|
|
||
|
a._ishlnsubmul(b, qj, j);
|
||
|
while (a.negative !== 0) {
|
||
|
qj--;
|
||
|
a.negative = 0;
|
||
|
a._ishlnsubmul(b, 1, j);
|
||
|
if (!a.isZero()) {
|
||
|
a.negative ^= 1;
|
||
|
}
|
||
|
}
|
||
|
if (q) {
|
||
|
q.words[j] = qj;
|
||
|
}
|
||
|
}
|
||
|
if (q) {
|
||
|
q.strip();
|
||
|
}
|
||
|
a.strip();
|
||
|
|
||
|
// Denormalize
|
||
|
if (mode !== 'div' && shift !== 0) {
|
||
|
a.iushrn(shift);
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
div: q || null,
|
||
|
mod: a
|
||
|
};
|
||
|
};
|
||
|
|
||
|
// NOTE: 1) `mode` can be set to `mod` to request mod only,
|
||
|
// to `div` to request div only, or be absent to
|
||
|
// request both div & mod
|
||
|
// 2) `positive` is true if unsigned mod is requested
|
||
|
BN.prototype.divmod = function divmod (num, mode, positive) {
|
||
|
assert(!num.isZero());
|
||
|
|
||
|
if (this.isZero()) {
|
||
|
return {
|
||
|
div: new BN(0),
|
||
|
mod: new BN(0)
|
||
|
};
|
||
|
}
|
||
|
|
||
|
var div, mod, res;
|
||
|
if (this.negative !== 0 && num.negative === 0) {
|
||
|
res = this.neg().divmod(num, mode);
|
||
|
|
||
|
if (mode !== 'mod') {
|
||
|
div = res.div.neg();
|
||
|
}
|
||
|
|
||
|
if (mode !== 'div') {
|
||
|
mod = res.mod.neg();
|
||
|
if (positive && mod.negative !== 0) {
|
||
|
mod.iadd(num);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
div: div,
|
||
|
mod: mod
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if (this.negative === 0 && num.negative !== 0) {
|
||
|
res = this.divmod(num.neg(), mode);
|
||
|
|
||
|
if (mode !== 'mod') {
|
||
|
div = res.div.neg();
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
div: div,
|
||
|
mod: res.mod
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if ((this.negative & num.negative) !== 0) {
|
||
|
res = this.neg().divmod(num.neg(), mode);
|
||
|
|
||
|
if (mode !== 'div') {
|
||
|
mod = res.mod.neg();
|
||
|
if (positive && mod.negative !== 0) {
|
||
|
mod.isub(num);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
div: res.div,
|
||
|
mod: mod
|
||
|
};
|
||
|
}
|
||
|
|
||
|
// Both numbers are positive at this point
|
||
|
|
||
|
// Strip both numbers to approximate shift value
|
||
|
if (num.length > this.length || this.cmp(num) < 0) {
|
||
|
return {
|
||
|
div: new BN(0),
|
||
|
mod: this
|
||
|
};
|
||
|
}
|
||
|
|
||
|
// Very short reduction
|
||
|
if (num.length === 1) {
|
||
|
if (mode === 'div') {
|
||
|
return {
|
||
|
div: this.divn(num.words[0]),
|
||
|
mod: null
|
||
|
};
|
||
|
}
|
||
|
|
||
|
if (mode === 'mod') {
|
||
|
return {
|
||
|
div: null,
|
||
|
mod: new BN(this.modn(num.words[0]))
|
||
|
};
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
div: this.divn(num.words[0]),
|
||
|
mod: new BN(this.modn(num.words[0]))
|
||
|
};
|
||
|
}
|
||
|
|
||
|
return this._wordDiv(num, mode);
|
||
|
};
|
||
|
|
||
|
// Find `this` / `num`
|
||
|
BN.prototype.div = function div (num) {
|
||
|
return this.divmod(num, 'div', false).div;
|
||
|
};
|
||
|
|
||
|
// Find `this` % `num`
|
||
|
BN.prototype.mod = function mod (num) {
|
||
|
return this.divmod(num, 'mod', false).mod;
|
||
|
};
|
||
|
|
||
|
BN.prototype.umod = function umod (num) {
|
||
|
return this.divmod(num, 'mod', true).mod;
|
||
|
};
|
||
|
|
||
|
// Find Round(`this` / `num`)
|
||
|
BN.prototype.divRound = function divRound (num) {
|
||
|
var dm = this.divmod(num);
|
||
|
|
||
|
// Fast case - exact division
|
||
|
if (dm.mod.isZero()) return dm.div;
|
||
|
|
||
|
var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod;
|
||
|
|
||
|
var half = num.ushrn(1);
|
||
|
var r2 = num.andln(1);
|
||
|
var cmp = mod.cmp(half);
|
||
|
|
||
|
// Round down
|
||
|
if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div;
|
||
|
|
||
|
// Round up
|
||
|
return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1);
|
||
|
};
|
||
|
|
||
|
BN.prototype.modn = function modn (num) {
|
||
|
assert(num <= 0x3ffffff);
|
||
|
var p = (1 << 26) % num;
|
||
|
|
||
|
var acc = 0;
|
||
|
for (var i = this.length - 1; i >= 0; i--) {
|
||
|
acc = (p * acc + (this.words[i] | 0)) % num;
|
||
|
}
|
||
|
|
||
|
return acc;
|
||
|
};
|
||
|
|
||
|
// In-place division by number
|
||
|
BN.prototype.idivn = function idivn (num) {
|
||
|
assert(num <= 0x3ffffff);
|
||
|
|
||
|
var carry = 0;
|
||
|
for (var i = this.length - 1; i >= 0; i--) {
|
||
|
var w = (this.words[i] | 0) + carry * 0x4000000;
|
||
|
this.words[i] = (w / num) | 0;
|
||
|
carry = w % num;
|
||
|
}
|
||
|
|
||
|
return this.strip();
|
||
|
};
|
||
|
|
||
|
BN.prototype.divn = function divn (num) {
|
||
|
return this.clone().idivn(num);
|
||
|
};
|
||
|
|
||
|
BN.prototype.egcd = function egcd (p) {
|
||
|
assert(p.negative === 0);
|
||
|
assert(!p.isZero());
|
||
|
|
||
|
var x = this;
|
||
|
var y = p.clone();
|
||
|
|
||
|
if (x.negative !== 0) {
|
||
|
x = x.umod(p);
|
||
|
} else {
|
||
|
x = x.clone();
|
||
|
}
|
||
|
|
||
|
// A * x + B * y = x
|
||
|
var A = new BN(1);
|
||
|
var B = new BN(0);
|
||
|
|
||
|
// C * x + D * y = y
|
||
|
var C = new BN(0);
|
||
|
var D = new BN(1);
|
||
|
|
||
|
var g = 0;
|
||
|
|
||
|
while (x.isEven() && y.isEven()) {
|
||
|
x.iushrn(1);
|
||
|
y.iushrn(1);
|
||
|
++g;
|
||
|
}
|
||
|
|
||
|
var yp = y.clone();
|
||
|
var xp = x.clone();
|
||
|
|
||
|
while (!x.isZero()) {
|
||
|
for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
||
|
if (i > 0) {
|
||
|
x.iushrn(i);
|
||
|
while (i-- > 0) {
|
||
|
if (A.isOdd() || B.isOdd()) {
|
||
|
A.iadd(yp);
|
||
|
B.isub(xp);
|
||
|
}
|
||
|
|
||
|
A.iushrn(1);
|
||
|
B.iushrn(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
||
|
if (j > 0) {
|
||
|
y.iushrn(j);
|
||
|
while (j-- > 0) {
|
||
|
if (C.isOdd() || D.isOdd()) {
|
||
|
C.iadd(yp);
|
||
|
D.isub(xp);
|
||
|
}
|
||
|
|
||
|
C.iushrn(1);
|
||
|
D.iushrn(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (x.cmp(y) >= 0) {
|
||
|
x.isub(y);
|
||
|
A.isub(C);
|
||
|
B.isub(D);
|
||
|
} else {
|
||
|
y.isub(x);
|
||
|
C.isub(A);
|
||
|
D.isub(B);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
a: C,
|
||
|
b: D,
|
||
|
gcd: y.iushln(g)
|
||
|
};
|
||
|
};
|
||
|
|
||
|
// This is reduced incarnation of the binary EEA
|
||
|
// above, designated to invert members of the
|
||
|
// _prime_ fields F(p) at a maximal speed
|
||
|
BN.prototype._invmp = function _invmp (p) {
|
||
|
assert(p.negative === 0);
|
||
|
assert(!p.isZero());
|
||
|
|
||
|
var a = this;
|
||
|
var b = p.clone();
|
||
|
|
||
|
if (a.negative !== 0) {
|
||
|
a = a.umod(p);
|
||
|
} else {
|
||
|
a = a.clone();
|
||
|
}
|
||
|
|
||
|
var x1 = new BN(1);
|
||
|
var x2 = new BN(0);
|
||
|
|
||
|
var delta = b.clone();
|
||
|
|
||
|
while (a.cmpn(1) > 0 && b.cmpn(1) > 0) {
|
||
|
for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1);
|
||
|
if (i > 0) {
|
||
|
a.iushrn(i);
|
||
|
while (i-- > 0) {
|
||
|
if (x1.isOdd()) {
|
||
|
x1.iadd(delta);
|
||
|
}
|
||
|
|
||
|
x1.iushrn(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1);
|
||
|
if (j > 0) {
|
||
|
b.iushrn(j);
|
||
|
while (j-- > 0) {
|
||
|
if (x2.isOdd()) {
|
||
|
x2.iadd(delta);
|
||
|
}
|
||
|
|
||
|
x2.iushrn(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (a.cmp(b) >= 0) {
|
||
|
a.isub(b);
|
||
|
x1.isub(x2);
|
||
|
} else {
|
||
|
b.isub(a);
|
||
|
x2.isub(x1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var res;
|
||
|
if (a.cmpn(1) === 0) {
|
||
|
res = x1;
|
||
|
} else {
|
||
|
res = x2;
|
||
|
}
|
||
|
|
||
|
if (res.cmpn(0) < 0) {
|
||
|
res.iadd(p);
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
BN.prototype.gcd = function gcd (num) {
|
||
|
if (this.isZero()) return num.abs();
|
||
|
if (num.isZero()) return this.abs();
|
||
|
|
||
|
var a = this.clone();
|
||
|
var b = num.clone();
|
||
|
a.negative = 0;
|
||
|
b.negative = 0;
|
||
|
|
||
|
// Remove common factor of two
|
||
|
for (var shift = 0; a.isEven() && b.isEven(); shift++) {
|
||
|
a.iushrn(1);
|
||
|
b.iushrn(1);
|
||
|
}
|
||
|
|
||
|
do {
|
||
|
while (a.isEven()) {
|
||
|
a.iushrn(1);
|
||
|
}
|
||
|
while (b.isEven()) {
|
||
|
b.iushrn(1);
|
||
|
}
|
||
|
|
||
|
var r = a.cmp(b);
|
||
|
if (r < 0) {
|
||
|
// Swap `a` and `b` to make `a` always bigger than `b`
|
||
|
var t = a;
|
||
|
a = b;
|
||
|
b = t;
|
||
|
} else if (r === 0 || b.cmpn(1) === 0) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
a.isub(b);
|
||
|
} while (true);
|
||
|
|
||
|
return b.iushln(shift);
|
||
|
};
|
||
|
|
||
|
// Invert number in the field F(num)
|
||
|
BN.prototype.invm = function invm (num) {
|
||
|
return this.egcd(num).a.umod(num);
|
||
|
};
|
||
|
|
||
|
BN.prototype.isEven = function isEven () {
|
||
|
return (this.words[0] & 1) === 0;
|
||
|
};
|
||
|
|
||
|
BN.prototype.isOdd = function isOdd () {
|
||
|
return (this.words[0] & 1) === 1;
|
||
|
};
|
||
|
|
||
|
// And first word and num
|
||
|
BN.prototype.andln = function andln (num) {
|
||
|
return this.words[0] & num;
|
||
|
};
|
||
|
|
||
|
// Increment at the bit position in-line
|
||
|
BN.prototype.bincn = function bincn (bit) {
|
||
|
assert(typeof bit === 'number');
|
||
|
var r = bit % 26;
|
||
|
var s = (bit - r) / 26;
|
||
|
var q = 1 << r;
|
||
|
|
||
|
// Fast case: bit is much higher than all existing words
|
||
|
if (this.length <= s) {
|
||
|
this._expand(s + 1);
|
||
|
this.words[s] |= q;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
// Add bit and propagate, if needed
|
||
|
var carry = q;
|
||
|
for (var i = s; carry !== 0 && i < this.length; i++) {
|
||
|
var w = this.words[i] | 0;
|
||
|
w += carry;
|
||
|
carry = w >>> 26;
|
||
|
w &= 0x3ffffff;
|
||
|
this.words[i] = w;
|
||
|
}
|
||
|
if (carry !== 0) {
|
||
|
this.words[i] = carry;
|
||
|
this.length++;
|
||
|
}
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
BN.prototype.isZero = function isZero () {
|
||
|
return this.length === 1 && this.words[0] === 0;
|
||
|
};
|
||
|
|
||
|
BN.prototype.cmpn = function cmpn (num) {
|
||
|
var negative = num < 0;
|
||
|
|
||
|
if (this.negative !== 0 && !negative) return -1;
|
||
|
if (this.negative === 0 && negative) return 1;
|
||
|
|
||
|
this.strip();
|
||
|
|
||
|
var res;
|
||
|
if (this.length > 1) {
|
||
|
res = 1;
|
||
|
} else {
|
||
|
if (negative) {
|
||
|
num = -num;
|
||
|
}
|
||
|
|
||
|
assert(num <= 0x3ffffff, 'Number is too big');
|
||
|
|
||
|
var w = this.words[0] | 0;
|
||
|
res = w === num ? 0 : w < num ? -1 : 1;
|
||
|
}
|
||
|
if (this.negative !== 0) return -res | 0;
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
// Compare two numbers and return:
|
||
|
// 1 - if `this` > `num`
|
||
|
// 0 - if `this` == `num`
|
||
|
// -1 - if `this` < `num`
|
||
|
BN.prototype.cmp = function cmp (num) {
|
||
|
if (this.negative !== 0 && num.negative === 0) return -1;
|
||
|
if (this.negative === 0 && num.negative !== 0) return 1;
|
||
|
|
||
|
var res = this.ucmp(num);
|
||
|
if (this.negative !== 0) return -res | 0;
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
// Unsigned comparison
|
||
|
BN.prototype.ucmp = function ucmp (num) {
|
||
|
// At this point both numbers have the same sign
|
||
|
if (this.length > num.length) return 1;
|
||
|
if (this.length < num.length) return -1;
|
||
|
|
||
|
var res = 0;
|
||
|
for (var i = this.length - 1; i >= 0; i--) {
|
||
|
var a = this.words[i] | 0;
|
||
|
var b = num.words[i] | 0;
|
||
|
|
||
|
if (a === b) continue;
|
||
|
if (a < b) {
|
||
|
res = -1;
|
||
|
} else if (a > b) {
|
||
|
res = 1;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
BN.prototype.gtn = function gtn (num) {
|
||
|
return this.cmpn(num) === 1;
|
||
|
};
|
||
|
|
||
|
BN.prototype.gt = function gt (num) {
|
||
|
return this.cmp(num) === 1;
|
||
|
};
|
||
|
|
||
|
BN.prototype.gten = function gten (num) {
|
||
|
return this.cmpn(num) >= 0;
|
||
|
};
|
||
|
|
||
|
BN.prototype.gte = function gte (num) {
|
||
|
return this.cmp(num) >= 0;
|
||
|
};
|
||
|
|
||
|
BN.prototype.ltn = function ltn (num) {
|
||
|
return this.cmpn(num) === -1;
|
||
|
};
|
||
|
|
||
|
BN.prototype.lt = function lt (num) {
|
||
|
return this.cmp(num) === -1;
|
||
|
};
|
||
|
|
||
|
BN.prototype.lten = function lten (num) {
|
||
|
return this.cmpn(num) <= 0;
|
||
|
};
|
||
|
|
||
|
BN.prototype.lte = function lte (num) {
|
||
|
return this.cmp(num) <= 0;
|
||
|
};
|
||
|
|
||
|
BN.prototype.eqn = function eqn (num) {
|
||
|
return this.cmpn(num) === 0;
|
||
|
};
|
||
|
|
||
|
BN.prototype.eq = function eq (num) {
|
||
|
return this.cmp(num) === 0;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// A reduce context, could be using montgomery or something better, depending
|
||
|
// on the `m` itself.
|
||
|
//
|
||
|
BN.red = function red (num) {
|
||
|
return new Red(num);
|
||
|
};
|
||
|
|
||
|
BN.prototype.toRed = function toRed (ctx) {
|
||
|
assert(!this.red, 'Already a number in reduction context');
|
||
|
assert(this.negative === 0, 'red works only with positives');
|
||
|
return ctx.convertTo(this)._forceRed(ctx);
|
||
|
};
|
||
|
|
||
|
BN.prototype.fromRed = function fromRed () {
|
||
|
assert(this.red, 'fromRed works only with numbers in reduction context');
|
||
|
return this.red.convertFrom(this);
|
||
|
};
|
||
|
|
||
|
BN.prototype._forceRed = function _forceRed (ctx) {
|
||
|
this.red = ctx;
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
BN.prototype.forceRed = function forceRed (ctx) {
|
||
|
assert(!this.red, 'Already a number in reduction context');
|
||
|
return this._forceRed(ctx);
|
||
|
};
|
||
|
|
||
|
BN.prototype.redAdd = function redAdd (num) {
|
||
|
assert(this.red, 'redAdd works only with red numbers');
|
||
|
return this.red.add(this, num);
|
||
|
};
|
||
|
|
||
|
BN.prototype.redIAdd = function redIAdd (num) {
|
||
|
assert(this.red, 'redIAdd works only with red numbers');
|
||
|
return this.red.iadd(this, num);
|
||
|
};
|
||
|
|
||
|
BN.prototype.redSub = function redSub (num) {
|
||
|
assert(this.red, 'redSub works only with red numbers');
|
||
|
return this.red.sub(this, num);
|
||
|
};
|
||
|
|
||
|
BN.prototype.redISub = function redISub (num) {
|
||
|
assert(this.red, 'redISub works only with red numbers');
|
||
|
return this.red.isub(this, num);
|
||
|
};
|
||
|
|
||
|
BN.prototype.redShl = function redShl (num) {
|
||
|
assert(this.red, 'redShl works only with red numbers');
|
||
|
return this.red.shl(this, num);
|
||
|
};
|
||
|
|
||
|
BN.prototype.redMul = function redMul (num) {
|
||
|
assert(this.red, 'redMul works only with red numbers');
|
||
|
this.red._verify2(this, num);
|
||
|
return this.red.mul(this, num);
|
||
|
};
|
||
|
|
||
|
BN.prototype.redIMul = function redIMul (num) {
|
||
|
assert(this.red, 'redMul works only with red numbers');
|
||
|
this.red._verify2(this, num);
|
||
|
return this.red.imul(this, num);
|
||
|
};
|
||
|
|
||
|
BN.prototype.redSqr = function redSqr () {
|
||
|
assert(this.red, 'redSqr works only with red numbers');
|
||
|
this.red._verify1(this);
|
||
|
return this.red.sqr(this);
|
||
|
};
|
||
|
|
||
|
BN.prototype.redISqr = function redISqr () {
|
||
|
assert(this.red, 'redISqr works only with red numbers');
|
||
|
this.red._verify1(this);
|
||
|
return this.red.isqr(this);
|
||
|
};
|
||
|
|
||
|
// Square root over p
|
||
|
BN.prototype.redSqrt = function redSqrt () {
|
||
|
assert(this.red, 'redSqrt works only with red numbers');
|
||
|
this.red._verify1(this);
|
||
|
return this.red.sqrt(this);
|
||
|
};
|
||
|
|
||
|
BN.prototype.redInvm = function redInvm () {
|
||
|
assert(this.red, 'redInvm works only with red numbers');
|
||
|
this.red._verify1(this);
|
||
|
return this.red.invm(this);
|
||
|
};
|
||
|
|
||
|
// Return negative clone of `this` % `red modulo`
|
||
|
BN.prototype.redNeg = function redNeg () {
|
||
|
assert(this.red, 'redNeg works only with red numbers');
|
||
|
this.red._verify1(this);
|
||
|
return this.red.neg(this);
|
||
|
};
|
||
|
|
||
|
BN.prototype.redPow = function redPow (num) {
|
||
|
assert(this.red && !num.red, 'redPow(normalNum)');
|
||
|
this.red._verify1(this);
|
||
|
return this.red.pow(this, num);
|
||
|
};
|
||
|
|
||
|
// Prime numbers with efficient reduction
|
||
|
var primes = {
|
||
|
k256: null,
|
||
|
p224: null,
|
||
|
p192: null,
|
||
|
p25519: null
|
||
|
};
|
||
|
|
||
|
// Pseudo-Mersenne prime
|
||
|
function MPrime (name, p) {
|
||
|
// P = 2 ^ N - K
|
||
|
this.name = name;
|
||
|
this.p = new BN(p, 16);
|
||
|
this.n = this.p.bitLength();
|
||
|
this.k = new BN(1).iushln(this.n).isub(this.p);
|
||
|
|
||
|
this.tmp = this._tmp();
|
||
|
}
|
||
|
|
||
|
MPrime.prototype._tmp = function _tmp () {
|
||
|
var tmp = new BN(null);
|
||
|
tmp.words = new Array(Math.ceil(this.n / 13));
|
||
|
return tmp;
|
||
|
};
|
||
|
|
||
|
MPrime.prototype.ireduce = function ireduce (num) {
|
||
|
// Assumes that `num` is less than `P^2`
|
||
|
// num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P)
|
||
|
var r = num;
|
||
|
var rlen;
|
||
|
|
||
|
do {
|
||
|
this.split(r, this.tmp);
|
||
|
r = this.imulK(r);
|
||
|
r = r.iadd(this.tmp);
|
||
|
rlen = r.bitLength();
|
||
|
} while (rlen > this.n);
|
||
|
|
||
|
var cmp = rlen < this.n ? -1 : r.ucmp(this.p);
|
||
|
if (cmp === 0) {
|
||
|
r.words[0] = 0;
|
||
|
r.length = 1;
|
||
|
} else if (cmp > 0) {
|
||
|
r.isub(this.p);
|
||
|
} else {
|
||
|
r.strip();
|
||
|
}
|
||
|
|
||
|
return r;
|
||
|
};
|
||
|
|
||
|
MPrime.prototype.split = function split (input, out) {
|
||
|
input.iushrn(this.n, 0, out);
|
||
|
};
|
||
|
|
||
|
MPrime.prototype.imulK = function imulK (num) {
|
||
|
return num.imul(this.k);
|
||
|
};
|
||
|
|
||
|
function K256 () {
|
||
|
MPrime.call(
|
||
|
this,
|
||
|
'k256',
|
||
|
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f');
|
||
|
}
|
||
|
inherits(K256, MPrime);
|
||
|
|
||
|
K256.prototype.split = function split (input, output) {
|
||
|
// 256 = 9 * 26 + 22
|
||
|
var mask = 0x3fffff;
|
||
|
|
||
|
var outLen = Math.min(input.length, 9);
|
||
|
for (var i = 0; i < outLen; i++) {
|
||
|
output.words[i] = input.words[i];
|
||
|
}
|
||
|
output.length = outLen;
|
||
|
|
||
|
if (input.length <= 9) {
|
||
|
input.words[0] = 0;
|
||
|
input.length = 1;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Shift by 9 limbs
|
||
|
var prev = input.words[9];
|
||
|
output.words[output.length++] = prev & mask;
|
||
|
|
||
|
for (i = 10; i < input.length; i++) {
|
||
|
var next = input.words[i] | 0;
|
||
|
input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22);
|
||
|
prev = next;
|
||
|
}
|
||
|
prev >>>= 22;
|
||
|
input.words[i - 10] = prev;
|
||
|
if (prev === 0 && input.length > 10) {
|
||
|
input.length -= 10;
|
||
|
} else {
|
||
|
input.length -= 9;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
K256.prototype.imulK = function imulK (num) {
|
||
|
// K = 0x1000003d1 = [ 0x40, 0x3d1 ]
|
||
|
num.words[num.length] = 0;
|
||
|
num.words[num.length + 1] = 0;
|
||
|
num.length += 2;
|
||
|
|
||
|
// bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390
|
||
|
var lo = 0;
|
||
|
for (var i = 0; i < num.length; i++) {
|
||
|
var w = num.words[i] | 0;
|
||
|
lo += w * 0x3d1;
|
||
|
num.words[i] = lo & 0x3ffffff;
|
||
|
lo = w * 0x40 + ((lo / 0x4000000) | 0);
|
||
|
}
|
||
|
|
||
|
// Fast length reduction
|
||
|
if (num.words[num.length - 1] === 0) {
|
||
|
num.length--;
|
||
|
if (num.words[num.length - 1] === 0) {
|
||
|
num.length--;
|
||
|
}
|
||
|
}
|
||
|
return num;
|
||
|
};
|
||
|
|
||
|
function P224 () {
|
||
|
MPrime.call(
|
||
|
this,
|
||
|
'p224',
|
||
|
'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001');
|
||
|
}
|
||
|
inherits(P224, MPrime);
|
||
|
|
||
|
function P192 () {
|
||
|
MPrime.call(
|
||
|
this,
|
||
|
'p192',
|
||
|
'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff');
|
||
|
}
|
||
|
inherits(P192, MPrime);
|
||
|
|
||
|
function P25519 () {
|
||
|
// 2 ^ 255 - 19
|
||
|
MPrime.call(
|
||
|
this,
|
||
|
'25519',
|
||
|
'7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed');
|
||
|
}
|
||
|
inherits(P25519, MPrime);
|
||
|
|
||
|
P25519.prototype.imulK = function imulK (num) {
|
||
|
// K = 0x13
|
||
|
var carry = 0;
|
||
|
for (var i = 0; i < num.length; i++) {
|
||
|
var hi = (num.words[i] | 0) * 0x13 + carry;
|
||
|
var lo = hi & 0x3ffffff;
|
||
|
hi >>>= 26;
|
||
|
|
||
|
num.words[i] = lo;
|
||
|
carry = hi;
|
||
|
}
|
||
|
if (carry !== 0) {
|
||
|
num.words[num.length++] = carry;
|
||
|
}
|
||
|
return num;
|
||
|
};
|
||
|
|
||
|
// Exported mostly for testing purposes, use plain name instead
|
||
|
BN._prime = function prime (name) {
|
||
|
// Cached version of prime
|
||
|
if (primes[name]) return primes[name];
|
||
|
|
||
|
var prime;
|
||
|
if (name === 'k256') {
|
||
|
prime = new K256();
|
||
|
} else if (name === 'p224') {
|
||
|
prime = new P224();
|
||
|
} else if (name === 'p192') {
|
||
|
prime = new P192();
|
||
|
} else if (name === 'p25519') {
|
||
|
prime = new P25519();
|
||
|
} else {
|
||
|
throw new Error('Unknown prime ' + name);
|
||
|
}
|
||
|
primes[name] = prime;
|
||
|
|
||
|
return prime;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Base reduction engine
|
||
|
//
|
||
|
function Red (m) {
|
||
|
if (typeof m === 'string') {
|
||
|
var prime = BN._prime(m);
|
||
|
this.m = prime.p;
|
||
|
this.prime = prime;
|
||
|
} else {
|
||
|
assert(m.gtn(1), 'modulus must be greater than 1');
|
||
|
this.m = m;
|
||
|
this.prime = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Red.prototype._verify1 = function _verify1 (a) {
|
||
|
assert(a.negative === 0, 'red works only with positives');
|
||
|
assert(a.red, 'red works only with red numbers');
|
||
|
};
|
||
|
|
||
|
Red.prototype._verify2 = function _verify2 (a, b) {
|
||
|
assert((a.negative | b.negative) === 0, 'red works only with positives');
|
||
|
assert(a.red && a.red === b.red,
|
||
|
'red works only with red numbers');
|
||
|
};
|
||
|
|
||
|
Red.prototype.imod = function imod (a) {
|
||
|
if (this.prime) return this.prime.ireduce(a)._forceRed(this);
|
||
|
return a.umod(this.m)._forceRed(this);
|
||
|
};
|
||
|
|
||
|
Red.prototype.neg = function neg (a) {
|
||
|
if (a.isZero()) {
|
||
|
return a.clone();
|
||
|
}
|
||
|
|
||
|
return this.m.sub(a)._forceRed(this);
|
||
|
};
|
||
|
|
||
|
Red.prototype.add = function add (a, b) {
|
||
|
this._verify2(a, b);
|
||
|
|
||
|
var res = a.add(b);
|
||
|
if (res.cmp(this.m) >= 0) {
|
||
|
res.isub(this.m);
|
||
|
}
|
||
|
return res._forceRed(this);
|
||
|
};
|
||
|
|
||
|
Red.prototype.iadd = function iadd (a, b) {
|
||
|
this._verify2(a, b);
|
||
|
|
||
|
var res = a.iadd(b);
|
||
|
if (res.cmp(this.m) >= 0) {
|
||
|
res.isub(this.m);
|
||
|
}
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
Red.prototype.sub = function sub (a, b) {
|
||
|
this._verify2(a, b);
|
||
|
|
||
|
var res = a.sub(b);
|
||
|
if (res.cmpn(0) < 0) {
|
||
|
res.iadd(this.m);
|
||
|
}
|
||
|
return res._forceRed(this);
|
||
|
};
|
||
|
|
||
|
Red.prototype.isub = function isub (a, b) {
|
||
|
this._verify2(a, b);
|
||
|
|
||
|
var res = a.isub(b);
|
||
|
if (res.cmpn(0) < 0) {
|
||
|
res.iadd(this.m);
|
||
|
}
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
Red.prototype.shl = function shl (a, num) {
|
||
|
this._verify1(a);
|
||
|
return this.imod(a.ushln(num));
|
||
|
};
|
||
|
|
||
|
Red.prototype.imul = function imul (a, b) {
|
||
|
this._verify2(a, b);
|
||
|
return this.imod(a.imul(b));
|
||
|
};
|
||
|
|
||
|
Red.prototype.mul = function mul (a, b) {
|
||
|
this._verify2(a, b);
|
||
|
return this.imod(a.mul(b));
|
||
|
};
|
||
|
|
||
|
Red.prototype.isqr = function isqr (a) {
|
||
|
return this.imul(a, a.clone());
|
||
|
};
|
||
|
|
||
|
Red.prototype.sqr = function sqr (a) {
|
||
|
return this.mul(a, a);
|
||
|
};
|
||
|
|
||
|
Red.prototype.sqrt = function sqrt (a) {
|
||
|
if (a.isZero()) return a.clone();
|
||
|
|
||
|
var mod3 = this.m.andln(3);
|
||
|
assert(mod3 % 2 === 1);
|
||
|
|
||
|
// Fast case
|
||
|
if (mod3 === 3) {
|
||
|
var pow = this.m.add(new BN(1)).iushrn(2);
|
||
|
return this.pow(a, pow);
|
||
|
}
|
||
|
|
||
|
// Tonelli-Shanks algorithm (Totally unoptimized and slow)
|
||
|
//
|
||
|
// Find Q and S, that Q * 2 ^ S = (P - 1)
|
||
|
var q = this.m.subn(1);
|
||
|
var s = 0;
|
||
|
while (!q.isZero() && q.andln(1) === 0) {
|
||
|
s++;
|
||
|
q.iushrn(1);
|
||
|
}
|
||
|
assert(!q.isZero());
|
||
|
|
||
|
var one = new BN(1).toRed(this);
|
||
|
var nOne = one.redNeg();
|
||
|
|
||
|
// Find quadratic non-residue
|
||
|
// NOTE: Max is such because of generalized Riemann hypothesis.
|
||
|
var lpow = this.m.subn(1).iushrn(1);
|
||
|
var z = this.m.bitLength();
|
||
|
z = new BN(2 * z * z).toRed(this);
|
||
|
|
||
|
while (this.pow(z, lpow).cmp(nOne) !== 0) {
|
||
|
z.redIAdd(nOne);
|
||
|
}
|
||
|
|
||
|
var c = this.pow(z, q);
|
||
|
var r = this.pow(a, q.addn(1).iushrn(1));
|
||
|
var t = this.pow(a, q);
|
||
|
var m = s;
|
||
|
while (t.cmp(one) !== 0) {
|
||
|
var tmp = t;
|
||
|
for (var i = 0; tmp.cmp(one) !== 0; i++) {
|
||
|
tmp = tmp.redSqr();
|
||
|
}
|
||
|
assert(i < m);
|
||
|
var b = this.pow(c, new BN(1).iushln(m - i - 1));
|
||
|
|
||
|
r = r.redMul(b);
|
||
|
c = b.redSqr();
|
||
|
t = t.redMul(c);
|
||
|
m = i;
|
||
|
}
|
||
|
|
||
|
return r;
|
||
|
};
|
||
|
|
||
|
Red.prototype.invm = function invm (a) {
|
||
|
var inv = a._invmp(this.m);
|
||
|
if (inv.negative !== 0) {
|
||
|
inv.negative = 0;
|
||
|
return this.imod(inv).redNeg();
|
||
|
} else {
|
||
|
return this.imod(inv);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
Red.prototype.pow = function pow (a, num) {
|
||
|
if (num.isZero()) return new BN(1);
|
||
|
if (num.cmpn(1) === 0) return a.clone();
|
||
|
|
||
|
var windowSize = 4;
|
||
|
var wnd = new Array(1 << windowSize);
|
||
|
wnd[0] = new BN(1).toRed(this);
|
||
|
wnd[1] = a;
|
||
|
for (var i = 2; i < wnd.length; i++) {
|
||
|
wnd[i] = this.mul(wnd[i - 1], a);
|
||
|
}
|
||
|
|
||
|
var res = wnd[0];
|
||
|
var current = 0;
|
||
|
var currentLen = 0;
|
||
|
var start = num.bitLength() % 26;
|
||
|
if (start === 0) {
|
||
|
start = 26;
|
||
|
}
|
||
|
|
||
|
for (i = num.length - 1; i >= 0; i--) {
|
||
|
var word = num.words[i];
|
||
|
for (var j = start - 1; j >= 0; j--) {
|
||
|
var bit = (word >> j) & 1;
|
||
|
if (res !== wnd[0]) {
|
||
|
res = this.sqr(res);
|
||
|
}
|
||
|
|
||
|
if (bit === 0 && current === 0) {
|
||
|
currentLen = 0;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
current <<= 1;
|
||
|
current |= bit;
|
||
|
currentLen++;
|
||
|
if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue;
|
||
|
|
||
|
res = this.mul(res, wnd[current]);
|
||
|
currentLen = 0;
|
||
|
current = 0;
|
||
|
}
|
||
|
start = 26;
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
Red.prototype.convertTo = function convertTo (num) {
|
||
|
var r = num.umod(this.m);
|
||
|
|
||
|
return r === num ? r.clone() : r;
|
||
|
};
|
||
|
|
||
|
Red.prototype.convertFrom = function convertFrom (num) {
|
||
|
var res = num.clone();
|
||
|
res.red = null;
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Montgomery method engine
|
||
|
//
|
||
|
|
||
|
BN.mont = function mont (num) {
|
||
|
return new Mont(num);
|
||
|
};
|
||
|
|
||
|
function Mont (m) {
|
||
|
Red.call(this, m);
|
||
|
|
||
|
this.shift = this.m.bitLength();
|
||
|
if (this.shift % 26 !== 0) {
|
||
|
this.shift += 26 - (this.shift % 26);
|
||
|
}
|
||
|
|
||
|
this.r = new BN(1).iushln(this.shift);
|
||
|
this.r2 = this.imod(this.r.sqr());
|
||
|
this.rinv = this.r._invmp(this.m);
|
||
|
|
||
|
this.minv = this.rinv.mul(this.r).isubn(1).div(this.m);
|
||
|
this.minv = this.minv.umod(this.r);
|
||
|
this.minv = this.r.sub(this.minv);
|
||
|
}
|
||
|
inherits(Mont, Red);
|
||
|
|
||
|
Mont.prototype.convertTo = function convertTo (num) {
|
||
|
return this.imod(num.ushln(this.shift));
|
||
|
};
|
||
|
|
||
|
Mont.prototype.convertFrom = function convertFrom (num) {
|
||
|
var r = this.imod(num.mul(this.rinv));
|
||
|
r.red = null;
|
||
|
return r;
|
||
|
};
|
||
|
|
||
|
Mont.prototype.imul = function imul (a, b) {
|
||
|
if (a.isZero() || b.isZero()) {
|
||
|
a.words[0] = 0;
|
||
|
a.length = 1;
|
||
|
return a;
|
||
|
}
|
||
|
|
||
|
var t = a.imul(b);
|
||
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
||
|
var u = t.isub(c).iushrn(this.shift);
|
||
|
var res = u;
|
||
|
|
||
|
if (u.cmp(this.m) >= 0) {
|
||
|
res = u.isub(this.m);
|
||
|
} else if (u.cmpn(0) < 0) {
|
||
|
res = u.iadd(this.m);
|
||
|
}
|
||
|
|
||
|
return res._forceRed(this);
|
||
|
};
|
||
|
|
||
|
Mont.prototype.mul = function mul (a, b) {
|
||
|
if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this);
|
||
|
|
||
|
var t = a.mul(b);
|
||
|
var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m);
|
||
|
var u = t.isub(c).iushrn(this.shift);
|
||
|
var res = u;
|
||
|
if (u.cmp(this.m) >= 0) {
|
||
|
res = u.isub(this.m);
|
||
|
} else if (u.cmpn(0) < 0) {
|
||
|
res = u.iadd(this.m);
|
||
|
}
|
||
|
|
||
|
return res._forceRed(this);
|
||
|
};
|
||
|
|
||
|
Mont.prototype.invm = function invm (a) {
|
||
|
// (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R
|
||
|
var res = this.imod(a._invmp(this.m).mul(this.r2));
|
||
|
return res._forceRed(this);
|
||
|
};
|
||
|
})(typeof module === 'undefined' || module, this);
|
||
|
|
||
|
},{}],4:[function(require,module,exports){
|
||
|
var r;
|
||
|
|
||
|
module.exports = function rand(len) {
|
||
|
if (!r)
|
||
|
r = new Rand(null);
|
||
|
|
||
|
return r.generate(len);
|
||
|
};
|
||
|
|
||
|
function Rand(rand) {
|
||
|
this.rand = rand;
|
||
|
}
|
||
|
module.exports.Rand = Rand;
|
||
|
|
||
|
Rand.prototype.generate = function generate(len) {
|
||
|
return this._rand(len);
|
||
|
};
|
||
|
|
||
|
// Emulate crypto API using randy
|
||
|
Rand.prototype._rand = function _rand(n) {
|
||
|
if (this.rand.getBytes)
|
||
|
return this.rand.getBytes(n);
|
||
|
|
||
|
var res = new Uint8Array(n);
|
||
|
for (var i = 0; i < res.length; i++)
|
||
|
res[i] = this.rand.getByte();
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
if (typeof self === 'object') {
|
||
|
if (self.crypto && self.crypto.getRandomValues) {
|
||
|
// Modern browsers
|
||
|
Rand.prototype._rand = function _rand(n) {
|
||
|
var arr = new Uint8Array(n);
|
||
|
self.crypto.getRandomValues(arr);
|
||
|
return arr;
|
||
|
};
|
||
|
} else if (self.msCrypto && self.msCrypto.getRandomValues) {
|
||
|
// IE
|
||
|
Rand.prototype._rand = function _rand(n) {
|
||
|
var arr = new Uint8Array(n);
|
||
|
self.msCrypto.getRandomValues(arr);
|
||
|
return arr;
|
||
|
};
|
||
|
|
||
|
// Safari's WebWorkers do not have `crypto`
|
||
|
} else if (typeof window === 'object') {
|
||
|
// Old junk
|
||
|
Rand.prototype._rand = function() {
|
||
|
throw new Error('Not implemented yet');
|
||
|
};
|
||
|
}
|
||
|
} else {
|
||
|
// Node.js or Web worker with no crypto support
|
||
|
try {
|
||
|
var crypto = require('crypto');
|
||
|
if (typeof crypto.randomBytes !== 'function')
|
||
|
throw new Error('Not supported');
|
||
|
|
||
|
Rand.prototype._rand = function _rand(n) {
|
||
|
return crypto.randomBytes(n);
|
||
|
};
|
||
|
} catch (e) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
},{"crypto":5}],5:[function(require,module,exports){
|
||
|
|
||
|
},{}],6:[function(require,module,exports){
|
||
|
'use strict';
|
||
|
|
||
|
var elliptic = exports;
|
||
|
|
||
|
elliptic.version = require('../package.json').version;
|
||
|
elliptic.utils = require('./elliptic/utils');
|
||
|
elliptic.rand = require('brorand');
|
||
|
elliptic.curve = require('./elliptic/curve');
|
||
|
elliptic.curves = require('./elliptic/curves');
|
||
|
|
||
|
// Protocols
|
||
|
elliptic.ec = require('./elliptic/ec');
|
||
|
elliptic.eddsa = require('./elliptic/eddsa');
|
||
|
|
||
|
},{"../package.json":19,"./elliptic/curve":9,"./elliptic/curves":12,"./elliptic/ec":13,"./elliptic/eddsa":16,"./elliptic/utils":18,"brorand":4}],7:[function(require,module,exports){
|
||
|
'use strict';
|
||
|
|
||
|
var BN = require('bn.js');
|
||
|
var elliptic = require('../../elliptic');
|
||
|
var utils = elliptic.utils;
|
||
|
var getNAF = utils.getNAF;
|
||
|
var getJSF = utils.getJSF;
|
||
|
var assert = utils.assert;
|
||
|
|
||
|
function BaseCurve(type, conf) {
|
||
|
this.type = type;
|
||
|
this.p = new BN(conf.p, 16);
|
||
|
|
||
|
// Use Montgomery, when there is no fast reduction for the prime
|
||
|
this.red = conf.prime ? BN.red(conf.prime) : BN.mont(this.p);
|
||
|
|
||
|
// Useful for many curves
|
||
|
this.zero = new BN(0).toRed(this.red);
|
||
|
this.one = new BN(1).toRed(this.red);
|
||
|
this.two = new BN(2).toRed(this.red);
|
||
|
|
||
|
// Curve configuration, optional
|
||
|
this.n = conf.n && new BN(conf.n, 16);
|
||
|
this.g = conf.g && this.pointFromJSON(conf.g, conf.gRed);
|
||
|
|
||
|
// Temporary arrays
|
||
|
this._wnafT1 = new Array(4);
|
||
|
this._wnafT2 = new Array(4);
|
||
|
this._wnafT3 = new Array(4);
|
||
|
this._wnafT4 = new Array(4);
|
||
|
|
||
|
// Generalized Greg Maxwell's trick
|
||
|
var adjustCount = this.n && this.p.div(this.n);
|
||
|
if (!adjustCount || adjustCount.cmpn(100) > 0) {
|
||
|
this.redN = null;
|
||
|
} else {
|
||
|
this._maxwellTrick = true;
|
||
|
this.redN = this.n.toRed(this.red);
|
||
|
}
|
||
|
}
|
||
|
module.exports = BaseCurve;
|
||
|
|
||
|
BaseCurve.prototype.point = function point() {
|
||
|
throw new Error('Not implemented');
|
||
|
};
|
||
|
|
||
|
BaseCurve.prototype.validate = function validate() {
|
||
|
throw new Error('Not implemented');
|
||
|
};
|
||
|
|
||
|
BaseCurve.prototype._fixedNafMul = function _fixedNafMul(p, k) {
|
||
|
assert(p.precomputed);
|
||
|
var doubles = p._getDoubles();
|
||
|
|
||
|
var naf = getNAF(k, 1);
|
||
|
var I = (1 << (doubles.step + 1)) - (doubles.step % 2 === 0 ? 2 : 1);
|
||
|
I /= 3;
|
||
|
|
||
|
// Translate into more windowed form
|
||
|
var repr = [];
|
||
|
for (var j = 0; j < naf.length; j += doubles.step) {
|
||
|
var nafW = 0;
|
||
|
for (var k = j + doubles.step - 1; k >= j; k--)
|
||
|
nafW = (nafW << 1) + naf[k];
|
||
|
repr.push(nafW);
|
||
|
}
|
||
|
|
||
|
var a = this.jpoint(null, null, null);
|
||
|
var b = this.jpoint(null, null, null);
|
||
|
for (var i = I; i > 0; i--) {
|
||
|
for (var j = 0; j < repr.length; j++) {
|
||
|
var nafW = repr[j];
|
||
|
if (nafW === i)
|
||
|
b = b.mixedAdd(doubles.points[j]);
|
||
|
else if (nafW === -i)
|
||
|
b = b.mixedAdd(doubles.points[j].neg());
|
||
|
}
|
||
|
a = a.add(b);
|
||
|
}
|
||
|
return a.toP();
|
||
|
};
|
||
|
|
||
|
BaseCurve.prototype._wnafMul = function _wnafMul(p, k) {
|
||
|
var w = 4;
|
||
|
|
||
|
// Precompute window
|
||
|
var nafPoints = p._getNAFPoints(w);
|
||
|
w = nafPoints.wnd;
|
||
|
var wnd = nafPoints.points;
|
||
|
|
||
|
// Get NAF form
|
||
|
var naf = getNAF(k, w);
|
||
|
|
||
|
// Add `this`*(N+1) for every w-NAF index
|
||
|
var acc = this.jpoint(null, null, null);
|
||
|
for (var i = naf.length - 1; i >= 0; i--) {
|
||
|
// Count zeroes
|
||
|
for (var k = 0; i >= 0 && naf[i] === 0; i--)
|
||
|
k++;
|
||
|
if (i >= 0)
|
||
|
k++;
|
||
|
acc = acc.dblp(k);
|
||
|
|
||
|
if (i < 0)
|
||
|
break;
|
||
|
var z = naf[i];
|
||
|
assert(z !== 0);
|
||
|
if (p.type === 'affine') {
|
||
|
// J +- P
|
||
|
if (z > 0)
|
||
|
acc = acc.mixedAdd(wnd[(z - 1) >> 1]);
|
||
|
else
|
||
|
acc = acc.mixedAdd(wnd[(-z - 1) >> 1].neg());
|
||
|
} else {
|
||
|
// J +- J
|
||
|
if (z > 0)
|
||
|
acc = acc.add(wnd[(z - 1) >> 1]);
|
||
|
else
|
||
|
acc = acc.add(wnd[(-z - 1) >> 1].neg());
|
||
|
}
|
||
|
}
|
||
|
return p.type === 'affine' ? acc.toP() : acc;
|
||
|
};
|
||
|
|
||
|
BaseCurve.prototype._wnafMulAdd = function _wnafMulAdd(defW,
|
||
|
points,
|
||
|
coeffs,
|
||
|
len,
|
||
|
jacobianResult) {
|
||
|
var wndWidth = this._wnafT1;
|
||
|
var wnd = this._wnafT2;
|
||
|
var naf = this._wnafT3;
|
||
|
|
||
|
// Fill all arrays
|
||
|
var max = 0;
|
||
|
for (var i = 0; i < len; i++) {
|
||
|
var p = points[i];
|
||
|
var nafPoints = p._getNAFPoints(defW);
|
||
|
wndWidth[i] = nafPoints.wnd;
|
||
|
wnd[i] = nafPoints.points;
|
||
|
}
|
||
|
|
||
|
// Comb small window NAFs
|
||
|
for (var i = len - 1; i >= 1; i -= 2) {
|
||
|
var a = i - 1;
|
||
|
var b = i;
|
||
|
if (wndWidth[a] !== 1 || wndWidth[b] !== 1) {
|
||
|
naf[a] = getNAF(coeffs[a], wndWidth[a]);
|
||
|
naf[b] = getNAF(coeffs[b], wndWidth[b]);
|
||
|
max = Math.max(naf[a].length, max);
|
||
|
max = Math.max(naf[b].length, max);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
var comb = [
|
||
|
points[a], /* 1 */
|
||
|
null, /* 3 */
|
||
|
null, /* 5 */
|
||
|
points[b] /* 7 */
|
||
|
];
|
||
|
|
||
|
// Try to avoid Projective points, if possible
|
||
|
if (points[a].y.cmp(points[b].y) === 0) {
|
||
|
comb[1] = points[a].add(points[b]);
|
||
|
comb[2] = points[a].toJ().mixedAdd(points[b].neg());
|
||
|
} else if (points[a].y.cmp(points[b].y.redNeg()) === 0) {
|
||
|
comb[1] = points[a].toJ().mixedAdd(points[b]);
|
||
|
comb[2] = points[a].add(points[b].neg());
|
||
|
} else {
|
||
|
comb[1] = points[a].toJ().mixedAdd(points[b]);
|
||
|
comb[2] = points[a].toJ().mixedAdd(points[b].neg());
|
||
|
}
|
||
|
|
||
|
var index = [
|
||
|
-3, /* -1 -1 */
|
||
|
-1, /* -1 0 */
|
||
|
-5, /* -1 1 */
|
||
|
-7, /* 0 -1 */
|
||
|
0, /* 0 0 */
|
||
|
7, /* 0 1 */
|
||
|
5, /* 1 -1 */
|
||
|
1, /* 1 0 */
|
||
|
3 /* 1 1 */
|
||
|
];
|
||
|
|
||
|
var jsf = getJSF(coeffs[a], coeffs[b]);
|
||
|
max = Math.max(jsf[0].length, max);
|
||
|
naf[a] = new Array(max);
|
||
|
naf[b] = new Array(max);
|
||
|
for (var j = 0; j < max; j++) {
|
||
|
var ja = jsf[0][j] | 0;
|
||
|
var jb = jsf[1][j] | 0;
|
||
|
|
||
|
naf[a][j] = index[(ja + 1) * 3 + (jb + 1)];
|
||
|
naf[b][j] = 0;
|
||
|
wnd[a] = comb;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var acc = this.jpoint(null, null, null);
|
||
|
var tmp = this._wnafT4;
|
||
|
for (var i = max; i >= 0; i--) {
|
||
|
var k = 0;
|
||
|
|
||
|
while (i >= 0) {
|
||
|
var zero = true;
|
||
|
for (var j = 0; j < len; j++) {
|
||
|
tmp[j] = naf[j][i] | 0;
|
||
|
if (tmp[j] !== 0)
|
||
|
zero = false;
|
||
|
}
|
||
|
if (!zero)
|
||
|
break;
|
||
|
k++;
|
||
|
i--;
|
||
|
}
|
||
|
if (i >= 0)
|
||
|
k++;
|
||
|
acc = acc.dblp(k);
|
||
|
if (i < 0)
|
||
|
break;
|
||
|
|
||
|
for (var j = 0; j < len; j++) {
|
||
|
var z = tmp[j];
|
||
|
var p;
|
||
|
if (z === 0)
|
||
|
continue;
|
||
|
else if (z > 0)
|
||
|
p = wnd[j][(z - 1) >> 1];
|
||
|
else if (z < 0)
|
||
|
p = wnd[j][(-z - 1) >> 1].neg();
|
||
|
|
||
|
if (p.type === 'affine')
|
||
|
acc = acc.mixedAdd(p);
|
||
|
else
|
||
|
acc = acc.add(p);
|
||
|
}
|
||
|
}
|
||
|
// Zeroify references
|
||
|
for (var i = 0; i < len; i++)
|
||
|
wnd[i] = null;
|
||
|
|
||
|
if (jacobianResult)
|
||
|
return acc;
|
||
|
else
|
||
|
return acc.toP();
|
||
|
};
|
||
|
|
||
|
function BasePoint(curve, type) {
|
||
|
this.curve = curve;
|
||
|
this.type = type;
|
||
|
this.precomputed = null;
|
||
|
}
|
||
|
BaseCurve.BasePoint = BasePoint;
|
||
|
|
||
|
BasePoint.prototype.eq = function eq(/*other*/) {
|
||
|
throw new Error('Not implemented');
|
||
|
};
|
||
|
|
||
|
BasePoint.prototype.validate = function validate() {
|
||
|
return this.curve.validate(this);
|
||
|
};
|
||
|
|
||
|
BaseCurve.prototype.decodePoint = function decodePoint(bytes, enc) {
|
||
|
bytes = utils.toArray(bytes, enc);
|
||
|
|
||
|
var len = this.p.byteLength();
|
||
|
|
||
|
// uncompressed, hybrid-odd, hybrid-even
|
||
|
if ((bytes[0] === 0x04 || bytes[0] === 0x06 || bytes[0] === 0x07) &&
|
||
|
bytes.length - 1 === 2 * len) {
|
||
|
if (bytes[0] === 0x06)
|
||
|
assert(bytes[bytes.length - 1] % 2 === 0);
|
||
|
else if (bytes[0] === 0x07)
|
||
|
assert(bytes[bytes.length - 1] % 2 === 1);
|
||
|
|
||
|
var res = this.point(bytes.slice(1, 1 + len),
|
||
|
bytes.slice(1 + len, 1 + 2 * len));
|
||
|
|
||
|
return res;
|
||
|
} else if ((bytes[0] === 0x02 || bytes[0] === 0x03) &&
|
||
|
bytes.length - 1 === len) {
|
||
|
return this.pointFromX(bytes.slice(1, 1 + len), bytes[0] === 0x03);
|
||
|
}
|
||
|
throw new Error('Unknown point format');
|
||
|
};
|
||
|
|
||
|
BasePoint.prototype.encodeCompressed = function encodeCompressed(enc) {
|
||
|
return this.encode(enc, true);
|
||
|
};
|
||
|
|
||
|
BasePoint.prototype._encode = function _encode(compact) {
|
||
|
var len = this.curve.p.byteLength();
|
||
|
var x = this.getX().toArray('be', len);
|
||
|
|
||
|
if (compact)
|
||
|
return [ this.getY().isEven() ? 0x02 : 0x03 ].concat(x);
|
||
|
|
||
|
return [ 0x04 ].concat(x, this.getY().toArray('be', len)) ;
|
||
|
};
|
||
|
|
||
|
BasePoint.prototype.encode = function encode(enc, compact) {
|
||
|
return utils.encode(this._encode(compact), enc);
|
||
|
};
|
||
|
|
||
|
BasePoint.prototype.precompute = function precompute(power) {
|
||
|
if (this.precomputed)
|
||
|
return this;
|
||
|
|
||
|
var precomputed = {
|
||
|
doubles: null,
|
||
|
naf: null,
|
||
|
beta: null
|
||
|
};
|
||
|
precomputed.naf = this._getNAFPoints(8);
|
||
|
precomputed.doubles = this._getDoubles(4, power);
|
||
|
precomputed.beta = this._getBeta();
|
||
|
this.precomputed = precomputed;
|
||
|
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
BasePoint.prototype._hasDoubles = function _hasDoubles(k) {
|
||
|
if (!this.precomputed)
|
||
|
return false;
|
||
|
|
||
|
var doubles = this.precomputed.doubles;
|
||
|
if (!doubles)
|
||
|
return false;
|
||
|
|
||
|
return doubles.points.length >= Math.ceil((k.bitLength() + 1) / doubles.step);
|
||
|
};
|
||
|
|
||
|
BasePoint.prototype._getDoubles = function _getDoubles(step, power) {
|
||
|
if (this.precomputed && this.precomputed.doubles)
|
||
|
return this.precomputed.doubles;
|
||
|
|
||
|
var doubles = [ this ];
|
||
|
var acc = this;
|
||
|
for (var i = 0; i < power; i += step) {
|
||
|
for (var j = 0; j < step; j++)
|
||
|
acc = acc.dbl();
|
||
|
doubles.push(acc);
|
||
|
}
|
||
|
return {
|
||
|
step: step,
|
||
|
points: doubles
|
||
|
};
|
||
|
};
|
||
|
|
||
|
BasePoint.prototype._getNAFPoints = function _getNAFPoints(wnd) {
|
||
|
if (this.precomputed && this.precomputed.naf)
|
||
|
return this.precomputed.naf;
|
||
|
|
||
|
var res = [ this ];
|
||
|
var max = (1 << wnd) - 1;
|
||
|
var dbl = max === 1 ? null : this.dbl();
|
||
|
for (var i = 1; i < max; i++)
|
||
|
res[i] = res[i - 1].add(dbl);
|
||
|
return {
|
||
|
wnd: wnd,
|
||
|
points: res
|
||
|
};
|
||
|
};
|
||
|
|
||
|
BasePoint.prototype._getBeta = function _getBeta() {
|
||
|
return null;
|
||
|
};
|
||
|
|
||
|
BasePoint.prototype.dblp = function dblp(k) {
|
||
|
var r = this;
|
||
|
for (var i = 0; i < k; i++)
|
||
|
r = r.dbl();
|
||
|
return r;
|
||
|
};
|
||
|
|
||
|
},{"../../elliptic":6,"bn.js":3}],8:[function(require,module,exports){
|
||
|
module.exports = {};
|
||
|
},{}],9:[function(require,module,exports){
|
||
|
'use strict';
|
||
|
|
||
|
var curve = exports;
|
||
|
|
||
|
curve.base = require('./base');
|
||
|
curve.short = require('./short');
|
||
|
curve.mont = require('./mont');
|
||
|
curve.edwards = require('./edwards');
|
||
|
|
||
|
},{"./base":7,"./edwards":8,"./mont":10,"./short":11}],10:[function(require,module,exports){
|
||
|
arguments[4][8][0].apply(exports,arguments)
|
||
|
},{"dup":8}],11:[function(require,module,exports){
|
||
|
'use strict';
|
||
|
|
||
|
var curve = require('../curve');
|
||
|
var elliptic = require('../../elliptic');
|
||
|
var BN = require('bn.js');
|
||
|
var inherits = require('inherits');
|
||
|
var Base = curve.base;
|
||
|
|
||
|
var assert = elliptic.utils.assert;
|
||
|
|
||
|
function ShortCurve(conf) {
|
||
|
Base.call(this, 'short', conf);
|
||
|
|
||
|
this.a = new BN(conf.a, 16).toRed(this.red);
|
||
|
this.b = new BN(conf.b, 16).toRed(this.red);
|
||
|
this.tinv = this.two.redInvm();
|
||
|
|
||
|
this.zeroA = this.a.fromRed().cmpn(0) === 0;
|
||
|
this.threeA = this.a.fromRed().sub(this.p).cmpn(-3) === 0;
|
||
|
|
||
|
// If the curve is endomorphic, precalculate beta and lambda
|
||
|
this.endo = this._getEndomorphism(conf);
|
||
|
this._endoWnafT1 = new Array(4);
|
||
|
this._endoWnafT2 = new Array(4);
|
||
|
}
|
||
|
inherits(ShortCurve, Base);
|
||
|
module.exports = ShortCurve;
|
||
|
|
||
|
ShortCurve.prototype._getEndomorphism = function _getEndomorphism(conf) {
|
||
|
// No efficient endomorphism
|
||
|
if (!this.zeroA || !this.g || !this.n || this.p.modn(3) !== 1)
|
||
|
return;
|
||
|
|
||
|
// Compute beta and lambda, that lambda * P = (beta * Px; Py)
|
||
|
var beta;
|
||
|
var lambda;
|
||
|
if (conf.beta) {
|
||
|
beta = new BN(conf.beta, 16).toRed(this.red);
|
||
|
} else {
|
||
|
var betas = this._getEndoRoots(this.p);
|
||
|
// Choose the smallest beta
|
||
|
beta = betas[0].cmp(betas[1]) < 0 ? betas[0] : betas[1];
|
||
|
beta = beta.toRed(this.red);
|
||
|
}
|
||
|
if (conf.lambda) {
|
||
|
lambda = new BN(conf.lambda, 16);
|
||
|
} else {
|
||
|
// Choose the lambda that is matching selected beta
|
||
|
var lambdas = this._getEndoRoots(this.n);
|
||
|
if (this.g.mul(lambdas[0]).x.cmp(this.g.x.redMul(beta)) === 0) {
|
||
|
lambda = lambdas[0];
|
||
|
} else {
|
||
|
lambda = lambdas[1];
|
||
|
assert(this.g.mul(lambda).x.cmp(this.g.x.redMul(beta)) === 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Get basis vectors, used for balanced length-two representation
|
||
|
var basis;
|
||
|
if (conf.basis) {
|
||
|
basis = conf.basis.map(function(vec) {
|
||
|
return {
|
||
|
a: new BN(vec.a, 16),
|
||
|
b: new BN(vec.b, 16)
|
||
|
};
|
||
|
});
|
||
|
} else {
|
||
|
basis = this._getEndoBasis(lambda);
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
beta: beta,
|
||
|
lambda: lambda,
|
||
|
basis: basis
|
||
|
};
|
||
|
};
|
||
|
|
||
|
ShortCurve.prototype._getEndoRoots = function _getEndoRoots(num) {
|
||
|
// Find roots of for x^2 + x + 1 in F
|
||
|
// Root = (-1 +- Sqrt(-3)) / 2
|
||
|
//
|
||
|
var red = num === this.p ? this.red : BN.mont(num);
|
||
|
var tinv = new BN(2).toRed(red).redInvm();
|
||
|
var ntinv = tinv.redNeg();
|
||
|
|
||
|
var s = new BN(3).toRed(red).redNeg().redSqrt().redMul(tinv);
|
||
|
|
||
|
var l1 = ntinv.redAdd(s).fromRed();
|
||
|
var l2 = ntinv.redSub(s).fromRed();
|
||
|
return [ l1, l2 ];
|
||
|
};
|
||
|
|
||
|
ShortCurve.prototype._getEndoBasis = function _getEndoBasis(lambda) {
|
||
|
// aprxSqrt >= sqrt(this.n)
|
||
|
var aprxSqrt = this.n.ushrn(Math.floor(this.n.bitLength() / 2));
|
||
|
|
||
|
// 3.74
|
||
|
// Run EGCD, until r(L + 1) < aprxSqrt
|
||
|
var u = lambda;
|
||
|
var v = this.n.clone();
|
||
|
var x1 = new BN(1);
|
||
|
var y1 = new BN(0);
|
||
|
var x2 = new BN(0);
|
||
|
var y2 = new BN(1);
|
||
|
|
||
|
// NOTE: all vectors are roots of: a + b * lambda = 0 (mod n)
|
||
|
var a0;
|
||
|
var b0;
|
||
|
// First vector
|
||
|
var a1;
|
||
|
var b1;
|
||
|
// Second vector
|
||
|
var a2;
|
||
|
var b2;
|
||
|
|
||
|
var prevR;
|
||
|
var i = 0;
|
||
|
var r;
|
||
|
var x;
|
||
|
while (u.cmpn(0) !== 0) {
|
||
|
var q = v.div(u);
|
||
|
r = v.sub(q.mul(u));
|
||
|
x = x2.sub(q.mul(x1));
|
||
|
var y = y2.sub(q.mul(y1));
|
||
|
|
||
|
if (!a1 && r.cmp(aprxSqrt) < 0) {
|
||
|
a0 = prevR.neg();
|
||
|
b0 = x1;
|
||
|
a1 = r.neg();
|
||
|
b1 = x;
|
||
|
} else if (a1 && ++i === 2) {
|
||
|
break;
|
||
|
}
|
||
|
prevR = r;
|
||
|
|
||
|
v = u;
|
||
|
u = r;
|
||
|
x2 = x1;
|
||
|
x1 = x;
|
||
|
y2 = y1;
|
||
|
y1 = y;
|
||
|
}
|
||
|
a2 = r.neg();
|
||
|
b2 = x;
|
||
|
|
||
|
var len1 = a1.sqr().add(b1.sqr());
|
||
|
var len2 = a2.sqr().add(b2.sqr());
|
||
|
if (len2.cmp(len1) >= 0) {
|
||
|
a2 = a0;
|
||
|
b2 = b0;
|
||
|
}
|
||
|
|
||
|
// Normalize signs
|
||
|
if (a1.negative) {
|
||
|
a1 = a1.neg();
|
||
|
b1 = b1.neg();
|
||
|
}
|
||
|
if (a2.negative) {
|
||
|
a2 = a2.neg();
|
||
|
b2 = b2.neg();
|
||
|
}
|
||
|
|
||
|
return [
|
||
|
{ a: a1, b: b1 },
|
||
|
{ a: a2, b: b2 }
|
||
|
];
|
||
|
};
|
||
|
|
||
|
ShortCurve.prototype._endoSplit = function _endoSplit(k) {
|
||
|
var basis = this.endo.basis;
|
||
|
var v1 = basis[0];
|
||
|
var v2 = basis[1];
|
||
|
|
||
|
var c1 = v2.b.mul(k).divRound(this.n);
|
||
|
var c2 = v1.b.neg().mul(k).divRound(this.n);
|
||
|
|
||
|
var p1 = c1.mul(v1.a);
|
||
|
var p2 = c2.mul(v2.a);
|
||
|
var q1 = c1.mul(v1.b);
|
||
|
var q2 = c2.mul(v2.b);
|
||
|
|
||
|
// Calculate answer
|
||
|
var k1 = k.sub(p1).sub(p2);
|
||
|
var k2 = q1.add(q2).neg();
|
||
|
return { k1: k1, k2: k2 };
|
||
|
};
|
||
|
|
||
|
ShortCurve.prototype.pointFromX = function pointFromX(x, odd) {
|
||
|
x = new BN(x, 16);
|
||
|
if (!x.red)
|
||
|
x = x.toRed(this.red);
|
||
|
|
||
|
var y2 = x.redSqr().redMul(x).redIAdd(x.redMul(this.a)).redIAdd(this.b);
|
||
|
var y = y2.redSqrt();
|
||
|
if (y.redSqr().redSub(y2).cmp(this.zero) !== 0)
|
||
|
throw new Error('invalid point');
|
||
|
|
||
|
// XXX Is there any way to tell if the number is odd without converting it
|
||
|
// to non-red form?
|
||
|
var isOdd = y.fromRed().isOdd();
|
||
|
if (odd && !isOdd || !odd && isOdd)
|
||
|
y = y.redNeg();
|
||
|
|
||
|
return this.point(x, y);
|
||
|
};
|
||
|
|
||
|
ShortCurve.prototype.validate = function validate(point) {
|
||
|
if (point.inf)
|
||
|
return true;
|
||
|
|
||
|
var x = point.x;
|
||
|
var y = point.y;
|
||
|
|
||
|
var ax = this.a.redMul(x);
|
||
|
var rhs = x.redSqr().redMul(x).redIAdd(ax).redIAdd(this.b);
|
||
|
return y.redSqr().redISub(rhs).cmpn(0) === 0;
|
||
|
};
|
||
|
|
||
|
ShortCurve.prototype._endoWnafMulAdd =
|
||
|
function _endoWnafMulAdd(points, coeffs, jacobianResult) {
|
||
|
var npoints = this._endoWnafT1;
|
||
|
var ncoeffs = this._endoWnafT2;
|
||
|
for (var i = 0; i < points.length; i++) {
|
||
|
var split = this._endoSplit(coeffs[i]);
|
||
|
var p = points[i];
|
||
|
var beta = p._getBeta();
|
||
|
|
||
|
if (split.k1.negative) {
|
||
|
split.k1.ineg();
|
||
|
p = p.neg(true);
|
||
|
}
|
||
|
if (split.k2.negative) {
|
||
|
split.k2.ineg();
|
||
|
beta = beta.neg(true);
|
||
|
}
|
||
|
|
||
|
npoints[i * 2] = p;
|
||
|
npoints[i * 2 + 1] = beta;
|
||
|
ncoeffs[i * 2] = split.k1;
|
||
|
ncoeffs[i * 2 + 1] = split.k2;
|
||
|
}
|
||
|
var res = this._wnafMulAdd(1, npoints, ncoeffs, i * 2, jacobianResult);
|
||
|
|
||
|
// Clean-up references to points and coefficients
|
||
|
for (var j = 0; j < i * 2; j++) {
|
||
|
npoints[j] = null;
|
||
|
ncoeffs[j] = null;
|
||
|
}
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
function Point(curve, x, y, isRed) {
|
||
|
Base.BasePoint.call(this, curve, 'affine');
|
||
|
if (x === null && y === null) {
|
||
|
this.x = null;
|
||
|
this.y = null;
|
||
|
this.inf = true;
|
||
|
} else {
|
||
|
this.x = new BN(x, 16);
|
||
|
this.y = new BN(y, 16);
|
||
|
// Force redgomery representation when loading from JSON
|
||
|
if (isRed) {
|
||
|
this.x.forceRed(this.curve.red);
|
||
|
this.y.forceRed(this.curve.red);
|
||
|
}
|
||
|
if (!this.x.red)
|
||
|
this.x = this.x.toRed(this.curve.red);
|
||
|
if (!this.y.red)
|
||
|
this.y = this.y.toRed(this.curve.red);
|
||
|
this.inf = false;
|
||
|
}
|
||
|
}
|
||
|
inherits(Point, Base.BasePoint);
|
||
|
|
||
|
ShortCurve.prototype.point = function point(x, y, isRed) {
|
||
|
return new Point(this, x, y, isRed);
|
||
|
};
|
||
|
|
||
|
ShortCurve.prototype.pointFromJSON = function pointFromJSON(obj, red) {
|
||
|
return Point.fromJSON(this, obj, red);
|
||
|
};
|
||
|
|
||
|
Point.prototype._getBeta = function _getBeta() {
|
||
|
if (!this.curve.endo)
|
||
|
return;
|
||
|
|
||
|
var pre = this.precomputed;
|
||
|
if (pre && pre.beta)
|
||
|
return pre.beta;
|
||
|
|
||
|
var beta = this.curve.point(this.x.redMul(this.curve.endo.beta), this.y);
|
||
|
if (pre) {
|
||
|
var curve = this.curve;
|
||
|
var endoMul = function(p) {
|
||
|
return curve.point(p.x.redMul(curve.endo.beta), p.y);
|
||
|
};
|
||
|
pre.beta = beta;
|
||
|
beta.precomputed = {
|
||
|
beta: null,
|
||
|
naf: pre.naf && {
|
||
|
wnd: pre.naf.wnd,
|
||
|
points: pre.naf.points.map(endoMul)
|
||
|
},
|
||
|
doubles: pre.doubles && {
|
||
|
step: pre.doubles.step,
|
||
|
points: pre.doubles.points.map(endoMul)
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
return beta;
|
||
|
};
|
||
|
|
||
|
Point.prototype.toJSON = function toJSON() {
|
||
|
if (!this.precomputed)
|
||
|
return [ this.x, this.y ];
|
||
|
|
||
|
return [ this.x, this.y, this.precomputed && {
|
||
|
doubles: this.precomputed.doubles && {
|
||
|
step: this.precomputed.doubles.step,
|
||
|
points: this.precomputed.doubles.points.slice(1)
|
||
|
},
|
||
|
naf: this.precomputed.naf && {
|
||
|
wnd: this.precomputed.naf.wnd,
|
||
|
points: this.precomputed.naf.points.slice(1)
|
||
|
}
|
||
|
} ];
|
||
|
};
|
||
|
|
||
|
Point.fromJSON = function fromJSON(curve, obj, red) {
|
||
|
if (typeof obj === 'string')
|
||
|
obj = JSON.parse(obj);
|
||
|
var res = curve.point(obj[0], obj[1], red);
|
||
|
if (!obj[2])
|
||
|
return res;
|
||
|
|
||
|
function obj2point(obj) {
|
||
|
return curve.point(obj[0], obj[1], red);
|
||
|
}
|
||
|
|
||
|
var pre = obj[2];
|
||
|
res.precomputed = {
|
||
|
beta: null,
|
||
|
doubles: pre.doubles && {
|
||
|
step: pre.doubles.step,
|
||
|
points: [ res ].concat(pre.doubles.points.map(obj2point))
|
||
|
},
|
||
|
naf: pre.naf && {
|
||
|
wnd: pre.naf.wnd,
|
||
|
points: [ res ].concat(pre.naf.points.map(obj2point))
|
||
|
}
|
||
|
};
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
Point.prototype.inspect = function inspect() {
|
||
|
if (this.isInfinity())
|
||
|
return '<EC Point Infinity>';
|
||
|
return '<EC Point x: ' + this.x.fromRed().toString(16, 2) +
|
||
|
' y: ' + this.y.fromRed().toString(16, 2) + '>';
|
||
|
};
|
||
|
|
||
|
Point.prototype.isInfinity = function isInfinity() {
|
||
|
return this.inf;
|
||
|
};
|
||
|
|
||
|
Point.prototype.add = function add(p) {
|
||
|
// O + P = P
|
||
|
if (this.inf)
|
||
|
return p;
|
||
|
|
||
|
// P + O = P
|
||
|
if (p.inf)
|
||
|
return this;
|
||
|
|
||
|
// P + P = 2P
|
||
|
if (this.eq(p))
|
||
|
return this.dbl();
|
||
|
|
||
|
// P + (-P) = O
|
||
|
if (this.neg().eq(p))
|
||
|
return this.curve.point(null, null);
|
||
|
|
||
|
// P + Q = O
|
||
|
if (this.x.cmp(p.x) === 0)
|
||
|
return this.curve.point(null, null);
|
||
|
|
||
|
var c = this.y.redSub(p.y);
|
||
|
if (c.cmpn(0) !== 0)
|
||
|
c = c.redMul(this.x.redSub(p.x).redInvm());
|
||
|
var nx = c.redSqr().redISub(this.x).redISub(p.x);
|
||
|
var ny = c.redMul(this.x.redSub(nx)).redISub(this.y);
|
||
|
return this.curve.point(nx, ny);
|
||
|
};
|
||
|
|
||
|
Point.prototype.dbl = function dbl() {
|
||
|
if (this.inf)
|
||
|
return this;
|
||
|
|
||
|
// 2P = O
|
||
|
var ys1 = this.y.redAdd(this.y);
|
||
|
if (ys1.cmpn(0) === 0)
|
||
|
return this.curve.point(null, null);
|
||
|
|
||
|
var a = this.curve.a;
|
||
|
|
||
|
var x2 = this.x.redSqr();
|
||
|
var dyinv = ys1.redInvm();
|
||
|
var c = x2.redAdd(x2).redIAdd(x2).redIAdd(a).redMul(dyinv);
|
||
|
|
||
|
var nx = c.redSqr().redISub(this.x.redAdd(this.x));
|
||
|
var ny = c.redMul(this.x.redSub(nx)).redISub(this.y);
|
||
|
return this.curve.point(nx, ny);
|
||
|
};
|
||
|
|
||
|
Point.prototype.getX = function getX() {
|
||
|
return this.x.fromRed();
|
||
|
};
|
||
|
|
||
|
Point.prototype.getY = function getY() {
|
||
|
return this.y.fromRed();
|
||
|
};
|
||
|
|
||
|
Point.prototype.mul = function mul(k) {
|
||
|
k = new BN(k, 16);
|
||
|
|
||
|
if (this._hasDoubles(k))
|
||
|
return this.curve._fixedNafMul(this, k);
|
||
|
else if (this.curve.endo)
|
||
|
return this.curve._endoWnafMulAdd([ this ], [ k ]);
|
||
|
else
|
||
|
return this.curve._wnafMul(this, k);
|
||
|
};
|
||
|
|
||
|
Point.prototype.mulAdd = function mulAdd(k1, p2, k2) {
|
||
|
var points = [ this, p2 ];
|
||
|
var coeffs = [ k1, k2 ];
|
||
|
if (this.curve.endo)
|
||
|
return this.curve._endoWnafMulAdd(points, coeffs);
|
||
|
else
|
||
|
return this.curve._wnafMulAdd(1, points, coeffs, 2);
|
||
|
};
|
||
|
|
||
|
Point.prototype.jmulAdd = function jmulAdd(k1, p2, k2) {
|
||
|
var points = [ this, p2 ];
|
||
|
var coeffs = [ k1, k2 ];
|
||
|
if (this.curve.endo)
|
||
|
return this.curve._endoWnafMulAdd(points, coeffs, true);
|
||
|
else
|
||
|
return this.curve._wnafMulAdd(1, points, coeffs, 2, true);
|
||
|
};
|
||
|
|
||
|
Point.prototype.eq = function eq(p) {
|
||
|
return this === p ||
|
||
|
this.inf === p.inf &&
|
||
|
(this.inf || this.x.cmp(p.x) === 0 && this.y.cmp(p.y) === 0);
|
||
|
};
|
||
|
|
||
|
Point.prototype.neg = function neg(_precompute) {
|
||
|
if (this.inf)
|
||
|
return this;
|
||
|
|
||
|
var res = this.curve.point(this.x, this.y.redNeg());
|
||
|
if (_precompute && this.precomputed) {
|
||
|
var pre = this.precomputed;
|
||
|
var negate = function(p) {
|
||
|
return p.neg();
|
||
|
};
|
||
|
res.precomputed = {
|
||
|
naf: pre.naf && {
|
||
|
wnd: pre.naf.wnd,
|
||
|
points: pre.naf.points.map(negate)
|
||
|
},
|
||
|
doubles: pre.doubles && {
|
||
|
step: pre.doubles.step,
|
||
|
points: pre.doubles.points.map(negate)
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
Point.prototype.toJ = function toJ() {
|
||
|
if (this.inf)
|
||
|
return this.curve.jpoint(null, null, null);
|
||
|
|
||
|
var res = this.curve.jpoint(this.x, this.y, this.curve.one);
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
function JPoint(curve, x, y, z) {
|
||
|
Base.BasePoint.call(this, curve, 'jacobian');
|
||
|
if (x === null && y === null && z === null) {
|
||
|
this.x = this.curve.one;
|
||
|
this.y = this.curve.one;
|
||
|
this.z = new BN(0);
|
||
|
} else {
|
||
|
this.x = new BN(x, 16);
|
||
|
this.y = new BN(y, 16);
|
||
|
this.z = new BN(z, 16);
|
||
|
}
|
||
|
if (!this.x.red)
|
||
|
this.x = this.x.toRed(this.curve.red);
|
||
|
if (!this.y.red)
|
||
|
this.y = this.y.toRed(this.curve.red);
|
||
|
if (!this.z.red)
|
||
|
this.z = this.z.toRed(this.curve.red);
|
||
|
|
||
|
this.zOne = this.z === this.curve.one;
|
||
|
}
|
||
|
inherits(JPoint, Base.BasePoint);
|
||
|
|
||
|
ShortCurve.prototype.jpoint = function jpoint(x, y, z) {
|
||
|
return new JPoint(this, x, y, z);
|
||
|
};
|
||
|
|
||
|
JPoint.prototype.toP = function toP() {
|
||
|
if (this.isInfinity())
|
||
|
return this.curve.point(null, null);
|
||
|
|
||
|
var zinv = this.z.redInvm();
|
||
|
var zinv2 = zinv.redSqr();
|
||
|
var ax = this.x.redMul(zinv2);
|
||
|
var ay = this.y.redMul(zinv2).redMul(zinv);
|
||
|
|
||
|
return this.curve.point(ax, ay);
|
||
|
};
|
||
|
|
||
|
JPoint.prototype.neg = function neg() {
|
||
|
return this.curve.jpoint(this.x, this.y.redNeg(), this.z);
|
||
|
};
|
||
|
|
||
|
JPoint.prototype.add = function add(p) {
|
||
|
// O + P = P
|
||
|
if (this.isInfinity())
|
||
|
return p;
|
||
|
|
||
|
// P + O = P
|
||
|
if (p.isInfinity())
|
||
|
return this;
|
||
|
|
||
|
// 12M + 4S + 7A
|
||
|
var pz2 = p.z.redSqr();
|
||
|
var z2 = this.z.redSqr();
|
||
|
var u1 = this.x.redMul(pz2);
|
||
|
var u2 = p.x.redMul(z2);
|
||
|
var s1 = this.y.redMul(pz2.redMul(p.z));
|
||
|
var s2 = p.y.redMul(z2.redMul(this.z));
|
||
|
|
||
|
var h = u1.redSub(u2);
|
||
|
var r = s1.redSub(s2);
|
||
|
if (h.cmpn(0) === 0) {
|
||
|
if (r.cmpn(0) !== 0)
|
||
|
return this.curve.jpoint(null, null, null);
|
||
|
else
|
||
|
return this.dbl();
|
||
|
}
|
||
|
|
||
|
var h2 = h.redSqr();
|
||
|
var h3 = h2.redMul(h);
|
||
|
var v = u1.redMul(h2);
|
||
|
|
||
|
var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v);
|
||
|
var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3));
|
||
|
var nz = this.z.redMul(p.z).redMul(h);
|
||
|
|
||
|
return this.curve.jpoint(nx, ny, nz);
|
||
|
};
|
||
|
|
||
|
JPoint.prototype.mixedAdd = function mixedAdd(p) {
|
||
|
// O + P = P
|
||
|
if (this.isInfinity())
|
||
|
return p.toJ();
|
||
|
|
||
|
// P + O = P
|
||
|
if (p.isInfinity())
|
||
|
return this;
|
||
|
|
||
|
// 8M + 3S + 7A
|
||
|
var z2 = this.z.redSqr();
|
||
|
var u1 = this.x;
|
||
|
var u2 = p.x.redMul(z2);
|
||
|
var s1 = this.y;
|
||
|
var s2 = p.y.redMul(z2).redMul(this.z);
|
||
|
|
||
|
var h = u1.redSub(u2);
|
||
|
var r = s1.redSub(s2);
|
||
|
if (h.cmpn(0) === 0) {
|
||
|
if (r.cmpn(0) !== 0)
|
||
|
return this.curve.jpoint(null, null, null);
|
||
|
else
|
||
|
return this.dbl();
|
||
|
}
|
||
|
|
||
|
var h2 = h.redSqr();
|
||
|
var h3 = h2.redMul(h);
|
||
|
var v = u1.redMul(h2);
|
||
|
|
||
|
var nx = r.redSqr().redIAdd(h3).redISub(v).redISub(v);
|
||
|
var ny = r.redMul(v.redISub(nx)).redISub(s1.redMul(h3));
|
||
|
var nz = this.z.redMul(h);
|
||
|
|
||
|
return this.curve.jpoint(nx, ny, nz);
|
||
|
};
|
||
|
|
||
|
JPoint.prototype.dblp = function dblp(pow) {
|
||
|
if (pow === 0)
|
||
|
return this;
|
||
|
if (this.isInfinity())
|
||
|
return this;
|
||
|
if (!pow)
|
||
|
return this.dbl();
|
||
|
|
||
|
if (this.curve.zeroA || this.curve.threeA) {
|
||
|
var r = this;
|
||
|
for (var i = 0; i < pow; i++)
|
||
|
r = r.dbl();
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
// 1M + 2S + 1A + N * (4S + 5M + 8A)
|
||
|
// N = 1 => 6M + 6S + 9A
|
||
|
var a = this.curve.a;
|
||
|
var tinv = this.curve.tinv;
|
||
|
|
||
|
var jx = this.x;
|
||
|
var jy = this.y;
|
||
|
var jz = this.z;
|
||
|
var jz4 = jz.redSqr().redSqr();
|
||
|
|
||
|
// Reuse results
|
||
|
var jyd = jy.redAdd(jy);
|
||
|
for (var i = 0; i < pow; i++) {
|
||
|
var jx2 = jx.redSqr();
|
||
|
var jyd2 = jyd.redSqr();
|
||
|
var jyd4 = jyd2.redSqr();
|
||
|
var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4));
|
||
|
|
||
|
var t1 = jx.redMul(jyd2);
|
||
|
var nx = c.redSqr().redISub(t1.redAdd(t1));
|
||
|
var t2 = t1.redISub(nx);
|
||
|
var dny = c.redMul(t2);
|
||
|
dny = dny.redIAdd(dny).redISub(jyd4);
|
||
|
var nz = jyd.redMul(jz);
|
||
|
if (i + 1 < pow)
|
||
|
jz4 = jz4.redMul(jyd4);
|
||
|
|
||
|
jx = nx;
|
||
|
jz = nz;
|
||
|
jyd = dny;
|
||
|
}
|
||
|
|
||
|
return this.curve.jpoint(jx, jyd.redMul(tinv), jz);
|
||
|
};
|
||
|
|
||
|
JPoint.prototype.dbl = function dbl() {
|
||
|
if (this.isInfinity())
|
||
|
return this;
|
||
|
|
||
|
if (this.curve.zeroA)
|
||
|
return this._zeroDbl();
|
||
|
else if (this.curve.threeA)
|
||
|
return this._threeDbl();
|
||
|
else
|
||
|
return this._dbl();
|
||
|
};
|
||
|
|
||
|
JPoint.prototype._zeroDbl = function _zeroDbl() {
|
||
|
var nx;
|
||
|
var ny;
|
||
|
var nz;
|
||
|
// Z = 1
|
||
|
if (this.zOne) {
|
||
|
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html
|
||
|
// #doubling-mdbl-2007-bl
|
||
|
// 1M + 5S + 14A
|
||
|
|
||
|
// XX = X1^2
|
||
|
var xx = this.x.redSqr();
|
||
|
// YY = Y1^2
|
||
|
var yy = this.y.redSqr();
|
||
|
// YYYY = YY^2
|
||
|
var yyyy = yy.redSqr();
|
||
|
// S = 2 * ((X1 + YY)^2 - XX - YYYY)
|
||
|
var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy);
|
||
|
s = s.redIAdd(s);
|
||
|
// M = 3 * XX + a; a = 0
|
||
|
var m = xx.redAdd(xx).redIAdd(xx);
|
||
|
// T = M ^ 2 - 2*S
|
||
|
var t = m.redSqr().redISub(s).redISub(s);
|
||
|
|
||
|
// 8 * YYYY
|
||
|
var yyyy8 = yyyy.redIAdd(yyyy);
|
||
|
yyyy8 = yyyy8.redIAdd(yyyy8);
|
||
|
yyyy8 = yyyy8.redIAdd(yyyy8);
|
||
|
|
||
|
// X3 = T
|
||
|
nx = t;
|
||
|
// Y3 = M * (S - T) - 8 * YYYY
|
||
|
ny = m.redMul(s.redISub(t)).redISub(yyyy8);
|
||
|
// Z3 = 2*Y1
|
||
|
nz = this.y.redAdd(this.y);
|
||
|
} else {
|
||
|
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html
|
||
|
// #doubling-dbl-2009-l
|
||
|
// 2M + 5S + 13A
|
||
|
|
||
|
// A = X1^2
|
||
|
var a = this.x.redSqr();
|
||
|
// B = Y1^2
|
||
|
var b = this.y.redSqr();
|
||
|
// C = B^2
|
||
|
var c = b.redSqr();
|
||
|
// D = 2 * ((X1 + B)^2 - A - C)
|
||
|
var d = this.x.redAdd(b).redSqr().redISub(a).redISub(c);
|
||
|
d = d.redIAdd(d);
|
||
|
// E = 3 * A
|
||
|
var e = a.redAdd(a).redIAdd(a);
|
||
|
// F = E^2
|
||
|
var f = e.redSqr();
|
||
|
|
||
|
// 8 * C
|
||
|
var c8 = c.redIAdd(c);
|
||
|
c8 = c8.redIAdd(c8);
|
||
|
c8 = c8.redIAdd(c8);
|
||
|
|
||
|
// X3 = F - 2 * D
|
||
|
nx = f.redISub(d).redISub(d);
|
||
|
// Y3 = E * (D - X3) - 8 * C
|
||
|
ny = e.redMul(d.redISub(nx)).redISub(c8);
|
||
|
// Z3 = 2 * Y1 * Z1
|
||
|
nz = this.y.redMul(this.z);
|
||
|
nz = nz.redIAdd(nz);
|
||
|
}
|
||
|
|
||
|
return this.curve.jpoint(nx, ny, nz);
|
||
|
};
|
||
|
|
||
|
JPoint.prototype._threeDbl = function _threeDbl() {
|
||
|
var nx;
|
||
|
var ny;
|
||
|
var nz;
|
||
|
// Z = 1
|
||
|
if (this.zOne) {
|
||
|
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html
|
||
|
// #doubling-mdbl-2007-bl
|
||
|
// 1M + 5S + 15A
|
||
|
|
||
|
// XX = X1^2
|
||
|
var xx = this.x.redSqr();
|
||
|
// YY = Y1^2
|
||
|
var yy = this.y.redSqr();
|
||
|
// YYYY = YY^2
|
||
|
var yyyy = yy.redSqr();
|
||
|
// S = 2 * ((X1 + YY)^2 - XX - YYYY)
|
||
|
var s = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy);
|
||
|
s = s.redIAdd(s);
|
||
|
// M = 3 * XX + a
|
||
|
var m = xx.redAdd(xx).redIAdd(xx).redIAdd(this.curve.a);
|
||
|
// T = M^2 - 2 * S
|
||
|
var t = m.redSqr().redISub(s).redISub(s);
|
||
|
// X3 = T
|
||
|
nx = t;
|
||
|
// Y3 = M * (S - T) - 8 * YYYY
|
||
|
var yyyy8 = yyyy.redIAdd(yyyy);
|
||
|
yyyy8 = yyyy8.redIAdd(yyyy8);
|
||
|
yyyy8 = yyyy8.redIAdd(yyyy8);
|
||
|
ny = m.redMul(s.redISub(t)).redISub(yyyy8);
|
||
|
// Z3 = 2 * Y1
|
||
|
nz = this.y.redAdd(this.y);
|
||
|
} else {
|
||
|
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
|
||
|
// 3M + 5S
|
||
|
|
||
|
// delta = Z1^2
|
||
|
var delta = this.z.redSqr();
|
||
|
// gamma = Y1^2
|
||
|
var gamma = this.y.redSqr();
|
||
|
// beta = X1 * gamma
|
||
|
var beta = this.x.redMul(gamma);
|
||
|
// alpha = 3 * (X1 - delta) * (X1 + delta)
|
||
|
var alpha = this.x.redSub(delta).redMul(this.x.redAdd(delta));
|
||
|
alpha = alpha.redAdd(alpha).redIAdd(alpha);
|
||
|
// X3 = alpha^2 - 8 * beta
|
||
|
var beta4 = beta.redIAdd(beta);
|
||
|
beta4 = beta4.redIAdd(beta4);
|
||
|
var beta8 = beta4.redAdd(beta4);
|
||
|
nx = alpha.redSqr().redISub(beta8);
|
||
|
// Z3 = (Y1 + Z1)^2 - gamma - delta
|
||
|
nz = this.y.redAdd(this.z).redSqr().redISub(gamma).redISub(delta);
|
||
|
// Y3 = alpha * (4 * beta - X3) - 8 * gamma^2
|
||
|
var ggamma8 = gamma.redSqr();
|
||
|
ggamma8 = ggamma8.redIAdd(ggamma8);
|
||
|
ggamma8 = ggamma8.redIAdd(ggamma8);
|
||
|
ggamma8 = ggamma8.redIAdd(ggamma8);
|
||
|
ny = alpha.redMul(beta4.redISub(nx)).redISub(ggamma8);
|
||
|
}
|
||
|
|
||
|
return this.curve.jpoint(nx, ny, nz);
|
||
|
};
|
||
|
|
||
|
JPoint.prototype._dbl = function _dbl() {
|
||
|
var a = this.curve.a;
|
||
|
|
||
|
// 4M + 6S + 10A
|
||
|
var jx = this.x;
|
||
|
var jy = this.y;
|
||
|
var jz = this.z;
|
||
|
var jz4 = jz.redSqr().redSqr();
|
||
|
|
||
|
var jx2 = jx.redSqr();
|
||
|
var jy2 = jy.redSqr();
|
||
|
|
||
|
var c = jx2.redAdd(jx2).redIAdd(jx2).redIAdd(a.redMul(jz4));
|
||
|
|
||
|
var jxd4 = jx.redAdd(jx);
|
||
|
jxd4 = jxd4.redIAdd(jxd4);
|
||
|
var t1 = jxd4.redMul(jy2);
|
||
|
var nx = c.redSqr().redISub(t1.redAdd(t1));
|
||
|
var t2 = t1.redISub(nx);
|
||
|
|
||
|
var jyd8 = jy2.redSqr();
|
||
|
jyd8 = jyd8.redIAdd(jyd8);
|
||
|
jyd8 = jyd8.redIAdd(jyd8);
|
||
|
jyd8 = jyd8.redIAdd(jyd8);
|
||
|
var ny = c.redMul(t2).redISub(jyd8);
|
||
|
var nz = jy.redAdd(jy).redMul(jz);
|
||
|
|
||
|
return this.curve.jpoint(nx, ny, nz);
|
||
|
};
|
||
|
|
||
|
JPoint.prototype.trpl = function trpl() {
|
||
|
if (!this.curve.zeroA)
|
||
|
return this.dbl().add(this);
|
||
|
|
||
|
// hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#tripling-tpl-2007-bl
|
||
|
// 5M + 10S + ...
|
||
|
|
||
|
// XX = X1^2
|
||
|
var xx = this.x.redSqr();
|
||
|
// YY = Y1^2
|
||
|
var yy = this.y.redSqr();
|
||
|
// ZZ = Z1^2
|
||
|
var zz = this.z.redSqr();
|
||
|
// YYYY = YY^2
|
||
|
var yyyy = yy.redSqr();
|
||
|
// M = 3 * XX + a * ZZ2; a = 0
|
||
|
var m = xx.redAdd(xx).redIAdd(xx);
|
||
|
// MM = M^2
|
||
|
var mm = m.redSqr();
|
||
|
// E = 6 * ((X1 + YY)^2 - XX - YYYY) - MM
|
||
|
var e = this.x.redAdd(yy).redSqr().redISub(xx).redISub(yyyy);
|
||
|
e = e.redIAdd(e);
|
||
|
e = e.redAdd(e).redIAdd(e);
|
||
|
e = e.redISub(mm);
|
||
|
// EE = E^2
|
||
|
var ee = e.redSqr();
|
||
|
// T = 16*YYYY
|
||
|
var t = yyyy.redIAdd(yyyy);
|
||
|
t = t.redIAdd(t);
|
||
|
t = t.redIAdd(t);
|
||
|
t = t.redIAdd(t);
|
||
|
// U = (M + E)^2 - MM - EE - T
|
||
|
var u = m.redIAdd(e).redSqr().redISub(mm).redISub(ee).redISub(t);
|
||
|
// X3 = 4 * (X1 * EE - 4 * YY * U)
|
||
|
var yyu4 = yy.redMul(u);
|
||
|
yyu4 = yyu4.redIAdd(yyu4);
|
||
|
yyu4 = yyu4.redIAdd(yyu4);
|
||
|
var nx = this.x.redMul(ee).redISub(yyu4);
|
||
|
nx = nx.redIAdd(nx);
|
||
|
nx = nx.redIAdd(nx);
|
||
|
// Y3 = 8 * Y1 * (U * (T - U) - E * EE)
|
||
|
var ny = this.y.redMul(u.redMul(t.redISub(u)).redISub(e.redMul(ee)));
|
||
|
ny = ny.redIAdd(ny);
|
||
|
ny = ny.redIAdd(ny);
|
||
|
ny = ny.redIAdd(ny);
|
||
|
// Z3 = (Z1 + E)^2 - ZZ - EE
|
||
|
var nz = this.z.redAdd(e).redSqr().redISub(zz).redISub(ee);
|
||
|
|
||
|
return this.curve.jpoint(nx, ny, nz);
|
||
|
};
|
||
|
|
||
|
JPoint.prototype.mul = function mul(k, kbase) {
|
||
|
k = new BN(k, kbase);
|
||
|
|
||
|
return this.curve._wnafMul(this, k);
|
||
|
};
|
||
|
|
||
|
JPoint.prototype.eq = function eq(p) {
|
||
|
if (p.type === 'affine')
|
||
|
return this.eq(p.toJ());
|
||
|
|
||
|
if (this === p)
|
||
|
return true;
|
||
|
|
||
|
// x1 * z2^2 == x2 * z1^2
|
||
|
var z2 = this.z.redSqr();
|
||
|
var pz2 = p.z.redSqr();
|
||
|
if (this.x.redMul(pz2).redISub(p.x.redMul(z2)).cmpn(0) !== 0)
|
||
|
return false;
|
||
|
|
||
|
// y1 * z2^3 == y2 * z1^3
|
||
|
var z3 = z2.redMul(this.z);
|
||
|
var pz3 = pz2.redMul(p.z);
|
||
|
return this.y.redMul(pz3).redISub(p.y.redMul(z3)).cmpn(0) === 0;
|
||
|
};
|
||
|
|
||
|
JPoint.prototype.eqXToP = function eqXToP(x) {
|
||
|
var zs = this.z.redSqr();
|
||
|
var rx = x.toRed(this.curve.red).redMul(zs);
|
||
|
if (this.x.cmp(rx) === 0)
|
||
|
return true;
|
||
|
|
||
|
var xc = x.clone();
|
||
|
var t = this.curve.redN.redMul(zs);
|
||
|
for (;;) {
|
||
|
xc.iadd(this.curve.n);
|
||
|
if (xc.cmp(this.curve.p) >= 0)
|
||
|
return false;
|
||
|
|
||
|
rx.redIAdd(t);
|
||
|
if (this.x.cmp(rx) === 0)
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
};
|
||
|
|
||
|
JPoint.prototype.inspect = function inspect() {
|
||
|
if (this.isInfinity())
|
||
|
return '<EC JPoint Infinity>';
|
||
|
return '<EC JPoint x: ' + this.x.toString(16, 2) +
|
||
|
' y: ' + this.y.toString(16, 2) +
|
||
|
' z: ' + this.z.toString(16, 2) + '>';
|
||
|
};
|
||
|
|
||
|
JPoint.prototype.isInfinity = function isInfinity() {
|
||
|
// XXX This code assumes that zero is always zero in red
|
||
|
return this.z.cmpn(0) === 0;
|
||
|
};
|
||
|
|
||
|
},{"../../elliptic":6,"../curve":9,"bn.js":3,"inherits":27}],12:[function(require,module,exports){
|
||
|
'use strict';
|
||
|
|
||
|
var curves = exports;
|
||
|
|
||
|
var hash = require('hash.js');
|
||
|
var elliptic = require('../elliptic');
|
||
|
|
||
|
var assert = elliptic.utils.assert;
|
||
|
|
||
|
function PresetCurve(options) {
|
||
|
if (options.type === 'short')
|
||
|
this.curve = new elliptic.curve.short(options);
|
||
|
else if (options.type === 'edwards')
|
||
|
this.curve = new elliptic.curve.edwards(options);
|
||
|
else
|
||
|
this.curve = new elliptic.curve.mont(options);
|
||
|
this.g = this.curve.g;
|
||
|
this.n = this.curve.n;
|
||
|
this.hash = options.hash;
|
||
|
|
||
|
assert(this.g.validate(), 'Invalid curve');
|
||
|
assert(this.g.mul(this.n).isInfinity(), 'Invalid curve, G*N != O');
|
||
|
}
|
||
|
curves.PresetCurve = PresetCurve;
|
||
|
|
||
|
function defineCurve(name, options) {
|
||
|
Object.defineProperty(curves, name, {
|
||
|
configurable: true,
|
||
|
enumerable: true,
|
||
|
get: function() {
|
||
|
var curve = new PresetCurve(options);
|
||
|
Object.defineProperty(curves, name, {
|
||
|
configurable: true,
|
||
|
enumerable: true,
|
||
|
value: curve
|
||
|
});
|
||
|
return curve;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
defineCurve('p192', {
|
||
|
type: 'short',
|
||
|
prime: 'p192',
|
||
|
p: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff',
|
||
|
a: 'ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc',
|
||
|
b: '64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1',
|
||
|
n: 'ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831',
|
||
|
hash: hash.sha256,
|
||
|
gRed: false,
|
||
|
g: [
|
||
|
'188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012',
|
||
|
'07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811'
|
||
|
]
|
||
|
});
|
||
|
|
||
|
defineCurve('p224', {
|
||
|
type: 'short',
|
||
|
prime: 'p224',
|
||
|
p: 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001',
|
||
|
a: 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe',
|
||
|
b: 'b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4',
|
||
|
n: 'ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d',
|
||
|
hash: hash.sha256,
|
||
|
gRed: false,
|
||
|
g: [
|
||
|
'b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21',
|
||
|
'bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34'
|
||
|
]
|
||
|
});
|
||
|
|
||
|
defineCurve('p256', {
|
||
|
type: 'short',
|
||
|
prime: null,
|
||
|
p: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff',
|
||
|
a: 'ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc',
|
||
|
b: '5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b',
|
||
|
n: 'ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551',
|
||
|
hash: hash.sha256,
|
||
|
gRed: false,
|
||
|
g: [
|
||
|
'6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296',
|
||
|
'4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5'
|
||
|
]
|
||
|
});
|
||
|
|
||
|
defineCurve('p384', {
|
||
|
type: 'short',
|
||
|
prime: null,
|
||
|
p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
||
|
'fffffffe ffffffff 00000000 00000000 ffffffff',
|
||
|
a: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
||
|
'fffffffe ffffffff 00000000 00000000 fffffffc',
|
||
|
b: 'b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f ' +
|
||
|
'5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef',
|
||
|
n: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 ' +
|
||
|
'f4372ddf 581a0db2 48b0a77a ecec196a ccc52973',
|
||
|
hash: hash.sha384,
|
||
|
gRed: false,
|
||
|
g: [
|
||
|
'aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 ' +
|
||
|
'5502f25d bf55296c 3a545e38 72760ab7',
|
||
|
'3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 ' +
|
||
|
'0a60b1ce 1d7e819d 7a431d7c 90ea0e5f'
|
||
|
]
|
||
|
});
|
||
|
|
||
|
defineCurve('p521', {
|
||
|
type: 'short',
|
||
|
prime: null,
|
||
|
p: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
||
|
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
||
|
'ffffffff ffffffff ffffffff ffffffff ffffffff',
|
||
|
a: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
||
|
'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
||
|
'ffffffff ffffffff ffffffff ffffffff fffffffc',
|
||
|
b: '00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b ' +
|
||
|
'99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd ' +
|
||
|
'3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00',
|
||
|
n: '000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ' +
|
||
|
'ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 ' +
|
||
|
'f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409',
|
||
|
hash: hash.sha512,
|
||
|
gRed: false,
|
||
|
g: [
|
||
|
'000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 ' +
|
||
|
'053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 ' +
|
||
|
'a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66',
|
||
|
'00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 ' +
|
||
|
'579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 ' +
|
||
|
'3fad0761 353c7086 a272c240 88be9476 9fd16650'
|
||
|
]
|
||
|
});
|
||
|
|
||
|
defineCurve('curve25519', {
|
||
|
type: 'mont',
|
||
|
prime: 'p25519',
|
||
|
p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed',
|
||
|
a: '76d06',
|
||
|
b: '1',
|
||
|
n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed',
|
||
|
hash: hash.sha256,
|
||
|
gRed: false,
|
||
|
g: [
|
||
|
'9'
|
||
|
]
|
||
|
});
|
||
|
|
||
|
defineCurve('ed25519', {
|
||
|
type: 'edwards',
|
||
|
prime: 'p25519',
|
||
|
p: '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed',
|
||
|
a: '-1',
|
||
|
c: '1',
|
||
|
// -121665 * (121666^(-1)) (mod P)
|
||
|
d: '52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3',
|
||
|
n: '1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed',
|
||
|
hash: hash.sha256,
|
||
|
gRed: false,
|
||
|
g: [
|
||
|
'216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a',
|
||
|
|
||
|
// 4/5
|
||
|
'6666666666666666666666666666666666666666666666666666666666666658'
|
||
|
]
|
||
|
});
|
||
|
|
||
|
var pre;
|
||
|
try {
|
||
|
pre = require('./precomputed/secp256k1');
|
||
|
} catch (e) {
|
||
|
pre = undefined;
|
||
|
}
|
||
|
|
||
|
defineCurve('secp256k1', {
|
||
|
type: 'short',
|
||
|
prime: 'k256',
|
||
|
p: 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f',
|
||
|
a: '0',
|
||
|
b: '7',
|
||
|
n: 'ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141',
|
||
|
h: '1',
|
||
|
hash: hash.sha256,
|
||
|
|
||
|
// Precomputed endomorphism
|
||
|
beta: '7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee',
|
||
|
lambda: '5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72',
|
||
|
basis: [
|
||
|
{
|
||
|
a: '3086d221a7d46bcde86c90e49284eb15',
|
||
|
b: '-e4437ed6010e88286f547fa90abfe4c3'
|
||
|
},
|
||
|
{
|
||
|
a: '114ca50f7a8e2f3f657c1108d9d44cfd8',
|
||
|
b: '3086d221a7d46bcde86c90e49284eb15'
|
||
|
}
|
||
|
],
|
||
|
|
||
|
gRed: false,
|
||
|
g: [
|
||
|
'79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
|
||
|
'483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8',
|
||
|
pre
|
||
|
]
|
||
|
});
|
||
|
|
||
|
},{"../elliptic":6,"./precomputed/secp256k1":17,"hash.js":20}],13:[function(require,module,exports){
|
||
|
'use strict';
|
||
|
|
||
|
var BN = require('bn.js');
|
||
|
var HmacDRBG = require('hmac-drbg');
|
||
|
var elliptic = require('../../elliptic');
|
||
|
var utils = elliptic.utils;
|
||
|
var assert = utils.assert;
|
||
|
|
||
|
var KeyPair = require('./key');
|
||
|
var Signature = require('./signature');
|
||
|
|
||
|
function EC(options) {
|
||
|
if (!(this instanceof EC))
|
||
|
return new EC(options);
|
||
|
|
||
|
// Shortcut `elliptic.ec(curve-name)`
|
||
|
if (typeof options === 'string') {
|
||
|
assert(elliptic.curves.hasOwnProperty(options), 'Unknown curve ' + options);
|
||
|
|
||
|
options = elliptic.curves[options];
|
||
|
}
|
||
|
|
||
|
// Shortcut for `elliptic.ec(elliptic.curves.curveName)`
|
||
|
if (options instanceof elliptic.curves.PresetCurve)
|
||
|
options = { curve: options };
|
||
|
|
||
|
this.curve = options.curve.curve;
|
||
|
this.n = this.curve.n;
|
||
|
this.nh = this.n.ushrn(1);
|
||
|
this.g = this.curve.g;
|
||
|
|
||
|
// Point on curve
|
||
|
this.g = options.curve.g;
|
||
|
this.g.precompute(options.curve.n.bitLength() + 1);
|
||
|
|
||
|
// Hash for function for DRBG
|
||
|
this.hash = options.hash || options.curve.hash;
|
||
|
}
|
||
|
module.exports = EC;
|
||
|
|
||
|
EC.prototype.keyPair = function keyPair(options) {
|
||
|
return new KeyPair(this, options);
|
||
|
};
|
||
|
|
||
|
EC.prototype.keyFromPrivate = function keyFromPrivate(priv, enc) {
|
||
|
return KeyPair.fromPrivate(this, priv, enc);
|
||
|
};
|
||
|
|
||
|
EC.prototype.keyFromPublic = function keyFromPublic(pub, enc) {
|
||
|
return KeyPair.fromPublic(this, pub, enc);
|
||
|
};
|
||
|
|
||
|
EC.prototype.genKeyPair = function genKeyPair(options) {
|
||
|
if (!options)
|
||
|
options = {};
|
||
|
|
||
|
// Instantiate Hmac_DRBG
|
||
|
var drbg = new HmacDRBG({
|
||
|
hash: this.hash,
|
||
|
pers: options.pers,
|
||
|
persEnc: options.persEnc || 'utf8',
|
||
|
entropy: options.entropy || elliptic.rand(this.hash.hmacStrength),
|
||
|
entropyEnc: options.entropy && options.entropyEnc || 'utf8',
|
||
|
nonce: this.n.toArray()
|
||
|
});
|
||
|
|
||
|
var bytes = this.n.byteLength();
|
||
|
var ns2 = this.n.sub(new BN(2));
|
||
|
do {
|
||
|
var priv = new BN(drbg.generate(bytes));
|
||
|
if (priv.cmp(ns2) > 0)
|
||
|
continue;
|
||
|
|
||
|
priv.iaddn(1);
|
||
|
return this.keyFromPrivate(priv);
|
||
|
} while (true);
|
||
|
};
|
||
|
|
||
|
EC.prototype._truncateToN = function truncateToN(msg, truncOnly) {
|
||
|
var delta = msg.byteLength() * 8 - this.n.bitLength();
|
||
|
if (delta > 0)
|
||
|
msg = msg.ushrn(delta);
|
||
|
if (!truncOnly && msg.cmp(this.n) >= 0)
|
||
|
return msg.sub(this.n);
|
||
|
else
|
||
|
return msg;
|
||
|
};
|
||
|
|
||
|
EC.prototype.sign = function sign(msg, key, enc, options) {
|
||
|
if (typeof enc === 'object') {
|
||
|
options = enc;
|
||
|
enc = null;
|
||
|
}
|
||
|
if (!options)
|
||
|
options = {};
|
||
|
|
||
|
key = this.keyFromPrivate(key, enc);
|
||
|
msg = this._truncateToN(new BN(msg, 16));
|
||
|
|
||
|
// Zero-extend key to provide enough entropy
|
||
|
var bytes = this.n.byteLength();
|
||
|
var bkey = key.getPrivate().toArray('be', bytes);
|
||
|
|
||
|
// Zero-extend nonce to have the same byte size as N
|
||
|
var nonce = msg.toArray('be', bytes);
|
||
|
|
||
|
// Instantiate Hmac_DRBG
|
||
|
var drbg = new HmacDRBG({
|
||
|
hash: this.hash,
|
||
|
entropy: bkey,
|
||
|
nonce: nonce,
|
||
|
pers: options.pers,
|
||
|
persEnc: options.persEnc || 'utf8'
|
||
|
});
|
||
|
|
||
|
// Number of bytes to generate
|
||
|
var ns1 = this.n.sub(new BN(1));
|
||
|
|
||
|
for (var iter = 0; true; iter++) {
|
||
|
var k = options.k ?
|
||
|
options.k(iter) :
|
||
|
new BN(drbg.generate(this.n.byteLength()));
|
||
|
k = this._truncateToN(k, true);
|
||
|
if (k.cmpn(1) <= 0 || k.cmp(ns1) >= 0)
|
||
|
continue;
|
||
|
|
||
|
var kp = this.g.mul(k);
|
||
|
if (kp.isInfinity())
|
||
|
continue;
|
||
|
|
||
|
var kpX = kp.getX();
|
||
|
var r = kpX.umod(this.n);
|
||
|
if (r.cmpn(0) === 0)
|
||
|
continue;
|
||
|
|
||
|
var s = k.invm(this.n).mul(r.mul(key.getPrivate()).iadd(msg));
|
||
|
s = s.umod(this.n);
|
||
|
if (s.cmpn(0) === 0)
|
||
|
continue;
|
||
|
|
||
|
var recoveryParam = (kp.getY().isOdd() ? 1 : 0) |
|
||
|
(kpX.cmp(r) !== 0 ? 2 : 0);
|
||
|
|
||
|
// Use complement of `s`, if it is > `n / 2`
|
||
|
if (options.canonical && s.cmp(this.nh) > 0) {
|
||
|
s = this.n.sub(s);
|
||
|
recoveryParam ^= 1;
|
||
|
}
|
||
|
|
||
|
return new Signature({ r: r, s: s, recoveryParam: recoveryParam });
|
||
|
}
|
||
|
};
|
||
|
|
||
|
EC.prototype.verify = function verify(msg, signature, key, enc) {
|
||
|
msg = this._truncateToN(new BN(msg, 16));
|
||
|
key = this.keyFromPublic(key, enc);
|
||
|
signature = new Signature(signature, 'hex');
|
||
|
|
||
|
// Perform primitive values validation
|
||
|
var r = signature.r;
|
||
|
var s = signature.s;
|
||
|
if (r.cmpn(1) < 0 || r.cmp(this.n) >= 0)
|
||
|
return false;
|
||
|
if (s.cmpn(1) < 0 || s.cmp(this.n) >= 0)
|
||
|
return false;
|
||
|
|
||
|
// Validate signature
|
||
|
var sinv = s.invm(this.n);
|
||
|
var u1 = sinv.mul(msg).umod(this.n);
|
||
|
var u2 = sinv.mul(r).umod(this.n);
|
||
|
|
||
|
if (!this.curve._maxwellTrick) {
|
||
|
var p = this.g.mulAdd(u1, key.getPublic(), u2);
|
||
|
if (p.isInfinity())
|
||
|
return false;
|
||
|
|
||
|
return p.getX().umod(this.n).cmp(r) === 0;
|
||
|
}
|
||
|
|
||
|
// NOTE: Greg Maxwell's trick, inspired by:
|
||
|
// https://git.io/vad3K
|
||
|
|
||
|
var p = this.g.jmulAdd(u1, key.getPublic(), u2);
|
||
|
if (p.isInfinity())
|
||
|
return false;
|
||
|
|
||
|
// Compare `p.x` of Jacobian point with `r`,
|
||
|
// this will do `p.x == r * p.z^2` instead of multiplying `p.x` by the
|
||
|
// inverse of `p.z^2`
|
||
|
return p.eqXToP(r);
|
||
|
};
|
||
|
|
||
|
EC.prototype.recoverPubKey = function(msg, signature, j, enc) {
|
||
|
assert((3 & j) === j, 'The recovery param is more than two bits');
|
||
|
signature = new Signature(signature, enc);
|
||
|
|
||
|
var n = this.n;
|
||
|
var e = new BN(msg);
|
||
|
var r = signature.r;
|
||
|
var s = signature.s;
|
||
|
|
||
|
// A set LSB signifies that the y-coordinate is odd
|
||
|
var isYOdd = j & 1;
|
||
|
var isSecondKey = j >> 1;
|
||
|
if (r.cmp(this.curve.p.umod(this.curve.n)) >= 0 && isSecondKey)
|
||
|
throw new Error('Unable to find sencond key candinate');
|
||
|
|
||
|
// 1.1. Let x = r + jn.
|
||
|
if (isSecondKey)
|
||
|
r = this.curve.pointFromX(r.add(this.curve.n), isYOdd);
|
||
|
else
|
||
|
r = this.curve.pointFromX(r, isYOdd);
|
||
|
|
||
|
var rInv = signature.r.invm(n);
|
||
|
var s1 = n.sub(e).mul(rInv).umod(n);
|
||
|
var s2 = s.mul(rInv).umod(n);
|
||
|
|
||
|
// 1.6.1 Compute Q = r^-1 (sR - eG)
|
||
|
// Q = r^-1 (sR + -eG)
|
||
|
return this.g.mulAdd(s1, r, s2);
|
||
|
};
|
||
|
|
||
|
EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) {
|
||
|
signature = new Signature(signature, enc);
|
||
|
if (signature.recoveryParam !== null)
|
||
|
return signature.recoveryParam;
|
||
|
|
||
|
for (var i = 0; i < 4; i++) {
|
||
|
var Qprime;
|
||
|
try {
|
||
|
Qprime = this.recoverPubKey(e, signature, i);
|
||
|
} catch (e) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (Qprime.eq(Q))
|
||
|
return i;
|
||
|
}
|
||
|
throw new Error('Unable to find valid recovery factor');
|
||
|
};
|
||
|
|
||
|
},{"../../elliptic":6,"./key":14,"./signature":15,"bn.js":3,"hmac-drbg":26}],14:[function(require,module,exports){
|
||
|
'use strict';
|
||
|
|
||
|
var BN = require('bn.js');
|
||
|
var elliptic = require('../../elliptic');
|
||
|
var utils = elliptic.utils;
|
||
|
var assert = utils.assert;
|
||
|
|
||
|
function KeyPair(ec, options) {
|
||
|
this.ec = ec;
|
||
|
this.priv = null;
|
||
|
this.pub = null;
|
||
|
|
||
|
// KeyPair(ec, { priv: ..., pub: ... })
|
||
|
if (options.priv)
|
||
|
this._importPrivate(options.priv, options.privEnc);
|
||
|
if (options.pub)
|
||
|
this._importPublic(options.pub, options.pubEnc);
|
||
|
}
|
||
|
module.exports = KeyPair;
|
||
|
|
||
|
KeyPair.fromPublic = function fromPublic(ec, pub, enc) {
|
||
|
if (pub instanceof KeyPair)
|
||
|
return pub;
|
||
|
|
||
|
return new KeyPair(ec, {
|
||
|
pub: pub,
|
||
|
pubEnc: enc
|
||
|
});
|
||
|
};
|
||
|
|
||
|
KeyPair.fromPrivate = function fromPrivate(ec, priv, enc) {
|
||
|
if (priv instanceof KeyPair)
|
||
|
return priv;
|
||
|
|
||
|
return new KeyPair(ec, {
|
||
|
priv: priv,
|
||
|
privEnc: enc
|
||
|
});
|
||
|
};
|
||
|
|
||
|
KeyPair.prototype.validate = function validate() {
|
||
|
var pub = this.getPublic();
|
||
|
|
||
|
if (pub.isInfinity())
|
||
|
return { result: false, reason: 'Invalid public key' };
|
||
|
if (!pub.validate())
|
||
|
return { result: false, reason: 'Public key is not a point' };
|
||
|
if (!pub.mul(this.ec.curve.n).isInfinity())
|
||
|
return { result: false, reason: 'Public key * N != O' };
|
||
|
|
||
|
return { result: true, reason: null };
|
||
|
};
|
||
|
|
||
|
KeyPair.prototype.getPublic = function getPublic(compact, enc) {
|
||
|
// compact is optional argument
|
||
|
if (typeof compact === 'string') {
|
||
|
enc = compact;
|
||
|
compact = null;
|
||
|
}
|
||
|
|
||
|
if (!this.pub)
|
||
|
this.pub = this.ec.g.mul(this.priv);
|
||
|
|
||
|
if (!enc)
|
||
|
return this.pub;
|
||
|
|
||
|
return this.pub.encode(enc, compact);
|
||
|
};
|
||
|
|
||
|
KeyPair.prototype.getPrivate = function getPrivate(enc) {
|
||
|
if (enc === 'hex')
|
||
|
return this.priv.toString(16, 2);
|
||
|
else
|
||
|
return this.priv;
|
||
|
};
|
||
|
|
||
|
KeyPair.prototype._importPrivate = function _importPrivate(key, enc) {
|
||
|
this.priv = new BN(key, enc || 16);
|
||
|
|
||
|
// Ensure that the priv won't be bigger than n, otherwise we may fail
|
||
|
// in fixed multiplication method
|
||
|
this.priv = this.priv.umod(this.ec.curve.n);
|
||
|
};
|
||
|
|
||
|
KeyPair.prototype._importPublic = function _importPublic(key, enc) {
|
||
|
if (key.x || key.y) {
|
||
|
// Montgomery points only have an `x` coordinate.
|
||
|
// Weierstrass/Edwards points on the other hand have both `x` and
|
||
|
// `y` coordinates.
|
||
|
if (this.ec.curve.type === 'mont') {
|
||
|
assert(key.x, 'Need x coordinate');
|
||
|
} else if (this.ec.curve.type === 'short' ||
|
||
|
this.ec.curve.type === 'edwards') {
|
||
|
assert(key.x && key.y, 'Need both x and y coordinate');
|
||
|
}
|
||
|
this.pub = this.ec.curve.point(key.x, key.y);
|
||
|
return;
|
||
|
}
|
||
|
this.pub = this.ec.curve.decodePoint(key, enc);
|
||
|
};
|
||
|
|
||
|
// ECDH
|
||
|
KeyPair.prototype.derive = function derive(pub) {
|
||
|
return pub.mul(this.priv).getX();
|
||
|
};
|
||
|
|
||
|
// ECDSA
|
||
|
KeyPair.prototype.sign = function sign(msg, enc, options) {
|
||
|
return this.ec.sign(msg, this, enc, options);
|
||
|
};
|
||
|
|
||
|
KeyPair.prototype.verify = function verify(msg, signature) {
|
||
|
return this.ec.verify(msg, signature, this);
|
||
|
};
|
||
|
|
||
|
KeyPair.prototype.inspect = function inspect() {
|
||
|
return '<Key priv: ' + (this.priv && this.priv.toString(16, 2)) +
|
||
|
' pub: ' + (this.pub && this.pub.inspect()) + ' >';
|
||
|
};
|
||
|
|
||
|
},{"../../elliptic":6,"bn.js":3}],15:[function(require,module,exports){
|
||
|
'use strict';
|
||
|
|
||
|
var BN = require('bn.js');
|
||
|
|
||
|
var elliptic = require('../../elliptic');
|
||
|
var utils = elliptic.utils;
|
||
|
var assert = utils.assert;
|
||
|
|
||
|
function Signature(options, enc) {
|
||
|
if (options instanceof Signature)
|
||
|
return options;
|
||
|
|
||
|
if (this._importDER(options, enc))
|
||
|
return;
|
||
|
|
||
|
assert(options.r && options.s, 'Signature without r or s');
|
||
|
this.r = new BN(options.r, 16);
|
||
|
this.s = new BN(options.s, 16);
|
||
|
if (options.recoveryParam === undefined)
|
||
|
this.recoveryParam = null;
|
||
|
else
|
||
|
this.recoveryParam = options.recoveryParam;
|
||
|
}
|
||
|
module.exports = Signature;
|
||
|
|
||
|
function Position() {
|
||
|
this.place = 0;
|
||
|
}
|
||
|
|
||
|
function getLength(buf, p) {
|
||
|
var initial = buf[p.place++];
|
||
|
if (!(initial & 0x80)) {
|
||
|
return initial;
|
||
|
}
|
||
|
var octetLen = initial & 0xf;
|
||
|
var val = 0;
|
||
|
for (var i = 0, off = p.place; i < octetLen; i++, off++) {
|
||
|
val <<= 8;
|
||
|
val |= buf[off];
|
||
|
}
|
||
|
p.place = off;
|
||
|
return val;
|
||
|
}
|
||
|
|
||
|
function rmPadding(buf) {
|
||
|
var i = 0;
|
||
|
var len = buf.length - 1;
|
||
|
while (!buf[i] && !(buf[i + 1] & 0x80) && i < len) {
|
||
|
i++;
|
||
|
}
|
||
|
if (i === 0) {
|
||
|
return buf;
|
||
|
}
|
||
|
return buf.slice(i);
|
||
|
}
|
||
|
|
||
|
Signature.prototype._importDER = function _importDER(data, enc) {
|
||
|
data = utils.toArray(data, enc);
|
||
|
var p = new Position();
|
||
|
if (data[p.place++] !== 0x30) {
|
||
|
return false;
|
||
|
}
|
||
|
var len = getLength(data, p);
|
||
|
if ((len + p.place) !== data.length) {
|
||
|
return false;
|
||
|
}
|
||
|
if (data[p.place++] !== 0x02) {
|
||
|
return false;
|
||
|
}
|
||
|
var rlen = getLength(data, p);
|
||
|
var r = data.slice(p.place, rlen + p.place);
|
||
|
p.place += rlen;
|
||
|
if (data[p.place++] !== 0x02) {
|
||
|
return false;
|
||
|
}
|
||
|
var slen = getLength(data, p);
|
||
|
if (data.length !== slen + p.place) {
|
||
|
return false;
|
||
|
}
|
||
|
var s = data.slice(p.place, slen + p.place);
|
||
|
if (r[0] === 0 && (r[1] & 0x80)) {
|
||
|
r = r.slice(1);
|
||
|
}
|
||
|
if (s[0] === 0 && (s[1] & 0x80)) {
|
||
|
s = s.slice(1);
|
||
|
}
|
||
|
|
||
|
this.r = new BN(r);
|
||
|
this.s = new BN(s);
|
||
|
this.recoveryParam = null;
|
||
|
|
||
|
return true;
|
||
|
};
|
||
|
|
||
|
function constructLength(arr, len) {
|
||
|
if (len < 0x80) {
|
||
|
arr.push(len);
|
||
|
return;
|
||
|
}
|
||
|
var octets = 1 + (Math.log(len) / Math.LN2 >>> 3);
|
||
|
arr.push(octets | 0x80);
|
||
|
while (--octets) {
|
||
|
arr.push((len >>> (octets << 3)) & 0xff);
|
||
|
}
|
||
|
arr.push(len);
|
||
|
}
|
||
|
|
||
|
Signature.prototype.toDER = function toDER(enc) {
|
||
|
var r = this.r.toArray();
|
||
|
var s = this.s.toArray();
|
||
|
|
||
|
// Pad values
|
||
|
if (r[0] & 0x80)
|
||
|
r = [ 0 ].concat(r);
|
||
|
// Pad values
|
||
|
if (s[0] & 0x80)
|
||
|
s = [ 0 ].concat(s);
|
||
|
|
||
|
r = rmPadding(r);
|
||
|
s = rmPadding(s);
|
||
|
|
||
|
while (!s[0] && !(s[1] & 0x80)) {
|
||
|
s = s.slice(1);
|
||
|
}
|
||
|
var arr = [ 0x02 ];
|
||
|
constructLength(arr, r.length);
|
||
|
arr = arr.concat(r);
|
||
|
arr.push(0x02);
|
||
|
constructLength(arr, s.length);
|
||
|
var backHalf = arr.concat(s);
|
||
|
var res = [ 0x30 ];
|
||
|
constructLength(res, backHalf.length);
|
||
|
res = res.concat(backHalf);
|
||
|
return utils.encode(res, enc);
|
||
|
};
|
||
|
|
||
|
},{"../../elliptic":6,"bn.js":3}],16:[function(require,module,exports){
|
||
|
arguments[4][8][0].apply(exports,arguments)
|
||
|
},{"dup":8}],17:[function(require,module,exports){
|
||
|
module.exports = undefined;
|
||
|
},{}],18:[function(require,module,exports){
|
||
|
'use strict';
|
||
|
|
||
|
var utils = exports;
|
||
|
var BN = require('bn.js');
|
||
|
var minAssert = require('minimalistic-assert');
|
||
|
var minUtils = require('minimalistic-crypto-utils');
|
||
|
|
||
|
utils.assert = minAssert;
|
||
|
utils.toArray = minUtils.toArray;
|
||
|
utils.zero2 = minUtils.zero2;
|
||
|
utils.toHex = minUtils.toHex;
|
||
|
utils.encode = minUtils.encode;
|
||
|
|
||
|
// Represent num in a w-NAF form
|
||
|
function getNAF(num, w) {
|
||
|
var naf = [];
|
||
|
var ws = 1 << (w + 1);
|
||
|
var k = num.clone();
|
||
|
while (k.cmpn(1) >= 0) {
|
||
|
var z;
|
||
|
if (k.isOdd()) {
|
||
|
var mod = k.andln(ws - 1);
|
||
|
if (mod > (ws >> 1) - 1)
|
||
|
z = (ws >> 1) - mod;
|
||
|
else
|
||
|
z = mod;
|
||
|
k.isubn(z);
|
||
|
} else {
|
||
|
z = 0;
|
||
|
}
|
||
|
naf.push(z);
|
||
|
|
||
|
// Optimization, shift by word if possible
|
||
|
var shift = (k.cmpn(0) !== 0 && k.andln(ws - 1) === 0) ? (w + 1) : 1;
|
||
|
for (var i = 1; i < shift; i++)
|
||
|
naf.push(0);
|
||
|
k.iushrn(shift);
|
||
|
}
|
||
|
|
||
|
return naf;
|
||
|
}
|
||
|
utils.getNAF = getNAF;
|
||
|
|
||
|
// Represent k1, k2 in a Joint Sparse Form
|
||
|
function getJSF(k1, k2) {
|
||
|
var jsf = [
|
||
|
[],
|
||
|
[]
|
||
|
];
|
||
|
|
||
|
k1 = k1.clone();
|
||
|
k2 = k2.clone();
|
||
|
var d1 = 0;
|
||
|
var d2 = 0;
|
||
|
while (k1.cmpn(-d1) > 0 || k2.cmpn(-d2) > 0) {
|
||
|
|
||
|
// First phase
|
||
|
var m14 = (k1.andln(3) + d1) & 3;
|
||
|
var m24 = (k2.andln(3) + d2) & 3;
|
||
|
if (m14 === 3)
|
||
|
m14 = -1;
|
||
|
if (m24 === 3)
|
||
|
m24 = -1;
|
||
|
var u1;
|
||
|
if ((m14 & 1) === 0) {
|
||
|
u1 = 0;
|
||
|
} else {
|
||
|
var m8 = (k1.andln(7) + d1) & 7;
|
||
|
if ((m8 === 3 || m8 === 5) && m24 === 2)
|
||
|
u1 = -m14;
|
||
|
else
|
||
|
u1 = m14;
|
||
|
}
|
||
|
jsf[0].push(u1);
|
||
|
|
||
|
var u2;
|
||
|
if ((m24 & 1) === 0) {
|
||
|
u2 = 0;
|
||
|
} else {
|
||
|
var m8 = (k2.andln(7) + d2) & 7;
|
||
|
if ((m8 === 3 || m8 === 5) && m14 === 2)
|
||
|
u2 = -m24;
|
||
|
else
|
||
|
u2 = m24;
|
||
|
}
|
||
|
jsf[1].push(u2);
|
||
|
|
||
|
// Second phase
|
||
|
if (2 * d1 === u1 + 1)
|
||
|
d1 = 1 - d1;
|
||
|
if (2 * d2 === u2 + 1)
|
||
|
d2 = 1 - d2;
|
||
|
k1.iushrn(1);
|
||
|
k2.iushrn(1);
|
||
|
}
|
||
|
|
||
|
return jsf;
|
||
|
}
|
||
|
utils.getJSF = getJSF;
|
||
|
|
||
|
function cachedProperty(obj, name, computer) {
|
||
|
var key = '_' + name;
|
||
|
obj.prototype[name] = function cachedProperty() {
|
||
|
return this[key] !== undefined ? this[key] :
|
||
|
this[key] = computer.call(this);
|
||
|
};
|
||
|
}
|
||
|
utils.cachedProperty = cachedProperty;
|
||
|
|
||
|
function parseBytes(bytes) {
|
||
|
return typeof bytes === 'string' ? utils.toArray(bytes, 'hex') :
|
||
|
bytes;
|
||
|
}
|
||
|
utils.parseBytes = parseBytes;
|
||
|
|
||
|
function intFromLE(bytes) {
|
||
|
return new BN(bytes, 'hex', 'le');
|
||
|
}
|
||
|
utils.intFromLE = intFromLE;
|
||
|
|
||
|
|
||
|
},{"bn.js":3,"minimalistic-assert":28,"minimalistic-crypto-utils":29}],19:[function(require,module,exports){
|
||
|
module.exports={
|
||
|
"_args": [
|
||
|
[
|
||
|
{
|
||
|
"raw": "elliptic@^6.0.0",
|
||
|
"scope": null,
|
||
|
"escapedName": "elliptic",
|
||
|
"name": "elliptic",
|
||
|
"rawSpec": "^6.0.0",
|
||
|
"spec": ">=6.0.0 <7.0.0",
|
||
|
"type": "range"
|
||
|
},
|
||
|
"/Users/ricmoo/Development/ethers/ethers.js/node_modules/browserify-sign"
|
||
|
]
|
||
|
],
|
||
|
"_from": "elliptic@>=6.0.0 <7.0.0",
|
||
|
"_id": "elliptic@6.4.0",
|
||
|
"_inCache": true,
|
||
|
"_location": "/elliptic",
|
||
|
"_nodeVersion": "7.0.0",
|
||
|
"_npmOperationalInternal": {
|
||
|
"host": "packages-18-east.internal.npmjs.com",
|
||
|
"tmp": "tmp/elliptic-6.4.0.tgz_1487798866428_0.30510620190761983"
|
||
|
},
|
||
|
"_npmUser": {
|
||
|
"name": "indutny",
|
||
|
"email": "fedor@indutny.com"
|
||
|
},
|
||
|
"_npmVersion": "3.10.8",
|
||
|
"_phantomChildren": {},
|
||
|
"_requested": {
|
||
|
"raw": "elliptic@^6.0.0",
|
||
|
"scope": null,
|
||
|
"escapedName": "elliptic",
|
||
|
"name": "elliptic",
|
||
|
"rawSpec": "^6.0.0",
|
||
|
"spec": ">=6.0.0 <7.0.0",
|
||
|
"type": "range"
|
||
|
},
|
||
|
"_requiredBy": [
|
||
|
"/browserify-sign",
|
||
|
"/create-ecdh"
|
||
|
],
|
||
|
"_resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
|
||
|
"_shasum": "cac9af8762c85836187003c8dfe193e5e2eae5df",
|
||
|
"_shrinkwrap": null,
|
||
|
"_spec": "elliptic@^6.0.0",
|
||
|
"_where": "/Users/ricmoo/Development/ethers/ethers.js/node_modules/browserify-sign",
|
||
|
"author": {
|
||
|
"name": "Fedor Indutny",
|
||
|
"email": "fedor@indutny.com"
|
||
|
},
|
||
|
"bugs": {
|
||
|
"url": "https://github.com/indutny/elliptic/issues"
|
||
|
},
|
||
|
"dependencies": {
|
||
|
"bn.js": "^4.4.0",
|
||
|
"brorand": "^1.0.1",
|
||
|
"hash.js": "^1.0.0",
|
||
|
"hmac-drbg": "^1.0.0",
|
||
|
"inherits": "^2.0.1",
|
||
|
"minimalistic-assert": "^1.0.0",
|
||
|
"minimalistic-crypto-utils": "^1.0.0"
|
||
|
},
|
||
|
"description": "EC cryptography",
|
||
|
"devDependencies": {
|
||
|
"brfs": "^1.4.3",
|
||
|
"coveralls": "^2.11.3",
|
||
|
"grunt": "^0.4.5",
|
||
|
"grunt-browserify": "^5.0.0",
|
||
|
"grunt-cli": "^1.2.0",
|
||
|
"grunt-contrib-connect": "^1.0.0",
|
||
|
"grunt-contrib-copy": "^1.0.0",
|
||
|
"grunt-contrib-uglify": "^1.0.1",
|
||
|
"grunt-mocha-istanbul": "^3.0.1",
|
||
|
"grunt-saucelabs": "^8.6.2",
|
||
|
"istanbul": "^0.4.2",
|
||
|
"jscs": "^2.9.0",
|
||
|
"jshint": "^2.6.0",
|
||
|
"mocha": "^2.1.0"
|
||
|
},
|
||
|
"directories": {},
|
||
|
"dist": {
|
||
|
"shasum": "cac9af8762c85836187003c8dfe193e5e2eae5df",
|
||
|
"tarball": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz"
|
||
|
},
|
||
|
"files": [
|
||
|
"lib"
|
||
|
],
|
||
|
"gitHead": "6b0d2b76caae91471649c8e21f0b1d3ba0f96090",
|
||
|
"homepage": "https://github.com/indutny/elliptic",
|
||
|
"keywords": [
|
||
|
"EC",
|
||
|
"Elliptic",
|
||
|
"curve",
|
||
|
"Cryptography"
|
||
|
],
|
||
|
"license": "MIT",
|
||
|
"main": "lib/elliptic.js",
|
||
|
"maintainers": [
|
||
|
{
|
||
|
"name": "indutny",
|
||
|
"email": "fedor@indutny.com"
|
||
|
}
|
||
|
],
|
||
|
"name": "elliptic",
|
||
|
"optionalDependencies": {},
|
||
|
"readme": "ERROR: No README data found!",
|
||
|
"repository": {
|
||
|
"type": "git",
|
||
|
"url": "git+ssh://git@github.com/indutny/elliptic.git"
|
||
|
},
|
||
|
"scripts": {
|
||
|
"jscs": "jscs benchmarks/*.js lib/*.js lib/**/*.js lib/**/**/*.js test/index.js",
|
||
|
"jshint": "jscs benchmarks/*.js lib/*.js lib/**/*.js lib/**/**/*.js test/index.js",
|
||
|
"lint": "npm run jscs && npm run jshint",
|
||
|
"test": "npm run lint && npm run unit",
|
||
|
"unit": "istanbul test _mocha --reporter=spec test/index.js",
|
||
|
"version": "grunt dist && git add dist/"
|
||
|
},
|
||
|
"version": "6.4.0"
|
||
|
}
|
||
|
|
||
|
},{}],20:[function(require,module,exports){
|
||
|
var hash = exports;
|
||
|
|
||
|
hash.utils = require('./hash/utils');
|
||
|
hash.common = require('./hash/common');
|
||
|
hash.sha = require('./hash/sha');
|
||
|
hash.ripemd = require('./hash/ripemd');
|
||
|
hash.hmac = require('./hash/hmac');
|
||
|
|
||
|
// Proxy hash functions to the main object
|
||
|
hash.sha1 = hash.sha.sha1;
|
||
|
hash.sha256 = hash.sha.sha256;
|
||
|
hash.sha224 = hash.sha.sha224;
|
||
|
hash.sha384 = hash.sha.sha384;
|
||
|
hash.sha512 = hash.sha.sha512;
|
||
|
hash.ripemd160 = hash.ripemd.ripemd160;
|
||
|
|
||
|
},{"./hash/common":21,"./hash/hmac":22,"./hash/ripemd":23,"./hash/sha":24,"./hash/utils":25}],21:[function(require,module,exports){
|
||
|
var hash = require('../hash');
|
||
|
var utils = hash.utils;
|
||
|
var assert = utils.assert;
|
||
|
|
||
|
function BlockHash() {
|
||
|
this.pending = null;
|
||
|
this.pendingTotal = 0;
|
||
|
this.blockSize = this.constructor.blockSize;
|
||
|
this.outSize = this.constructor.outSize;
|
||
|
this.hmacStrength = this.constructor.hmacStrength;
|
||
|
this.padLength = this.constructor.padLength / 8;
|
||
|
this.endian = 'big';
|
||
|
|
||
|
this._delta8 = this.blockSize / 8;
|
||
|
this._delta32 = this.blockSize / 32;
|
||
|
}
|
||
|
exports.BlockHash = BlockHash;
|
||
|
|
||
|
BlockHash.prototype.update = function update(msg, enc) {
|
||
|
// Convert message to array, pad it, and join into 32bit blocks
|
||
|
msg = utils.toArray(msg, enc);
|
||
|
if (!this.pending)
|
||
|
this.pending = msg;
|
||
|
else
|
||
|
this.pending = this.pending.concat(msg);
|
||
|
this.pendingTotal += msg.length;
|
||
|
|
||
|
// Enough data, try updating
|
||
|
if (this.pending.length >= this._delta8) {
|
||
|
msg = this.pending;
|
||
|
|
||
|
// Process pending data in blocks
|
||
|
var r = msg.length % this._delta8;
|
||
|
this.pending = msg.slice(msg.length - r, msg.length);
|
||
|
if (this.pending.length === 0)
|
||
|
this.pending = null;
|
||
|
|
||
|
msg = utils.join32(msg, 0, msg.length - r, this.endian);
|
||
|
for (var i = 0; i < msg.length; i += this._delta32)
|
||
|
this._update(msg, i, i + this._delta32);
|
||
|
}
|
||
|
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
BlockHash.prototype.digest = function digest(enc) {
|
||
|
this.update(this._pad());
|
||
|
assert(this.pending === null);
|
||
|
|
||
|
return this._digest(enc);
|
||
|
};
|
||
|
|
||
|
BlockHash.prototype._pad = function pad() {
|
||
|
var len = this.pendingTotal;
|
||
|
var bytes = this._delta8;
|
||
|
var k = bytes - ((len + this.padLength) % bytes);
|
||
|
var res = new Array(k + this.padLength);
|
||
|
res[0] = 0x80;
|
||
|
for (var i = 1; i < k; i++)
|
||
|
res[i] = 0;
|
||
|
|
||
|
// Append length
|
||
|
len <<= 3;
|
||
|
if (this.endian === 'big') {
|
||
|
for (var t = 8; t < this.padLength; t++)
|
||
|
res[i++] = 0;
|
||
|
|
||
|
res[i++] = 0;
|
||
|
res[i++] = 0;
|
||
|
res[i++] = 0;
|
||
|
res[i++] = 0;
|
||
|
res[i++] = (len >>> 24) & 0xff;
|
||
|
res[i++] = (len >>> 16) & 0xff;
|
||
|
res[i++] = (len >>> 8) & 0xff;
|
||
|
res[i++] = len & 0xff;
|
||
|
} else {
|
||
|
res[i++] = len & 0xff;
|
||
|
res[i++] = (len >>> 8) & 0xff;
|
||
|
res[i++] = (len >>> 16) & 0xff;
|
||
|
res[i++] = (len >>> 24) & 0xff;
|
||
|
res[i++] = 0;
|
||
|
res[i++] = 0;
|
||
|
res[i++] = 0;
|
||
|
res[i++] = 0;
|
||
|
|
||
|
for (var t = 8; t < this.padLength; t++)
|
||
|
res[i++] = 0;
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
};
|
||
|
|
||
|
},{"../hash":20}],22:[function(require,module,exports){
|
||
|
var hmac = exports;
|
||
|
|
||
|
var hash = require('../hash');
|
||
|
var utils = hash.utils;
|
||
|
var assert = utils.assert;
|
||
|
|
||
|
function Hmac(hash, key, enc) {
|
||
|
if (!(this instanceof Hmac))
|
||
|
return new Hmac(hash, key, enc);
|
||
|
this.Hash = hash;
|
||
|
this.blockSize = hash.blockSize / 8;
|
||
|
this.outSize = hash.outSize / 8;
|
||
|
this.inner = null;
|
||
|
this.outer = null;
|
||
|
|
||
|
this._init(utils.toArray(key, enc));
|
||
|
}
|
||
|
module.exports = Hmac;
|
||
|
|
||
|
Hmac.prototype._init = function init(key) {
|
||
|
// Shorten key, if needed
|
||
|
if (key.length > this.blockSize)
|
||
|
key = new this.Hash().update(key).digest();
|
||
|
assert(key.length <= this.blockSize);
|
||
|
|
||
|
// Add padding to key
|
||
|
for (var i = key.length; i < this.blockSize; i++)
|
||
|
key.push(0);
|
||
|
|
||
|
for (var i = 0; i < key.length; i++)
|
||
|
key[i] ^= 0x36;
|
||
|
this.inner = new this.Hash().update(key);
|
||
|
|
||
|
// 0x36 ^ 0x5c = 0x6a
|
||
|
for (var i = 0; i < key.length; i++)
|
||
|
key[i] ^= 0x6a;
|
||
|
this.outer = new this.Hash().update(key);
|
||
|
};
|
||
|
|
||
|
Hmac.prototype.update = function update(msg, enc) {
|
||
|
this.inner.update(msg, enc);
|
||
|
return this;
|
||
|
};
|
||
|
|
||
|
Hmac.prototype.digest = function digest(enc) {
|
||
|
this.outer.update(this.inner.digest());
|
||
|
return this.outer.digest(enc);
|
||
|
};
|
||
|
|
||
|
},{"../hash":20}],23:[function(require,module,exports){
|
||
|
module.exports = {ripemd160: null}
|
||
|
},{}],24:[function(require,module,exports){
|
||
|
var hash = require('../hash');
|
||
|
var utils = hash.utils;
|
||
|
var assert = utils.assert;
|
||
|
|
||
|
var rotr32 = utils.rotr32;
|
||
|
var rotl32 = utils.rotl32;
|
||
|
var sum32 = utils.sum32;
|
||
|
var sum32_4 = utils.sum32_4;
|
||
|
var sum32_5 = utils.sum32_5;
|
||
|
var rotr64_hi = utils.rotr64_hi;
|
||
|
var rotr64_lo = utils.rotr64_lo;
|
||
|
var shr64_hi = utils.shr64_hi;
|
||
|
var shr64_lo = utils.shr64_lo;
|
||
|
var sum64 = utils.sum64;
|
||
|
var sum64_hi = utils.sum64_hi;
|
||
|
var sum64_lo = utils.sum64_lo;
|
||
|
var sum64_4_hi = utils.sum64_4_hi;
|
||
|
var sum64_4_lo = utils.sum64_4_lo;
|
||
|
var sum64_5_hi = utils.sum64_5_hi;
|
||
|
var sum64_5_lo = utils.sum64_5_lo;
|
||
|
var BlockHash = hash.common.BlockHash;
|
||
|
|
||
|
var sha256_K = [
|
||
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||
|
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||
|
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||
|
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||
|
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||
|
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||
|
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||
|
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||
|
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||
|
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||
|
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||
|
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||
|
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||
|
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||
|
];
|
||
|
|
||
|
var sha512_K = [
|
||
|
0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
|
||
|
0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
|
||
|
0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
|
||
|
0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
|
||
|
0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,
|
||
|
0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
|
||
|
0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,
|
||
|
0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
|
||
|
0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
|
||
|
0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
|
||
|
0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,
|
||
|
0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
|
||
|
0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,
|
||
|
0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
|
||
|
0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
|
||
|
0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
|
||
|
0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,
|
||
|
0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
|
||
|
0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,
|
||
|
0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
|
||
|
0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
|
||
|
0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
|
||
|
0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,
|
||
|
0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
|
||
|
0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,
|
||
|
0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
|
||
|
0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
|
||
|
0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
|
||
|
0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,
|
||
|
0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
|
||
|
0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,
|
||
|
0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
|
||
|
0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
|
||
|
0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
|
||
|
0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,
|
||
|
0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
|
||
|
0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,
|
||
|
0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
|
||
|
0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
|
||
|
0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
|
||
|
];
|
||
|
|
||
|
var sha1_K = [
|
||
|
0x5A827999, 0x6ED9EBA1,
|
||
|
0x8F1BBCDC, 0xCA62C1D6
|
||
|
];
|
||
|
|
||
|
function SHA256() {
|
||
|
if (!(this instanceof SHA256))
|
||
|
return new SHA256();
|
||
|
|
||
|
BlockHash.call(this);
|
||
|
this.h = [ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||
|
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ];
|
||
|
this.k = sha256_K;
|
||
|
this.W = new Array(64);
|
||
|
}
|
||
|
utils.inherits(SHA256, BlockHash);
|
||
|
exports.sha256 = SHA256;
|
||
|
|
||
|
SHA256.blockSize = 512;
|
||
|
SHA256.outSize = 256;
|
||
|
SHA256.hmacStrength = 192;
|
||
|
SHA256.padLength = 64;
|
||
|
|
||
|
SHA256.prototype._update = function _update(msg, start) {
|
||
|
var W = this.W;
|
||
|
|
||
|
for (var i = 0; i < 16; i++)
|
||
|
W[i] = msg[start + i];
|
||
|
for (; i < W.length; i++)
|
||
|
W[i] = sum32_4(g1_256(W[i - 2]), W[i - 7], g0_256(W[i - 15]), W[i - 16]);
|
||
|
|
||
|
var a = this.h[0];
|
||
|
var b = this.h[1];
|
||
|
var c = this.h[2];
|
||
|
var d = this.h[3];
|
||
|
var e = this.h[4];
|
||
|
var f = this.h[5];
|
||
|
var g = this.h[6];
|
||
|
var h = this.h[7];
|
||
|
|
||
|
assert(this.k.length === W.length);
|
||
|
for (var i = 0; i < W.length; i++) {
|
||
|
var T1 = sum32_5(h, s1_256(e), ch32(e, f, g), this.k[i], W[i]);
|
||
|
var T2 = sum32(s0_256(a), maj32(a, b, c));
|
||
|
h = g;
|
||
|
g = f;
|
||
|
f = e;
|
||
|
e = sum32(d, T1);
|
||
|
d = c;
|
||
|
c = b;
|
||
|
b = a;
|
||
|
a = sum32(T1, T2);
|
||
|
}
|
||
|
|
||
|
this.h[0] = sum32(this.h[0], a);
|
||
|
this.h[1] = sum32(this.h[1], b);
|
||
|
this.h[2] = sum32(this.h[2], c);
|
||
|
this.h[3] = sum32(this.h[3], d);
|
||
|
this.h[4] = sum32(this.h[4], e);
|
||
|
this.h[5] = sum32(this.h[5], f);
|
||
|
this.h[6] = sum32(this.h[6], g);
|
||
|
this.h[7] = sum32(this.h[7], h);
|
||
|
};
|
||
|
|
||
|
SHA256.prototype._digest = function digest(enc) {
|
||
|
if (enc === 'hex')
|
||
|
return utils.toHex32(this.h, 'big');
|
||
|
else
|
||
|
return utils.split32(this.h, 'big');
|
||
|
};
|
||
|
|
||
|
function SHA224() {
|
||
|
if (!(this instanceof SHA224))
|
||
|
return new SHA224();
|
||
|
|
||
|
SHA256.call(this);
|
||
|
this.h = [ 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
|
||
|
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 ];
|
||
|
}
|
||
|
utils.inherits(SHA224, SHA256);
|
||
|
exports.sha224 = SHA224;
|
||
|
|
||
|
SHA224.blockSize = 512;
|
||
|
SHA224.outSize = 224;
|
||
|
SHA224.hmacStrength = 192;
|
||
|
SHA224.padLength = 64;
|
||
|
|
||
|
SHA224.prototype._digest = function digest(enc) {
|
||
|
// Just truncate output
|
||
|
if (enc === 'hex')
|
||
|
return utils.toHex32(this.h.slice(0, 7), 'big');
|
||
|
else
|
||
|
return utils.split32(this.h.slice(0, 7), 'big');
|
||
|
};
|
||
|
|
||
|
function SHA512() {
|
||
|
if (!(this instanceof SHA512))
|
||
|
return new SHA512();
|
||
|
|
||
|
BlockHash.call(this);
|
||
|
this.h = [ 0x6a09e667, 0xf3bcc908,
|
||
|
0xbb67ae85, 0x84caa73b,
|
||
|
0x3c6ef372, 0xfe94f82b,
|
||
|
0xa54ff53a, 0x5f1d36f1,
|
||
|
0x510e527f, 0xade682d1,
|
||
|
0x9b05688c, 0x2b3e6c1f,
|
||
|
0x1f83d9ab, 0xfb41bd6b,
|
||
|
0x5be0cd19, 0x137e2179 ];
|
||
|
this.k = sha512_K;
|
||
|
this.W = new Array(160);
|
||
|
}
|
||
|
utils.inherits(SHA512, BlockHash);
|
||
|
exports.sha512 = SHA512;
|
||
|
|
||
|
SHA512.blockSize = 1024;
|
||
|
SHA512.outSize = 512;
|
||
|
SHA512.hmacStrength = 192;
|
||
|
SHA512.padLength = 128;
|
||
|
|
||
|
SHA512.prototype._prepareBlock = function _prepareBlock(msg, start) {
|
||
|
var W = this.W;
|
||
|
|
||
|
// 32 x 32bit words
|
||
|
for (var i = 0; i < 32; i++)
|
||
|
W[i] = msg[start + i];
|
||
|
for (; i < W.length; i += 2) {
|
||
|
var c0_hi = g1_512_hi(W[i - 4], W[i - 3]); // i - 2
|
||
|
var c0_lo = g1_512_lo(W[i - 4], W[i - 3]);
|
||
|
var c1_hi = W[i - 14]; // i - 7
|
||
|
var c1_lo = W[i - 13];
|
||
|
var c2_hi = g0_512_hi(W[i - 30], W[i - 29]); // i - 15
|
||
|
var c2_lo = g0_512_lo(W[i - 30], W[i - 29]);
|
||
|
var c3_hi = W[i - 32]; // i - 16
|
||
|
var c3_lo = W[i - 31];
|
||
|
|
||
|
W[i] = sum64_4_hi(c0_hi, c0_lo,
|
||
|
c1_hi, c1_lo,
|
||
|
c2_hi, c2_lo,
|
||
|
c3_hi, c3_lo);
|
||
|
W[i + 1] = sum64_4_lo(c0_hi, c0_lo,
|
||
|
c1_hi, c1_lo,
|
||
|
c2_hi, c2_lo,
|
||
|
c3_hi, c3_lo);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
SHA512.prototype._update = function _update(msg, start) {
|
||
|
this._prepareBlock(msg, start);
|
||
|
|
||
|
var W = this.W;
|
||
|
|
||
|
var ah = this.h[0];
|
||
|
var al = this.h[1];
|
||
|
var bh = this.h[2];
|
||
|
var bl = this.h[3];
|
||
|
var ch = this.h[4];
|
||
|
var cl = this.h[5];
|
||
|
var dh = this.h[6];
|
||
|
var dl = this.h[7];
|
||
|
var eh = this.h[8];
|
||
|
var el = this.h[9];
|
||
|
var fh = this.h[10];
|
||
|
var fl = this.h[11];
|
||
|
var gh = this.h[12];
|
||
|
var gl = this.h[13];
|
||
|
var hh = this.h[14];
|
||
|
var hl = this.h[15];
|
||
|
|
||
|
assert(this.k.length === W.length);
|
||
|
for (var i = 0; i < W.length; i += 2) {
|
||
|
var c0_hi = hh;
|
||
|
var c0_lo = hl;
|
||
|
var c1_hi = s1_512_hi(eh, el);
|
||
|
var c1_lo = s1_512_lo(eh, el);
|
||
|
var c2_hi = ch64_hi(eh, el, fh, fl, gh, gl);
|
||
|
var c2_lo = ch64_lo(eh, el, fh, fl, gh, gl);
|
||
|
var c3_hi = this.k[i];
|
||
|
var c3_lo = this.k[i + 1];
|
||
|
var c4_hi = W[i];
|
||
|
var c4_lo = W[i + 1];
|
||
|
|
||
|
var T1_hi = sum64_5_hi(c0_hi, c0_lo,
|
||
|
c1_hi, c1_lo,
|
||
|
c2_hi, c2_lo,
|
||
|
c3_hi, c3_lo,
|
||
|
c4_hi, c4_lo);
|
||
|
var T1_lo = sum64_5_lo(c0_hi, c0_lo,
|
||
|
c1_hi, c1_lo,
|
||
|
c2_hi, c2_lo,
|
||
|
c3_hi, c3_lo,
|
||
|
c4_hi, c4_lo);
|
||
|
|
||
|
var c0_hi = s0_512_hi(ah, al);
|
||
|
var c0_lo = s0_512_lo(ah, al);
|
||
|
var c1_hi = maj64_hi(ah, al, bh, bl, ch, cl);
|
||
|
var c1_lo = maj64_lo(ah, al, bh, bl, ch, cl);
|
||
|
|
||
|
var T2_hi = sum64_hi(c0_hi, c0_lo, c1_hi, c1_lo);
|
||
|
var T2_lo = sum64_lo(c0_hi, c0_lo, c1_hi, c1_lo);
|
||
|
|
||
|
hh = gh;
|
||
|
hl = gl;
|
||
|
|
||
|
gh = fh;
|
||
|
gl = fl;
|
||
|
|
||
|
fh = eh;
|
||
|
fl = el;
|
||
|
|
||
|
eh = sum64_hi(dh, dl, T1_hi, T1_lo);
|
||
|
el = sum64_lo(dl, dl, T1_hi, T1_lo);
|
||
|
|
||
|
dh = ch;
|
||
|
dl = cl;
|
||
|
|
||
|
ch = bh;
|
||
|
cl = bl;
|
||
|
|
||
|
bh = ah;
|
||
|
bl = al;
|
||
|
|
||
|
ah = sum64_hi(T1_hi, T1_lo, T2_hi, T2_lo);
|
||
|
al = sum64_lo(T1_hi, T1_lo, T2_hi, T2_lo);
|
||
|
}
|
||
|
|
||
|
sum64(this.h, 0, ah, al);
|
||
|
sum64(this.h, 2, bh, bl);
|
||
|
sum64(this.h, 4, ch, cl);
|
||
|
sum64(this.h, 6, dh, dl);
|
||
|
sum64(this.h, 8, eh, el);
|
||
|
sum64(this.h, 10, fh, fl);
|
||
|
sum64(this.h, 12, gh, gl);
|
||
|
sum64(this.h, 14, hh, hl);
|
||
|
};
|
||
|
|
||
|
SHA512.prototype._digest = function digest(enc) {
|
||
|
if (enc === 'hex')
|
||
|
return utils.toHex32(this.h, 'big');
|
||
|
else
|
||
|
return utils.split32(this.h, 'big');
|
||
|
};
|
||
|
|
||
|
function SHA384() {
|
||
|
if (!(this instanceof SHA384))
|
||
|
return new SHA384();
|
||
|
|
||
|
SHA512.call(this);
|
||
|
this.h = [ 0xcbbb9d5d, 0xc1059ed8,
|
||
|
0x629a292a, 0x367cd507,
|
||
|
0x9159015a, 0x3070dd17,
|
||
|
0x152fecd8, 0xf70e5939,
|
||
|
0x67332667, 0xffc00b31,
|
||
|
0x8eb44a87, 0x68581511,
|
||
|
0xdb0c2e0d, 0x64f98fa7,
|
||
|
0x47b5481d, 0xbefa4fa4 ];
|
||
|
}
|
||
|
utils.inherits(SHA384, SHA512);
|
||
|
exports.sha384 = SHA384;
|
||
|
|
||
|
SHA384.blockSize = 1024;
|
||
|
SHA384.outSize = 384;
|
||
|
SHA384.hmacStrength = 192;
|
||
|
SHA384.padLength = 128;
|
||
|
|
||
|
SHA384.prototype._digest = function digest(enc) {
|
||
|
if (enc === 'hex')
|
||
|
return utils.toHex32(this.h.slice(0, 12), 'big');
|
||
|
else
|
||
|
return utils.split32(this.h.slice(0, 12), 'big');
|
||
|
};
|
||
|
|
||
|
function SHA1() {
|
||
|
if (!(this instanceof SHA1))
|
||
|
return new SHA1();
|
||
|
|
||
|
BlockHash.call(this);
|
||
|
this.h = [ 0x67452301, 0xefcdab89, 0x98badcfe,
|
||
|
0x10325476, 0xc3d2e1f0 ];
|
||
|
this.W = new Array(80);
|
||
|
}
|
||
|
|
||
|
utils.inherits(SHA1, BlockHash);
|
||
|
exports.sha1 = SHA1;
|
||
|
|
||
|
SHA1.blockSize = 512;
|
||
|
SHA1.outSize = 160;
|
||
|
SHA1.hmacStrength = 80;
|
||
|
SHA1.padLength = 64;
|
||
|
|
||
|
SHA1.prototype._update = function _update(msg, start) {
|
||
|
var W = this.W;
|
||
|
|
||
|
for (var i = 0; i < 16; i++)
|
||
|
W[i] = msg[start + i];
|
||
|
|
||
|
for(; i < W.length; i++)
|
||
|
W[i] = rotl32(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
|
||
|
|
||
|
var a = this.h[0];
|
||
|
var b = this.h[1];
|
||
|
var c = this.h[2];
|
||
|
var d = this.h[3];
|
||
|
var e = this.h[4];
|
||
|
|
||
|
for (var i = 0; i < W.length; i++) {
|
||
|
var s = ~~(i / 20);
|
||
|
var t = sum32_5(rotl32(a, 5), ft_1(s, b, c, d), e, W[i], sha1_K[s]);
|
||
|
e = d;
|
||
|
d = c;
|
||
|
c = rotl32(b, 30);
|
||
|
b = a;
|
||
|
a = t;
|
||
|
}
|
||
|
|
||
|
this.h[0] = sum32(this.h[0], a);
|
||
|
this.h[1] = sum32(this.h[1], b);
|
||
|
this.h[2] = sum32(this.h[2], c);
|
||
|
this.h[3] = sum32(this.h[3], d);
|
||
|
this.h[4] = sum32(this.h[4], e);
|
||
|
};
|
||
|
|
||
|
SHA1.prototype._digest = function digest(enc) {
|
||
|
if (enc === 'hex')
|
||
|
return utils.toHex32(this.h, 'big');
|
||
|
else
|
||
|
return utils.split32(this.h, 'big');
|
||
|
};
|
||
|
|
||
|
function ch32(x, y, z) {
|
||
|
return (x & y) ^ ((~x) & z);
|
||
|
}
|
||
|
|
||
|
function maj32(x, y, z) {
|
||
|
return (x & y) ^ (x & z) ^ (y & z);
|
||
|
}
|
||
|
|
||
|
function p32(x, y, z) {
|
||
|
return x ^ y ^ z;
|
||
|
}
|
||
|
|
||
|
function s0_256(x) {
|
||
|
return rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22);
|
||
|
}
|
||
|
|
||
|
function s1_256(x) {
|
||
|
return rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25);
|
||
|
}
|
||
|
|
||
|
function g0_256(x) {
|
||
|
return rotr32(x, 7) ^ rotr32(x, 18) ^ (x >>> 3);
|
||
|
}
|
||
|
|
||
|
function g1_256(x) {
|
||
|
return rotr32(x, 17) ^ rotr32(x, 19) ^ (x >>> 10);
|
||
|
}
|
||
|
|
||
|
function ft_1(s, x, y, z) {
|
||
|
if (s === 0)
|
||
|
return ch32(x, y, z);
|
||
|
if (s === 1 || s === 3)
|
||
|
return p32(x, y, z);
|
||
|
if (s === 2)
|
||
|
return maj32(x, y, z);
|
||
|
}
|
||
|
|
||
|
function ch64_hi(xh, xl, yh, yl, zh, zl) {
|
||
|
var r = (xh & yh) ^ ((~xh) & zh);
|
||
|
if (r < 0)
|
||
|
r += 0x100000000;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
function ch64_lo(xh, xl, yh, yl, zh, zl) {
|
||
|
var r = (xl & yl) ^ ((~xl) & zl);
|
||
|
if (r < 0)
|
||
|
r += 0x100000000;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
function maj64_hi(xh, xl, yh, yl, zh, zl) {
|
||
|
var r = (xh & yh) ^ (xh & zh) ^ (yh & zh);
|
||
|
if (r < 0)
|
||
|
r += 0x100000000;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
function maj64_lo(xh, xl, yh, yl, zh, zl) {
|
||
|
var r = (xl & yl) ^ (xl & zl) ^ (yl & zl);
|
||
|
if (r < 0)
|
||
|
r += 0x100000000;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
function s0_512_hi(xh, xl) {
|
||
|
var c0_hi = rotr64_hi(xh, xl, 28);
|
||
|
var c1_hi = rotr64_hi(xl, xh, 2); // 34
|
||
|
var c2_hi = rotr64_hi(xl, xh, 7); // 39
|
||
|
|
||
|
var r = c0_hi ^ c1_hi ^ c2_hi;
|
||
|
if (r < 0)
|
||
|
r += 0x100000000;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
function s0_512_lo(xh, xl) {
|
||
|
var c0_lo = rotr64_lo(xh, xl, 28);
|
||
|
var c1_lo = rotr64_lo(xl, xh, 2); // 34
|
||
|
var c2_lo = rotr64_lo(xl, xh, 7); // 39
|
||
|
|
||
|
var r = c0_lo ^ c1_lo ^ c2_lo;
|
||
|
if (r < 0)
|
||
|
r += 0x100000000;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
function s1_512_hi(xh, xl) {
|
||
|
var c0_hi = rotr64_hi(xh, xl, 14);
|
||
|
var c1_hi = rotr64_hi(xh, xl, 18);
|
||
|
var c2_hi = rotr64_hi(xl, xh, 9); // 41
|
||
|
|
||
|
var r = c0_hi ^ c1_hi ^ c2_hi;
|
||
|
if (r < 0)
|
||
|
r += 0x100000000;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
function s1_512_lo(xh, xl) {
|
||
|
var c0_lo = rotr64_lo(xh, xl, 14);
|
||
|
var c1_lo = rotr64_lo(xh, xl, 18);
|
||
|
var c2_lo = rotr64_lo(xl, xh, 9); // 41
|
||
|
|
||
|
var r = c0_lo ^ c1_lo ^ c2_lo;
|
||
|
if (r < 0)
|
||
|
r += 0x100000000;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
function g0_512_hi(xh, xl) {
|
||
|
var c0_hi = rotr64_hi(xh, xl, 1);
|
||
|
var c1_hi = rotr64_hi(xh, xl, 8);
|
||
|
var c2_hi = shr64_hi(xh, xl, 7);
|
||
|
|
||
|
var r = c0_hi ^ c1_hi ^ c2_hi;
|
||
|
if (r < 0)
|
||
|
r += 0x100000000;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
function g0_512_lo(xh, xl) {
|
||
|
var c0_lo = rotr64_lo(xh, xl, 1);
|
||
|
var c1_lo = rotr64_lo(xh, xl, 8);
|
||
|
var c2_lo = shr64_lo(xh, xl, 7);
|
||
|
|
||
|
var r = c0_lo ^ c1_lo ^ c2_lo;
|
||
|
if (r < 0)
|
||
|
r += 0x100000000;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
function g1_512_hi(xh, xl) {
|
||
|
var c0_hi = rotr64_hi(xh, xl, 19);
|
||
|
var c1_hi = rotr64_hi(xl, xh, 29); // 61
|
||
|
var c2_hi = shr64_hi(xh, xl, 6);
|
||
|
|
||
|
var r = c0_hi ^ c1_hi ^ c2_hi;
|
||
|
if (r < 0)
|
||
|
r += 0x100000000;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
function g1_512_lo(xh, xl) {
|
||
|
var c0_lo = rotr64_lo(xh, xl, 19);
|
||
|
var c1_lo = rotr64_lo(xl, xh, 29); // 61
|
||
|
var c2_lo = shr64_lo(xh, xl, 6);
|
||
|
|
||
|
var r = c0_lo ^ c1_lo ^ c2_lo;
|
||
|
if (r < 0)
|
||
|
r += 0x100000000;
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
},{"../hash":20}],25:[function(require,module,exports){
|
||
|
var utils = exports;
|
||
|
var inherits = require('inherits');
|
||
|
|
||
|
function toArray(msg, enc) {
|
||
|
if (Array.isArray(msg))
|
||
|
return msg.slice();
|
||
|
if (!msg)
|
||
|
return [];
|
||
|
var res = [];
|
||
|
if (typeof msg === 'string') {
|
||
|
if (!enc) {
|
||
|
for (var i = 0; i < msg.length; i++) {
|
||
|
var c = msg.charCodeAt(i);
|
||
|
var hi = c >> 8;
|
||
|
var lo = c & 0xff;
|
||
|
if (hi)
|
||
|
res.push(hi, lo);
|
||
|
else
|
||
|
res.push(lo);
|
||
|
}
|
||
|
} else if (enc === 'hex') {
|
||
|
msg = msg.replace(/[^a-z0-9]+/ig, '');
|
||
|
if (msg.length % 2 !== 0)
|
||
|
msg = '0' + msg;
|
||
|
for (var i = 0; i < msg.length; i += 2)
|
||
|
res.push(parseInt(msg[i] + msg[i + 1], 16));
|
||
|
}
|
||
|
} else {
|
||
|
for (var i = 0; i < msg.length; i++)
|
||
|
res[i] = msg[i] | 0;
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
utils.toArray = toArray;
|
||
|
|
||
|
function toHex(msg) {
|
||
|
var res = '';
|
||
|
for (var i = 0; i < msg.length; i++)
|
||
|
res += zero2(msg[i].toString(16));
|
||
|
return res;
|
||
|
}
|
||
|
utils.toHex = toHex;
|
||
|
|
||
|
function htonl(w) {
|
||
|
var res = (w >>> 24) |
|
||
|
((w >>> 8) & 0xff00) |
|
||
|
((w << 8) & 0xff0000) |
|
||
|
((w & 0xff) << 24);
|
||
|
return res >>> 0;
|
||
|
}
|
||
|
utils.htonl = htonl;
|
||
|
|
||
|
function toHex32(msg, endian) {
|
||
|
var res = '';
|
||
|
for (var i = 0; i < msg.length; i++) {
|
||
|
var w = msg[i];
|
||
|
if (endian === 'little')
|
||
|
w = htonl(w);
|
||
|
res += zero8(w.toString(16));
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
utils.toHex32 = toHex32;
|
||
|
|
||
|
function zero2(word) {
|
||
|
if (word.length === 1)
|
||
|
return '0' + word;
|
||
|
else
|
||
|
return word;
|
||
|
}
|
||
|
utils.zero2 = zero2;
|
||
|
|
||
|
function zero8(word) {
|
||
|
if (word.length === 7)
|
||
|
return '0' + word;
|
||
|
else if (word.length === 6)
|
||
|
return '00' + word;
|
||
|
else if (word.length === 5)
|
||
|
return '000' + word;
|
||
|
else if (word.length === 4)
|
||
|
return '0000' + word;
|
||
|
else if (word.length === 3)
|
||
|
return '00000' + word;
|
||
|
else if (word.length === 2)
|
||
|
return '000000' + word;
|
||
|
else if (word.length === 1)
|
||
|
return '0000000' + word;
|
||
|
else
|
||
|
return word;
|
||
|
}
|
||
|
utils.zero8 = zero8;
|
||
|
|
||
|
function join32(msg, start, end, endian) {
|
||
|
var len = end - start;
|
||
|
assert(len % 4 === 0);
|
||
|
var res = new Array(len / 4);
|
||
|
for (var i = 0, k = start; i < res.length; i++, k += 4) {
|
||
|
var w;
|
||
|
if (endian === 'big')
|
||
|
w = (msg[k] << 24) | (msg[k + 1] << 16) | (msg[k + 2] << 8) | msg[k + 3];
|
||
|
else
|
||
|
w = (msg[k + 3] << 24) | (msg[k + 2] << 16) | (msg[k + 1] << 8) | msg[k];
|
||
|
res[i] = w >>> 0;
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
utils.join32 = join32;
|
||
|
|
||
|
function split32(msg, endian) {
|
||
|
var res = new Array(msg.length * 4);
|
||
|
for (var i = 0, k = 0; i < msg.length; i++, k += 4) {
|
||
|
var m = msg[i];
|
||
|
if (endian === 'big') {
|
||
|
res[k] = m >>> 24;
|
||
|
res[k + 1] = (m >>> 16) & 0xff;
|
||
|
res[k + 2] = (m >>> 8) & 0xff;
|
||
|
res[k + 3] = m & 0xff;
|
||
|
} else {
|
||
|
res[k + 3] = m >>> 24;
|
||
|
res[k + 2] = (m >>> 16) & 0xff;
|
||
|
res[k + 1] = (m >>> 8) & 0xff;
|
||
|
res[k] = m & 0xff;
|
||
|
}
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
utils.split32 = split32;
|
||
|
|
||
|
function rotr32(w, b) {
|
||
|
return (w >>> b) | (w << (32 - b));
|
||
|
}
|
||
|
utils.rotr32 = rotr32;
|
||
|
|
||
|
function rotl32(w, b) {
|
||
|
return (w << b) | (w >>> (32 - b));
|
||
|
}
|
||
|
utils.rotl32 = rotl32;
|
||
|
|
||
|
function sum32(a, b) {
|
||
|
return (a + b) >>> 0;
|
||
|
}
|
||
|
utils.sum32 = sum32;
|
||
|
|
||
|
function sum32_3(a, b, c) {
|
||
|
return (a + b + c) >>> 0;
|
||
|
}
|
||
|
utils.sum32_3 = sum32_3;
|
||
|
|
||
|
function sum32_4(a, b, c, d) {
|
||
|
return (a + b + c + d) >>> 0;
|
||
|
}
|
||
|
utils.sum32_4 = sum32_4;
|
||
|
|
||
|
function sum32_5(a, b, c, d, e) {
|
||
|
return (a + b + c + d + e) >>> 0;
|
||
|
}
|
||
|
utils.sum32_5 = sum32_5;
|
||
|
|
||
|
function assert(cond, msg) {
|
||
|
if (!cond)
|
||
|
throw new Error(msg || 'Assertion failed');
|
||
|
}
|
||
|
utils.assert = assert;
|
||
|
|
||
|
utils.inherits = inherits;
|
||
|
|
||
|
function sum64(buf, pos, ah, al) {
|
||
|
var bh = buf[pos];
|
||
|
var bl = buf[pos + 1];
|
||
|
|
||
|
var lo = (al + bl) >>> 0;
|
||
|
var hi = (lo < al ? 1 : 0) + ah + bh;
|
||
|
buf[pos] = hi >>> 0;
|
||
|
buf[pos + 1] = lo;
|
||
|
}
|
||
|
exports.sum64 = sum64;
|
||
|
|
||
|
function sum64_hi(ah, al, bh, bl) {
|
||
|
var lo = (al + bl) >>> 0;
|
||
|
var hi = (lo < al ? 1 : 0) + ah + bh;
|
||
|
return hi >>> 0;
|
||
|
};
|
||
|
exports.sum64_hi = sum64_hi;
|
||
|
|
||
|
function sum64_lo(ah, al, bh, bl) {
|
||
|
var lo = al + bl;
|
||
|
return lo >>> 0;
|
||
|
};
|
||
|
exports.sum64_lo = sum64_lo;
|
||
|
|
||
|
function sum64_4_hi(ah, al, bh, bl, ch, cl, dh, dl) {
|
||
|
var carry = 0;
|
||
|
var lo = al;
|
||
|
lo = (lo + bl) >>> 0;
|
||
|
carry += lo < al ? 1 : 0;
|
||
|
lo = (lo + cl) >>> 0;
|
||
|
carry += lo < cl ? 1 : 0;
|
||
|
lo = (lo + dl) >>> 0;
|
||
|
carry += lo < dl ? 1 : 0;
|
||
|
|
||
|
var hi = ah + bh + ch + dh + carry;
|
||
|
return hi >>> 0;
|
||
|
};
|
||
|
exports.sum64_4_hi = sum64_4_hi;
|
||
|
|
||
|
function sum64_4_lo(ah, al, bh, bl, ch, cl, dh, dl) {
|
||
|
var lo = al + bl + cl + dl;
|
||
|
return lo >>> 0;
|
||
|
};
|
||
|
exports.sum64_4_lo = sum64_4_lo;
|
||
|
|
||
|
function sum64_5_hi(ah, al, bh, bl, ch, cl, dh, dl, eh, el) {
|
||
|
var carry = 0;
|
||
|
var lo = al;
|
||
|
lo = (lo + bl) >>> 0;
|
||
|
carry += lo < al ? 1 : 0;
|
||
|
lo = (lo + cl) >>> 0;
|
||
|
carry += lo < cl ? 1 : 0;
|
||
|
lo = (lo + dl) >>> 0;
|
||
|
carry += lo < dl ? 1 : 0;
|
||
|
lo = (lo + el) >>> 0;
|
||
|
carry += lo < el ? 1 : 0;
|
||
|
|
||
|
var hi = ah + bh + ch + dh + eh + carry;
|
||
|
return hi >>> 0;
|
||
|
};
|
||
|
exports.sum64_5_hi = sum64_5_hi;
|
||
|
|
||
|
function sum64_5_lo(ah, al, bh, bl, ch, cl, dh, dl, eh, el) {
|
||
|
var lo = al + bl + cl + dl + el;
|
||
|
|
||
|
return lo >>> 0;
|
||
|
};
|
||
|
exports.sum64_5_lo = sum64_5_lo;
|
||
|
|
||
|
function rotr64_hi(ah, al, num) {
|
||
|
var r = (al << (32 - num)) | (ah >>> num);
|
||
|
return r >>> 0;
|
||
|
};
|
||
|
exports.rotr64_hi = rotr64_hi;
|
||
|
|
||
|
function rotr64_lo(ah, al, num) {
|
||
|
var r = (ah << (32 - num)) | (al >>> num);
|
||
|
return r >>> 0;
|
||
|
};
|
||
|
exports.rotr64_lo = rotr64_lo;
|
||
|
|
||
|
function shr64_hi(ah, al, num) {
|
||
|
return ah >>> num;
|
||
|
};
|
||
|
exports.shr64_hi = shr64_hi;
|
||
|
|
||
|
function shr64_lo(ah, al, num) {
|
||
|
var r = (ah << (32 - num)) | (al >>> num);
|
||
|
return r >>> 0;
|
||
|
};
|
||
|
exports.shr64_lo = shr64_lo;
|
||
|
|
||
|
},{"inherits":27}],26:[function(require,module,exports){
|
||
|
arguments[4][17][0].apply(exports,arguments)
|
||
|
},{"dup":17}],27:[function(require,module,exports){
|
||
|
if (typeof Object.create === 'function') {
|
||
|
// implementation from standard node.js 'util' module
|
||
|
module.exports = function inherits(ctor, superCtor) {
|
||
|
ctor.super_ = superCtor
|
||
|
ctor.prototype = Object.create(superCtor.prototype, {
|
||
|
constructor: {
|
||
|
value: ctor,
|
||
|
enumerable: false,
|
||
|
writable: true,
|
||
|
configurable: true
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
} else {
|
||
|
// old school shim for old browsers
|
||
|
module.exports = function inherits(ctor, superCtor) {
|
||
|
ctor.super_ = superCtor
|
||
|
var TempCtor = function () {}
|
||
|
TempCtor.prototype = superCtor.prototype
|
||
|
ctor.prototype = new TempCtor()
|
||
|
ctor.prototype.constructor = ctor
|
||
|
}
|
||
|
}
|
||
|
|
||
|
},{}],28:[function(require,module,exports){
|
||
|
module.exports = assert;
|
||
|
|
||
|
function assert(val, msg) {
|
||
|
if (!val)
|
||
|
throw new Error(msg || 'Assertion failed');
|
||
|
}
|
||
|
|
||
|
assert.equal = function assertEqual(l, r, msg) {
|
||
|
if (l != r)
|
||
|
throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r));
|
||
|
};
|
||
|
|
||
|
},{}],29:[function(require,module,exports){
|
||
|
'use strict';
|
||
|
|
||
|
var utils = exports;
|
||
|
|
||
|
function toArray(msg, enc) {
|
||
|
if (Array.isArray(msg))
|
||
|
return msg.slice();
|
||
|
if (!msg)
|
||
|
return [];
|
||
|
var res = [];
|
||
|
if (typeof msg !== 'string') {
|
||
|
for (var i = 0; i < msg.length; i++)
|
||
|
res[i] = msg[i] | 0;
|
||
|
return res;
|
||
|
}
|
||
|
if (enc === 'hex') {
|
||
|
msg = msg.replace(/[^a-z0-9]+/ig, '');
|
||
|
if (msg.length % 2 !== 0)
|
||
|
msg = '0' + msg;
|
||
|
for (var i = 0; i < msg.length; i += 2)
|
||
|
res.push(parseInt(msg[i] + msg[i + 1], 16));
|
||
|
} else {
|
||
|
for (var i = 0; i < msg.length; i++) {
|
||
|
var c = msg.charCodeAt(i);
|
||
|
var hi = c >> 8;
|
||
|
var lo = c & 0xff;
|
||
|
if (hi)
|
||
|
res.push(hi, lo);
|
||
|
else
|
||
|
res.push(lo);
|
||
|
}
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
utils.toArray = toArray;
|
||
|
|
||
|
function zero2(word) {
|
||
|
if (word.length === 1)
|
||
|
return '0' + word;
|
||
|
else
|
||
|
return word;
|
||
|
}
|
||
|
utils.zero2 = zero2;
|
||
|
|
||
|
function toHex(msg) {
|
||
|
var res = '';
|
||
|
for (var i = 0; i < msg.length; i++)
|
||
|
res += zero2(msg[i].toString(16));
|
||
|
return res;
|
||
|
}
|
||
|
utils.toHex = toHex;
|
||
|
|
||
|
utils.encode = function encode(arr, enc) {
|
||
|
if (enc === 'hex')
|
||
|
return toHex(arr);
|
||
|
else
|
||
|
return arr;
|
||
|
};
|
||
|
|
||
|
},{}],30:[function(require,module,exports){
|
||
|
/**
|
||
|
* BigNumber
|
||
|
*
|
||
|
* A wrapper around the BN.js object. In the future we can swap out
|
||
|
* the underlying BN.js library for something smaller.
|
||
|
*/
|
||
|
|
||
|
var BN = require('bn.js');
|
||
|
|
||
|
var defineProperty = require('./properties.js').defineProperty;
|
||
|
var convert = require('./convert.js');
|
||
|
|
||
|
function BigNumber(value) {
|
||
|
if (!(this instanceof BigNumber)) { throw new Error('missing new'); }
|
||
|
|
||
|
if (convert.isHexString(value)) {
|
||
|
if (value == '0x') { value = '0x0'; }
|
||
|
value = new BN(value.substring(2), 16);
|
||
|
|
||
|
} else if (typeof(value) === 'string' && value.match(/^-?[0-9]*$/)) {
|
||
|
if (value == '') { value = '0'; }
|
||
|
value = new BN(value);
|
||
|
|
||
|
} else if (typeof(value) === 'number' && parseInt(value) == value) {
|
||
|
value = new BN(value);
|
||
|
|
||
|
} else if (BN.isBN(value)) {
|
||
|
//value = value
|
||
|
|
||
|
} else if (value instanceof BigNumber) {
|
||
|
value = value._bn;
|
||
|
|
||
|
} else if (convert.isArrayish(value)) {
|
||
|
value = new BN(convert.hexlify(value).substring(2), 16);
|
||
|
|
||
|
} else {
|
||
|
throw new Error('invalid value');
|
||
|
}
|
||
|
|
||
|
defineProperty(this, '_bn', value);
|
||
|
}
|
||
|
|
||
|
defineProperty(BigNumber, 'constantNegativeOne', bigNumberify(-1));
|
||
|
defineProperty(BigNumber, 'constantZero', bigNumberify(0));
|
||
|
defineProperty(BigNumber, 'constantOne', bigNumberify(1));
|
||
|
defineProperty(BigNumber, 'constantTwo', bigNumberify(2));
|
||
|
defineProperty(BigNumber, 'constantWeiPerEther', bigNumberify(new BN('1000000000000000000')));
|
||
|
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'fromTwos', function(value) {
|
||
|
return new BigNumber(this._bn.fromTwos(value));
|
||
|
});
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'toTwos', function(value) {
|
||
|
return new BigNumber(this._bn.toTwos(value));
|
||
|
});
|
||
|
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'add', function(other) {
|
||
|
return new BigNumber(this._bn.add(bigNumberify(other)._bn));
|
||
|
});
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'sub', function(other) {
|
||
|
return new BigNumber(this._bn.sub(bigNumberify(other)._bn));
|
||
|
});
|
||
|
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'div', function(other) {
|
||
|
return new BigNumber(this._bn.div(bigNumberify(other)._bn));
|
||
|
});
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'mul', function(other) {
|
||
|
return new BigNumber(this._bn.mul(bigNumberify(other)._bn));
|
||
|
});
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'mod', function(other) {
|
||
|
return new BigNumber(this._bn.mod(bigNumberify(other)._bn));
|
||
|
});
|
||
|
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'maskn', function(value) {
|
||
|
return new BigNumber(this._bn.maskn(value));
|
||
|
});
|
||
|
|
||
|
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'eq', function(other) {
|
||
|
return this._bn.eq(bigNumberify(other)._bn);
|
||
|
});
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'lt', function(other) {
|
||
|
return this._bn.lt(bigNumberify(other)._bn);
|
||
|
});
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'lte', function(other) {
|
||
|
return this._bn.lte(bigNumberify(other)._bn);
|
||
|
});
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'gte', function(other) {
|
||
|
return this._bn.gte(bigNumberify(other)._bn);
|
||
|
});
|
||
|
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'isZero', function() {
|
||
|
return this._bn.isZero();
|
||
|
});
|
||
|
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'toNumber', function(base) {
|
||
|
return this._bn.toNumber();
|
||
|
});
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'toString', function(base) {
|
||
|
return this._bn.toString(base || 10);
|
||
|
});
|
||
|
|
||
|
defineProperty(BigNumber.prototype, 'toHexString', function() {
|
||
|
var hex = this._bn.toString(16);
|
||
|
if (hex.length % 2) { hex = '0' + hex; }
|
||
|
return '0x' + hex;
|
||
|
});
|
||
|
|
||
|
|
||
|
function isBigNumber(value) {
|
||
|
return (value instanceof BigNumber);
|
||
|
}
|
||
|
|
||
|
function bigNumberify(value, name) {
|
||
|
if (value instanceof BigNumber) { return value; }
|
||
|
|
||
|
try {
|
||
|
return new BigNumber(value);
|
||
|
|
||
|
} catch (error) {
|
||
|
console.log(error);
|
||
|
if (name) {
|
||
|
throw new Error('invalid arrayify object (' + name + ')');
|
||
|
}
|
||
|
throw new Error('invalid arrayify object');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
isBigNumber: isBigNumber,
|
||
|
bigNumberify: bigNumberify
|
||
|
};
|
||
|
|
||
|
},{"./convert.js":31,"./properties.js":42,"bn.js":33}],31:[function(require,module,exports){
|
||
|
/**
|
||
|
* Conversion Utilities
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
var defineProperty = require('./properties.js').defineProperty;
|
||
|
|
||
|
|
||
|
function isArrayish(value) {
|
||
|
if (!value || parseInt(value.length) != value.length) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
for (var i = 0; i < value.length; i++) {
|
||
|
var v = value[i];
|
||
|
if (v < 0 || v >= 256 || parseInt(v) != v) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
function arrayify(value, name) {
|
||
|
|
||
|
if (value && value.toHexString) {
|
||
|
value = value.toHexString();
|
||
|
}
|
||
|
|
||
|
if (isHexString(value)) {
|
||
|
value = value.substring(2);
|
||
|
if (value.length % 2) { value = '0' + value; }
|
||
|
|
||
|
var result = [];
|
||
|
for (var i = 0; i < value.length; i += 2) {
|
||
|
result.push(parseInt(value.substr(i, 2), 16));
|
||
|
}
|
||
|
|
||
|
return new Uint8Array(result);
|
||
|
}
|
||
|
|
||
|
if (isArrayish(value)) {
|
||
|
return new Uint8Array(value);
|
||
|
}
|
||
|
|
||
|
console.log('AA', typeof(value), value);
|
||
|
|
||
|
if (name) {
|
||
|
throw new Error('invalid arrayify object (' + name + ')');
|
||
|
}
|
||
|
throw new Error('invalid arrayify object');
|
||
|
}
|
||
|
|
||
|
function concat(objects) {
|
||
|
var arrays = [];
|
||
|
var length = 0;
|
||
|
for (var i = 0; i < objects.length; i++) {
|
||
|
var object = arrayify(objects[i])
|
||
|
arrays.push(object);
|
||
|
length += object.length;
|
||
|
}
|
||
|
|
||
|
var result = new Uint8Array(length);
|
||
|
var offset = 0;
|
||
|
for (var i = 0; i < arrays.length; i++) {
|
||
|
result.set(arrays[i], offset);
|
||
|
offset += arrays[i].length;
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
function stripZeros(value) {
|
||
|
value = arrayify(value);
|
||
|
|
||
|
if (value.length === 0) { return value; }
|
||
|
|
||
|
// Find the first non-zero entry
|
||
|
var start = 0;
|
||
|
while (value[start] === 0) { start++ }
|
||
|
|
||
|
// If we started with zeros, strip them
|
||
|
if (start) {
|
||
|
value = value.slice(start);
|
||
|
}
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
function padZeros(value, length) {
|
||
|
if (length < value.length) { throw new Error('cannot pad'); }
|
||
|
var result = new Uint8Array(length);
|
||
|
result.set(value, length - value.length);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
function isHexString(value, length) {
|
||
|
if (typeof(value) !== 'string' || !value.match(/^0x[0-9A-Fa-f]*$/)) {
|
||
|
return false
|
||
|
}
|
||
|
if (length && value.length !== 2 + 2 * length) { return false; }
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
var HexCharacters = '0123456789abcdef';
|
||
|
|
||
|
function hexlify(value, name) {
|
||
|
|
||
|
if (value && value.toHexString) {
|
||
|
return value.toHexString();
|
||
|
}
|
||
|
|
||
|
if (typeof(value) === 'number') {
|
||
|
if (value < 0) {
|
||
|
throw new Error('cannot hexlify negative value');
|
||
|
}
|
||
|
|
||
|
var hex = '';
|
||
|
while (value) {
|
||
|
hex = HexCharacters[value & 0x0f] + hex;
|
||
|
value = parseInt(value / 16);
|
||
|
}
|
||
|
|
||
|
if (hex.length) {
|
||
|
if (hex.length % 2) { hex = '0' + hex; }
|
||
|
return '0x' + hex;
|
||
|
}
|
||
|
|
||
|
return '0x00';
|
||
|
}
|
||
|
|
||
|
if (isHexString(value)) {
|
||
|
if (value.length % 2) {
|
||
|
value = '0x0' + value.substring(2);
|
||
|
}
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
if (isArrayish(value)) {
|
||
|
var result = [];
|
||
|
for (var i = 0; i < value.length; i++) {
|
||
|
var v = value[i];
|
||
|
result.push(HexCharacters[(v & 0xf0) >> 4] + HexCharacters[v & 0x0f]);
|
||
|
}
|
||
|
return '0x' + result.join('');
|
||
|
}
|
||
|
|
||
|
console.log('ERROR', typeof(value), value);
|
||
|
|
||
|
if (name) {
|
||
|
throw new Error('invalid hexlifiy value (' + name + ')');
|
||
|
}
|
||
|
throw new Error('invalid hexlify value');
|
||
|
}
|
||
|
|
||
|
|
||
|
module.exports = {
|
||
|
arrayify: arrayify,
|
||
|
isArrayish: isArrayish,
|
||
|
|
||
|
concat: concat,
|
||
|
|
||
|
padZeros: padZeros,
|
||
|
stripZeros: stripZeros,
|
||
|
|
||
|
hexlify: hexlify,
|
||
|
isHexString: isHexString,
|
||
|
};
|
||
|
|
||
|
},{"./properties.js":42}],32:[function(require,module,exports){
|
||
|
'use strict';
|
||
|
|
||
|
var hash = require('hash.js');
|
||
|
|
||
|
var convert = require('./convert.js');
|
||
|
|
||
|
// @TODO: Make this use create-hmac in node
|
||
|
|
||
|
function createSha256Hmac(key) {
|
||
|
if (!key.buffer) { key = convert.arrayify(key); }
|
||
|
return new hash.hmac(hash.sha256, key);
|
||
|
}
|
||
|
|
||
|
function createSha512Hmac(key) {
|
||
|
if (!key.buffer) { key = convert.arrayify(key); }
|
||
|
return new hash.hmac(hash.sha512, key);
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
createSha256Hmac: createSha256Hmac,
|
||
|
createSha512Hmac: createSha512Hmac,
|
||
|
};
|
||
|
|
||
|
},{"./convert.js":31,"hash.js":34}],33:[function(require,module,exports){
|
||
|
arguments[4][3][0].apply(exports,arguments)
|
||
|
},{"dup":3}],34:[function(require,module,exports){
|
||
|
arguments[4][20][0].apply(exports,arguments)
|
||
|
},{"./hash/common":35,"./hash/hmac":36,"./hash/ripemd":37,"./hash/sha":38,"./hash/utils":39,"dup":20}],35:[function(require,module,exports){
|
||
|
arguments[4][21][0].apply(exports,arguments)
|
||
|
},{"../hash":34,"dup":21}],36:[function(require,module,exports){
|
||
|
arguments[4][22][0].apply(exports,arguments)
|
||
|
},{"../hash":34,"dup":22}],37:[function(require,module,exports){
|
||
|
arguments[4][23][0].apply(exports,arguments)
|
||
|
},{"dup":23}],38:[function(require,module,exports){
|
||
|
arguments[4][24][0].apply(exports,arguments)
|
||
|
},{"../hash":34,"dup":24}],39:[function(require,module,exports){
|
||
|
arguments[4][25][0].apply(exports,arguments)
|
||
|
},{"dup":25,"inherits":40}],40:[function(require,module,exports){
|
||
|
arguments[4][27][0].apply(exports,arguments)
|
||
|
},{"dup":27}],41:[function(require,module,exports){
|
||
|
|
||
|
function pbkdf2(password, salt, iterations, keylen, createHmac) {
|
||
|
var hLen
|
||
|
var l = 1
|
||
|
var DK = new Uint8Array(keylen)
|
||
|
var block1 = new Uint8Array(salt.length + 4)
|
||
|
block1.set(salt);
|
||
|
//salt.copy(block1, 0, 0, salt.length)
|
||
|
|
||
|
var r
|
||
|
var T
|
||
|
|
||
|
for (var i = 1; i <= l; i++) {
|
||
|
//block1.writeUInt32BE(i, salt.length)
|
||
|
block1[salt.length] = (i >> 24) & 0xff;
|
||
|
block1[salt.length + 1] = (i >> 16) & 0xff;
|
||
|
block1[salt.length + 2] = (i >> 8) & 0xff;
|
||
|
block1[salt.length + 3] = i & 0xff;
|
||
|
|
||
|
var U = createHmac(password).update(block1).digest();
|
||
|
|
||
|
if (!hLen) {
|
||
|
hLen = U.length
|
||
|
T = new Uint8Array(hLen)
|
||
|
l = Math.ceil(keylen / hLen)
|
||
|
r = keylen - (l - 1) * hLen
|
||
|
}
|
||
|
|
||
|
//U.copy(T, 0, 0, hLen)
|
||
|
T.set(U);
|
||
|
|
||
|
|
||
|
for (var j = 1; j < iterations; j++) {
|
||
|
U = createHmac(password).update(U).digest()
|
||
|
for (var k = 0; k < hLen; k++) T[k] ^= U[k]
|
||
|
}
|
||
|
|
||
|
|
||
|
var destPos = (i - 1) * hLen
|
||
|
var len = (i === l ? r : hLen)
|
||
|
//T.copy(DK, destPos, 0, len)
|
||
|
DK.set(T.slice(0, len), destPos);
|
||
|
|
||
|
}
|
||
|
|
||
|
return DK
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
var hmac = require('./hmac.js');
|
||
|
var utf8 = require('./utf8.js');
|
||
|
var p = require('pbkdf2');
|
||
|
|
||
|
var pw = utf8.toUtf8Bytes('password');
|
||
|
var sa = utf8.toUtf8Bytes('salt');
|
||
|
|
||
|
var t0 = (new Date()).getTime();
|
||
|
for (var i = 0; i < 100; i++) {
|
||
|
pbkdf2(pw, sa, 1000, 40, hmac.createSha512Hmac);
|
||
|
}
|
||
|
var t1 = (new Date()).getTime();
|
||
|
for (var i = 0; i < 100; i++) {
|
||
|
p.pbkdf2Sync('password', 'salt', 1000, 40, 'sha512');
|
||
|
}
|
||
|
var t2 = (new Date()).getTime();
|
||
|
|
||
|
console.log('TT', t1 - t0, t2 - t1);
|
||
|
*/
|
||
|
module.exports = pbkdf2;
|
||
|
|
||
|
},{}],42:[function(require,module,exports){
|
||
|
function defineProperty(object, name, value) {
|
||
|
Object.defineProperty(object, name, {
|
||
|
enumerable: true,
|
||
|
value: value,
|
||
|
writable: false,
|
||
|
});
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
defineProperty: defineProperty,
|
||
|
};
|
||
|
|
||
|
},{}],43:[function(require,module,exports){
|
||
|
'use strict';
|
||
|
|
||
|
var hash = require('hash.js');
|
||
|
|
||
|
var convert = require('./convert.js');
|
||
|
|
||
|
function sha256(data) {
|
||
|
data = convert.arrayify(data);
|
||
|
return '0x' + (hash.sha256().update(data).digest('hex'));
|
||
|
}
|
||
|
|
||
|
function sha512(data) {
|
||
|
data = convert.arrayify(data);
|
||
|
return '0x' + (hash.sha512().update(data).digest('hex'));
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
sha256: sha256,
|
||
|
sha512: sha512,
|
||
|
|
||
|
createSha256: hash.sha256,
|
||
|
createSha512: hash.sha512,
|
||
|
}
|
||
|
|
||
|
},{"./convert.js":31,"hash.js":34}],44:[function(require,module,exports){
|
||
|
|
||
|
var convert = require('./convert.js');
|
||
|
|
||
|
// http://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array
|
||
|
function utf8ToBytes(str) {
|
||
|
var result = [];
|
||
|
var offset = 0;
|
||
|
for (var i = 0; i < str.length; i++) {
|
||
|
var c = str.charCodeAt(i);
|
||
|
if (c < 128) {
|
||
|
result[offset++] = c;
|
||
|
} else if (c < 2048) {
|
||
|
result[offset++] = (c >> 6) | 192;
|
||
|
result[offset++] = (c & 63) | 128;
|
||
|
} else if (((c & 0xFC00) == 0xD800) && (i + 1) < str.length && ((str.charCodeAt(i + 1) & 0xFC00) == 0xDC00)) {
|
||
|
// Surrogate Pair
|
||
|
c = 0x10000 + ((c & 0x03FF) << 10) + (str.charCodeAt(++i) & 0x03FF);
|
||
|
result[offset++] = (c >> 18) | 240;
|
||
|
result[offset++] = ((c >> 12) & 63) | 128;
|
||
|
result[offset++] = ((c >> 6) & 63) | 128;
|
||
|
result[offset++] = (c & 63) | 128;
|
||
|
} else {
|
||
|
result[offset++] = (c >> 12) | 224;
|
||
|
result[offset++] = ((c >> 6) & 63) | 128;
|
||
|
result[offset++] = (c & 63) | 128;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return convert.arrayify(result);
|
||
|
};
|
||
|
|
||
|
|
||
|
// http://stackoverflow.com/questions/13356493/decode-utf-8-with-javascript#13691499
|
||
|
function bytesToUtf8(bytes) {
|
||
|
bytes = convert.arrayify(bytes);
|
||
|
|
||
|
var result = '';
|
||
|
var i = 0;
|
||
|
|
||
|
// Invalid bytes are ignored
|
||
|
while(i < bytes.length) {
|
||
|
var c = bytes[i++];
|
||
|
if (c >> 7 == 0) {
|
||
|
// 0xxx xxxx
|
||
|
result += String.fromCharCode(c);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Invalid starting byte
|
||
|
if (c >> 6 == 0x02) { continue; }
|
||
|
|
||
|
// Multibyte; how many bytes left for thus character?
|
||
|
var extraLength = null;
|
||
|
if (c >> 5 == 0x06) {
|
||
|
extraLength = 1;
|
||
|
} else if (c >> 4 == 0x0e) {
|
||
|
extraLength = 2;
|
||
|
} else if (c >> 3 == 0x1e) {
|
||
|
extraLength = 3;
|
||
|
} else if (c >> 2 == 0x3e) {
|
||
|
extraLength = 4;
|
||
|
} else if (c >> 1 == 0x7e) {
|
||
|
extraLength = 5;
|
||
|
} else {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Do we have enough bytes in our data?
|
||
|
if (i + extraLength > bytes.length) {
|
||
|
|
||
|
// If there is an invalid unprocessed byte, try to continue
|
||
|
for (; i < bytes.length; i++) {
|
||
|
if (bytes[i] >> 6 != 0x02) { break; }
|
||
|
}
|
||
|
if (i != bytes.length) continue;
|
||
|
|
||
|
// All leftover bytes are valid.
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
// Remove the UTF-8 prefix from the char (res)
|
||
|
var res = c & ((1 << (8 - extraLength - 1)) - 1);
|
||
|
|
||
|
var count;
|
||
|
for (count = 0; count < extraLength; count++) {
|
||
|
var nextChar = bytes[i++];
|
||
|
|
||
|
// Is the char valid multibyte part?
|
||
|
if (nextChar >> 6 != 0x02) {break;};
|
||
|
res = (res << 6) | (nextChar & 0x3f);
|
||
|
}
|
||
|
|
||
|
if (count != extraLength) {
|
||
|
i--;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (res <= 0xffff) {
|
||
|
result += String.fromCharCode(res);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
res -= 0x10000;
|
||
|
result += String.fromCharCode(((res >> 10) & 0x3ff) + 0xd800, (res & 0x3ff) + 0xdc00);
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
toUtf8Bytes: utf8ToBytes,
|
||
|
toUtf8String: bytesToUtf8,
|
||
|
};
|
||
|
|
||
|
},{"./convert.js":31}]},{},[1])(1)
|
||
|
});
|