bsky-app/src/third-party/msrcrypto.js

10144 lines
276 KiB
JavaScript

// https://github.com/microsoft/MSR-JavaScript-Crypto
// version "1.6.5"
//*******************************************************************************
//
// Copyright 2020 Microsoft
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//*******************************************************************************
'use strict'
var msrCryptoVersion = '1.6.5'
;(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define([], function () {
return (root.msrCrypto = factory(root))
})
} else if (typeof exports === 'object') {
module.exports = factory(root)
} else {
root.msrCrypto = factory(root)
}
})(this, function (global) {
global = global || {}
var msrCrypto = function () {
var operations = {}
operations.register = function (
operationType,
algorithmName,
functionToCall,
) {
if (!operations[operationType]) {
operations[operationType] = {}
}
var op = operations[operationType]
if (!op[algorithmName]) {
op[algorithmName] = functionToCall
}
}
operations.exists = function (operationType, algorithmName) {
if (!operations[operationType]) {
return false
}
return operations[operationType][algorithmName] ? true : false
}
var scriptUrl = (function () {
if (typeof document !== 'undefined') {
try {
throw new Error()
} catch (e) {
if (e.stack) {
var match = /\w+:\/\/(.+?\/)*.+\.js/.exec(e.stack)
return match && match.length > 0 ? match[0] : null
}
}
} else if (
typeof self !== 'undefined' &&
typeof self.location !== 'undefined'
) {
return self.location.href
}
return null
})()
var fprngEntropyProvided = false
var webWorkerSupport = typeof Worker !== 'undefined'
var runningInWorkerInstance =
typeof importScripts === 'function' && self instanceof WorkerGlobalScope
var workerInitialized = false
var typedArraySupport = typeof ArrayBuffer !== 'undefined'
var setterSupport = (function () {
try {
Object.defineProperty({}, 'oncomplete', {})
return true
} catch (ex) {
return false
}
})()
var asyncMode = false
var createProperty = function (
parentObject,
propertyName,
initialValue,
getterFunction,
setterFunction,
) {
if (!setterSupport) {
parentObject[propertyName] = initialValue
return
}
var setGet = {}
getterFunction && (setGet.get = getterFunction)
setterFunction && (setGet.set = setterFunction)
Object.defineProperty(parentObject, propertyName, setGet)
}
var msrcryptoHashFunctions = {}
var msrcryptoUtilities = (function () {
var encodingChars =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
function consoleLog(text) {
if ('console' in self && 'log' in console) {
console.log(text)
}
}
function toBase64(data, base64Url) {
var dataType = getObjectType(data)
if (
dataType !== 'Array' &&
dataType !== 'Uint8Array' &&
dataType !== 'ArrayBuffer'
) {
throw new Error('invalid input')
}
var output = ''
var input = toArray(data)
if (!base64Url) {
base64Url = false
}
var char1, char2, char3, enc1, enc2, enc3, enc4
var i
for (i = 0; i < input.length; i += 3) {
char1 = input[i]
char2 = input[i + 1]
char3 = input[i + 2]
enc1 = char1 >> 2
enc2 = ((char1 & 0x3) << 4) | (char2 >> 4)
enc3 = ((char2 & 0xf) << 2) | (char3 >> 6)
enc4 = char3 & 0x3f
if (isNaN(char2)) {
enc3 = enc4 = 64
} else if (isNaN(char3)) {
enc4 = 64
}
output =
output +
encodingChars.charAt(enc1) +
encodingChars.charAt(enc2) +
encodingChars.charAt(enc3) +
encodingChars.charAt(enc4)
}
if (base64Url) {
return output
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/\=/g, '')
}
return output
}
function base64ToBytes(encodedString) {
encodedString = encodedString.replace(/-/g, '+').replace(/_/g, '/')
while (encodedString.length % 4 !== 0) {
encodedString += '='
}
var output = []
var char1, char2, char3
var enc1, enc2, enc3, enc4
var i
encodedString = encodedString.replace(/[^A-Za-z0-9\+\/\=]/g, '')
for (i = 0; i < encodedString.length; i += 4) {
enc1 = encodingChars.indexOf(encodedString.charAt(i))
enc2 = encodingChars.indexOf(encodedString.charAt(i + 1))
enc3 = encodingChars.indexOf(encodedString.charAt(i + 2))
enc4 = encodingChars.indexOf(encodedString.charAt(i + 3))
char1 = (enc1 << 2) | (enc2 >> 4)
char2 = ((enc2 & 15) << 4) | (enc3 >> 2)
char3 = ((enc3 & 3) << 6) | enc4
output.push(char1)
if (enc3 !== 64) {
output.push(char2)
}
if (enc4 !== 64) {
output.push(char3)
}
}
return output
}
function getObjectType(object) {
return Object.prototype.toString.call(object).slice(8, -1)
}
function bytesToHexString(bytes, separate) {
var result = ''
if (typeof separate === 'undefined') {
separate = false
}
for (var i = 0; i < bytes.length; i++) {
if (separate && i % 4 === 0 && i !== 0) {
result += '-'
}
var hexval = bytes[i].toString(16).toUpperCase()
if (hexval.length === 1) {
result += '0'
}
result += hexval
}
return result
}
function bytesToInt32(bytes, index) {
index = index || 0
return (
(bytes[index] << 24) |
(bytes[index + 1] << 16) |
(bytes[index + 2] << 8) |
bytes[index + 3]
)
}
function hexToBytesArray(hexString) {
hexString = hexString.replace(/\-/g, '')
var result = []
while (hexString.length >= 2) {
result.push(parseInt(hexString.substring(0, 2), 16))
hexString = hexString.substring(2, hexString.length)
}
return result
}
function clone(object) {
var newObject = {}
for (var propertyName in object) {
if (object.hasOwnProperty(propertyName)) {
newObject[propertyName] = object[propertyName]
}
}
return newObject
}
function unpackData(base64String, arraySize, toUint32s) {
var bytes = base64ToBytes(base64String),
data = [],
i
if (isNaN(arraySize)) {
return bytes
} else {
for (i = 0; i < bytes.length; i += arraySize) {
data.push(bytes.slice(i, i + arraySize))
}
}
if (toUint32s) {
for (i = 0; i < data.length; i++) {
data[i] =
(data[i][0] << 24) +
(data[i][1] << 16) +
(data[i][2] << 8) +
data[i][3]
}
}
return data
}
function int32ToBytes(int32) {
return [
(int32 >>> 24) & 255,
(int32 >>> 16) & 255,
(int32 >>> 8) & 255,
int32 & 255,
]
}
function int32ArrayToBytes(int32Array) {
var result = []
for (var i = 0; i < int32Array.length; i++) {
result = result.concat(int32ToBytes(int32Array[i]))
}
return result
}
function xorVectors(a, b, res) {
var length = Math.min(a.length, b.length),
res = res || new Array(length)
for (var i = 0; i < length; i += 1) {
res[i] = a[i] ^ b[i]
}
return res
}
function getVector(length, fillValue) {
if (isNaN(fillValue)) {
fillValue = 0
}
var res = new Array(length)
for (var i = 0; i < length; i += 1) {
res[i] = fillValue
}
return res
}
function toArray(typedArray) {
if (!typedArray) {
return []
}
if (typedArray.pop) {
return typedArray
}
if (getObjectType(typedArray) === 'ArrayBuffer') {
typedArray = new Uint8Array(typedArray)
} else if (typedArray.BYTES_PER_ELEMENT > 1) {
typedArray = new Uint8Array(typedArray.buffer)
}
if (typedArray.length === 1) {
return [typedArray[0]]
}
if (typedArray.length < 65536) {
return Array.apply(null, typedArray)
}
var returnArray = new Array(typedArray.length)
for (var i = 0; i < typedArray.length; i++) {
returnArray[i] = typedArray[i]
}
return returnArray
}
function padEnd(array, value, finalLength) {
while (array.length < finalLength) {
array.push(value)
}
return array
}
function padFront(array, value, finalLength) {
while (array.length < finalLength) {
array.unshift(value)
}
return array
}
function arraysEqual(array1, array2) {
var result = true
if (array1.length !== array2.length) {
result = false
}
for (var i = 0; i < array1.length; i++) {
if (array1[i] !== array2[i]) {
result = false
}
}
return result
}
function verifyByteArray(array) {
if (getObjectType(array) !== 'Array') {
return false
}
var element
for (var i = 0; i < array.length; i++) {
element = array[i]
if (isNaN(element) || element < 0 || element > 255) {
return false
}
}
return true
}
function checkParam(param, type, errorMessage) {
if (!param) {
throw new Error(errorMessage)
}
if (type && getObjectType(param) !== type) {
throw new Error(errorMessage)
}
return true
}
function stringToBytes(text) {
var encodedBytes = []
for (var i = 0, j = 0; i < text.length; i++) {
var charCode = text.charCodeAt(i)
if (charCode < 128) {
encodedBytes[j++] = charCode
} else if (charCode < 2048) {
encodedBytes[j++] = (charCode >>> 6) | 192
encodedBytes[j++] = (charCode & 63) | 128
} else if (charCode < 0xd800 || charCode > 0xdfff) {
encodedBytes[j++] = (charCode >>> 12) | 224
encodedBytes[j++] = ((charCode >>> 6) & 63) | 128
encodedBytes[j++] = (charCode & 63) | 128
} else {
charCode =
(charCode - 0xd800) * 0x400 +
(text.charCodeAt(++i) - 0xdc00) +
0x10000
encodedBytes[j++] = (charCode >>> 18) | 240
encodedBytes[j++] = ((charCode >>> 12) & 63) | 128
encodedBytes[j++] = ((charCode >>> 6) & 63) | 128
encodedBytes[j++] = (charCode & 63) | 128
}
}
return encodedBytes
}
function bytesToString(textBytes) {
var result = '',
charCode
textBytes = toArray(textBytes)
for (var i = 0; i < textBytes.length; ) {
var encodedChar = textBytes[i++]
if (encodedChar < 128) {
charCode = encodedChar
} else if (encodedChar < 224) {
charCode = (encodedChar << 6) + textBytes[i++] - 0x3080
} else if (encodedChar < 240) {
charCode =
(encodedChar << 12) +
(textBytes[i++] << 6) +
textBytes[i++] -
0xe2080
} else {
charCode =
(encodedChar << 18) +
(textBytes[i++] << 12) +
(textBytes[i++] << 6) +
textBytes[i++] -
0x3c82080
}
if (charCode > 0xffff) {
var surrogateHigh =
Math.floor((charCode - 0x10000) / 0x400) + 0xd800
var surrogateLow = ((charCode - 0x10000) % 0x400) + 0xdc00
result += String.fromCharCode(surrogateHigh, surrogateLow)
continue
}
result += String.fromCharCode(charCode)
}
return result
}
return {
consoleLog: consoleLog,
toBase64: toBase64,
fromBase64: base64ToBytes,
checkParam: checkParam,
getObjectType: getObjectType,
bytesToHexString: bytesToHexString,
bytesToInt32: bytesToInt32,
stringToBytes: stringToBytes,
bytesToString: bytesToString,
unpackData: unpackData,
hexToBytesArray: hexToBytesArray,
int32ToBytes: int32ToBytes,
int32ArrayToBytes: int32ArrayToBytes,
toArray: toArray,
arraysEqual: arraysEqual,
clone: clone,
xorVectors: xorVectors,
padEnd: padEnd,
padFront: padFront,
getVector: getVector,
verifyByteArray: verifyByteArray,
}
})()
var asn1 = (function () {
var asn1Types = {
0x00: 'CUSTOM',
0x01: 'BOOLEAN',
0x02: 'INTEGER',
0x03: 'BIT STRING',
0x04: 'OCTET STRING',
0x05: 'NULL',
0x06: 'OBJECT IDENTIFIER',
0x10: 'SEQUENCE',
0x11: 'SET',
0x13: 'PRINTABLE STRING',
0x17: 'UTCTime',
}
var asn1Classes = {
0x00: 'UNIVERSAL',
0x01: 'APPLICATION',
0x02: 'Context-Defined',
0x03: 'PRIVATE',
}
function parse(bytes, force) {
force = !!force
var type = asn1Types[bytes[0] & 0x1f],
dataLen = bytes[1],
i = 0,
constructed = !!(bytes[0] & 0x20),
remainder,
child,
header
if (dataLen & 0x80) {
for (i = 0, dataLen = 0; i < (bytes[1] & 127); i++) {
dataLen = (dataLen << 8) + bytes[2 + i]
}
}
header = 2 + i
if (type === undefined || dataLen > bytes.length) {
return null
}
var obj = constructed ? [] : {}
obj.type = type
obj.header = header
obj.data = bytes.slice(0, dataLen + header)
if (constructed || force) {
if (obj.type === 'BIT STRING' && bytes[header] === 0) {
i++
}
remainder = bytes.slice(header, obj.data.length)
while (remainder.length > 0) {
child = parse(remainder)
if (child === null) {
break
}
obj.push(child)
remainder = remainder.slice(child.data.length)
}
}
return obj
}
function encode(asn1tree) {
throw new Error('not implemented')
}
function toString(objTree, indent) {
var output =
new Array(indent + 1).join(' ') +
objTree.type +
' (' +
objTree.length +
') ' +
bytesToHexString(objTree.data).substring(0, 16) +
'\n'
if (!objTree.children) {
return output
}
for (var i = 0; i < objTree.children.length; i++) {
output += toString(objTree.children[i], indent + 4) + ''
}
return output
}
return {
parse: parse,
encode: encode,
toString: function (objTree) {
return toString(objTree, 0)
},
}
})()
var msrcryptoWorker = (function () {
function returnResult(result) {
if (workerInitialized && runningInWorkerInstance) {
self.postMessage(result)
}
return result
}
var workerId, operationType, operationSubType
return {
jsCryptoRunner: function (e) {
workerId = e.data.workerid
operationType = e.data.operationType
operationSubType = e.data.operationSubType
var operation = e.data.operationType,
result,
func = operations[operation][e.data.algorithm.name],
p = e.data
if (!operations.exists(operation, e.data.algorithm.name)) {
throw new Error('unregistered algorithm.')
}
if (p.operationSubType) {
result = returnResult({
type: p.operationSubType,
result: func(p),
})
} else {
result = returnResult(func(p))
}
return result
},
returnResult: returnResult,
}
})()
if (runningInWorkerInstance) {
self.onmessage = function (e) {
if (!workerInitialized && e.data.prngSeed) {
var entropy = e.data.prngSeed
msrcryptoPseudoRandom.init(entropy)
workerInitialized = true
return msrcryptoWorker.returnResult({
initialized: true,
})
}
if (workerInitialized === true) {
msrcryptoWorker.jsCryptoRunner(e)
}
}
}
var msrcryptoJwk = (function () {
var utils = msrcryptoUtilities
function stringToArray(stringData) {
var result = []
for (var i = 0; i < stringData.length; i++) {
result[i] = stringData.charCodeAt(i)
}
if (result[result.length - 1] === 0) {
result.pop()
}
return result
}
function getKeyType(keyHandle) {
var algType = keyHandle.algorithm.name.slice(0, 3).toUpperCase()
if (algType === 'RSA') {
return 'RSA'
}
if (algType === 'ECD') {
return 'EC'
}
return 'oct'
}
function hashSize(algorithm) {
return algorithm.hash.name.substring(
algorithm.hash.name.indexOf('-') + 1,
)
}
var algorithmMap = {
HMAC: function (algorithm) {
return 'HS' + hashSize(algorithm)
},
'AES-CBC': function (algorithm) {
return 'A' + algorithm.length.toString() + 'CBC'
},
'AES-GCM': function (algorithm) {
return 'A' + algorithm.length.toString() + 'GCM'
},
'RSAES-PKCS1-V1_5': function (algorithm) {
return 'RSA1_5'
},
'RSASSA-PKCS1-V1_5': function (algorithm) {
return 'RS' + hashSize(algorithm)
},
'RSA-OAEP': function (algorithm) {
if (algorithm.hash.name.toUpperCase() === 'SHA-1') {
return 'RSA-OAEP'
}
return 'RSA-OAEP-' + hashSize(algorithm)
},
'RSA-PSS': function (algorithm) {
return 'PS' + hashSize(algorithm)
},
ECDSA: function (algorithm) {
return (
'EC-' +
algorithm.namedCurve.substring(
algorithm.namedCurve.indexOf('-') + 1,
)
)
},
}
function keyToJwk(keyHandle, keyData) {
var key = {}
key.kty = getKeyType(keyHandle)
key.ext = keyHandle.extractable
if (algorithmMap[keyHandle.algorithm.name.toUpperCase()]) {
key.alg = algorithmMap[keyHandle.algorithm.name.toUpperCase()](
keyHandle.algorithm,
)
}
key.key_ops = keyHandle.usages
if (keyData.pop) {
key.k = utils.toBase64(keyData, true)
} else {
for (var property in keyData) {
if (keyData[property].pop && property !== 'key_ops') {
key[property] = utils.toBase64(keyData[property], true)
}
}
}
if (keyHandle.algorithm.namedCurve) {
key.crv = keyHandle.algorithm.namedCurve
}
return key
}
function findUsage(usage, usages) {
for (var i = 0; i < usages.length; i++) {
if (usage.toUpperCase() === usages[i].toUpperCase()) {
return true
}
}
return false
}
function keyToJwkOld(keyHandle, keyData) {
var key = {}
key.kty = getKeyType(keyHandle)
key.extractable = keyHandle.extractable
if (keyData.pop) {
key.k = utils.toBase64(keyData, true)
} else {
for (var property in keyData) {
if (keyData[property].pop) {
key[property] = utils.toBase64(keyData[property], true)
}
}
}
if (keyHandle.algorithm.namedCurve) {
key.crv = keyHandle.algorithm.namedCurve
}
var stringData = JSON.stringify(key, null, '\t')
return stringToArray(stringData)
}
function jwkToKey(keyData, algorithm, propsToArray) {
var jsonKeyObject = JSON.parse(JSON.stringify(keyData))
for (var i = 0; i < propsToArray.length; i += 1) {
var propValue = jsonKeyObject[propsToArray[i]]
if (propValue) {
jsonKeyObject[propsToArray[i]] = utils.fromBase64(propValue)
}
}
return jsonKeyObject
}
return {
keyToJwkOld: keyToJwkOld,
keyToJwk: keyToJwk,
jwkToKey: jwkToKey,
}
})()
function msrcryptoMath() {
var DIGIT_BITS = 24
var DIGIT_NUM_BYTES = Math.floor(DIGIT_BITS / 8)
var DIGIT_MASK = (1 << DIGIT_BITS) - 1
var DIGIT_BASE = 1 << DIGIT_BITS
var DIGIT_MAX = DIGIT_MASK
var DIG_INV = 1 / DIGIT_BASE
var DIGIT_MAX_ADDS = 31
var DIGIT_SCALER = [1, 256]
for (var ds = 2; ds <= DIGIT_NUM_BYTES; ds++) {
DIGIT_SCALER[ds] = DIGIT_SCALER[ds - 1] * 256
}
var Zero = [0]
var One = [1]
function createArray(parameter) {
var i,
array = null
if (!arguments.length || typeof arguments[0] === 'number') {
array = new Array(parameter)
for (i = 0; i < parameter; i += 1) {
array[i] = 0
}
} else if (typeof arguments[0] === 'object') {
array = new Array(parameter.length)
for (i = 0; i < parameter.length; i += 1) {
array[i] = parameter[i]
}
}
return array
}
function stringToDigits(numberStr, radix) {
numberStr = numberStr.replace(/^\s+|\s+$/g, '')
var num = [0]
var buffer = [0]
radix = radix || 10
for (var i = 0; i < numberStr.length; i += 1) {
var char = parseInt(numberStr[i], radix)
if (isNaN(char)) {
throw new Error(
'Failed to convert string to integer in radix ' +
radix.toString(),
)
}
multiply(num, radix, buffer)
add(buffer, [char], num)
normalizeDigitArray(num)
}
return num
}
function digitsToString(digits, radix) {
radix = radix || 10
if (DIGIT_BASE <= radix) {
throw new Error('DIGIT_BASE is smaller than RADIX; cannot convert.')
}
var wordLength = digits.length
var quotient = []
var remainder = []
var temp1 = []
var temp2 = []
var divisor = []
var a = []
var i
var sb = ''
var pad = '0'
divisor[0] = radix
while (Math.floor(DIGIT_BASE / divisor[0]) >= radix) {
divisor[0] = divisor[0] * radix
pad = pad.concat('0')
}
for (i = 0; i < wordLength; i += 1) {
a[i] = digits[i]
}
do {
var allZeros = true
for (i = 0; i < a.length; i += 1) {
if (a[i] !== 0) {
allZeros = false
break
}
}
if (allZeros) {
break
}
divRem(a, divisor, quotient, remainder, temp1, temp2)
normalizeDigitArray(quotient, a.length, true)
var newDigits = remainder[0].toString(radix)
sb = pad.substring(0, pad.length - newDigits.length) + newDigits + sb
var swap = a
a = quotient
quotient = swap
} while (true)
while (sb.length !== 0 && sb[0] === '0') {
sb = sb.substring(1, sb.length)
}
if (sb.length === 0) {
sb = '0'
}
return sb
}
function computeBitArray(bytes) {
var out = createArray(bytes.length * 8)
var bitLength = 0
var i = bytes.length - 1
while (i >= 0) {
var j = 0
while (j < 8) {
var mask = 1 << j
var bit = (bytes[i] & mask) === mask ? 1 : 0
var thisBitIndex = 8 * (bytes.length - i - 1) + j
if (bit === 1) {
bitLength = thisBitIndex + 1
}
out[thisBitIndex] = bit
j += 1
}
i--
}
return out.slice(0, bitLength)
}
function bitScanForward(digit) {
var index = 0
for (var i = 0; i < DIGIT_BITS; i++) {
index = Math.max(index, -((digit >>> i) & 1) & i)
}
return index
}
function highestSetBit(bytes) {
var i = 0
var bitLength = 0
while (i < bytes.length) {
if (bitLength === 0) {
var j = 7
while (j >= 0 && bitLength === 0) {
var mask = 1 << j
if ((bytes[i] & mask) === mask) {
bitLength = j + 1
}
j--
}
} else {
bitLength += 8
}
i += 1
}
return bitLength
}
function fixedWindowRecode(digits, windowSize, t) {
digits = digits.slice()
var recodedDigits = [],
windowSizeBits = Math.pow(2, windowSize),
windowSizeMinus1Bits = Math.pow(2, windowSize - 1)
for (var i = 0; i < t; i++) {
recodedDigits[i] = (digits[0] % windowSizeBits) - windowSizeMinus1Bits
digits[0] = digits[0] - recodedDigits[i]
cryptoMath.shiftRight(digits, digits, windowSize - 1)
}
recodedDigits[i] = digits[0]
return recodedDigits
}
function fixedWindowRecode2(digits, windowSize) {
var digLen = digits.length,
bits = new Array(digLen * DIGIT_BITS),
i = 0,
j = 0,
k = 0,
r = 0,
dig,
result = new Array(Math.ceil((digLen * DIGIT_BITS) / windowSize))
for (k = 0, result[0] = 0; i < digLen; i++) {
for (j = 0, dig = digits[i]; j < DIGIT_BITS; j++, dig >>>= 1) {
if (k === windowSize) {
result[++r] = 0
k = 0
}
result[r] += (dig & 1) << k++
}
}
return result
}
function fetchBits(digits, startBit, count) {
var startDigit = Math.floor(startBit / cryptoMath.DIGIT_BITS)
var endDigit = startDigit + 1
var shiftRight = startBit % cryptoMath.DIGIT_BITS
var shiftLeft = cryptoMath.DIGIT_BITS - shiftRight
var bits =
(digits[startDigit] >>> shiftRight) | (digits[endDigit] << shiftLeft)
return (
bits & (cryptoMath.DIGIT_MASK >>> (cryptoMath.DIGIT_BITS - count))
)
}
function fetchBits2(digits, startBit, count) {
var startDigit = Math.floor(startBit / DIGIT_BITS),
shiftRight = startBit % DIGIT_BITS
return (
(digits[startDigit] >>> shiftRight) |
((digits[startDigit + 1] << (DIGIT_BITS - shiftRight)) &
(DIGIT_MASK >>> (DIGIT_BITS - count)))
)
}
function copyArray(source, sourceIndex, destination, destIndex, length) {
while (length-- > 0) {
destination[destIndex + length] = source[sourceIndex + length]
}
}
function isZero(array) {
var i,
result = 0
for (i = 0; i < array.length; i += 1) {
result = result | array[i]
}
return !result
}
function isEven(array) {
return (array[0] & 0x1) === 0x0
}
function sequenceEqual(left, right) {
var equal = left.length === right.length
for (var i = 0; i < Math.min(left.length, right.length); i += 1) {
if (left[i] !== right[i]) {
equal = false
}
}
return equal
}
function bytesToDigits(bytes) {
var arrayLength = Math.floor(
(bytes.length + DIGIT_NUM_BYTES - 1) / DIGIT_NUM_BYTES,
)
var array = new Array(arrayLength)
array[0] = 0
var digit = 0,
index = 0,
scIndex = 0
for (var i = bytes.length - 1; i >= 0; i--) {
digit = digit + DIGIT_SCALER[scIndex++] * (bytes[i] & 0x0ff)
if (DIGIT_SCALER[scIndex] === DIGIT_BASE) {
scIndex = 0
array[index++] = digit
digit = 0
}
}
if (digit !== 0) {
array[index] = digit
}
while (array[--arrayLength] == null) {
array[arrayLength] = 0
}
return array
}
function digitsToBytes(digits, trim, minTrimLength) {
var i, j, byte1
var bytes = [0]
if (typeof trim === 'undefined') {
trim = true
}
for (i = 0; i < digits.length; i += 1) {
byte1 = digits[i]
for (j = 0; j < DIGIT_NUM_BYTES; j += 1) {
bytes[i * DIGIT_NUM_BYTES + j] = byte1 & 0x0ff
byte1 = Math.floor(byte1 / 256)
}
}
bytes.reverse()
if (minTrimLength === undefined) {
minTrimLength = 1
}
if (trim) {
while (bytes.length > minTrimLength && bytes[0] === 0) {
bytes.shift()
}
}
return bytes
}
function intToDigits(value, numDigits) {
if (typeof numDigits === 'undefined') {
if (value <= 1) {
numDigits = 1
} else {
var numBits = Math.log(value) / Math.LN2
numDigits = Math.ceil(numBits / DIGIT_BITS)
}
}
var digitRepresentation = []
while (value > 0) {
digitRepresentation.push(value % DIGIT_BASE)
value = Math.floor(value / DIGIT_BASE)
}
while (digitRepresentation.length < numDigits) {
digitRepresentation.push(0)
}
return digitRepresentation
}
function mswIndex(digits) {
for (var i = digits.length - 1; i >= 0; i--) {
if (digits[i] !== undefined && digits[i] !== 0) {
return i
}
}
return digits[0] === 0 ? -1 : 0
}
function compareDigits(left, right) {
var result = 0,
val,
i
for (i = 0; i < Math.max(left.length, right.length); i++) {
val = ~~left[i] - ~~right[i]
result = val + (result & -!val)
}
return result
}
function normalizeDigitArray(digits, length, pad) {
var i = mswIndex(digits)
digits.length = length || i + 1
if (pad) {
while (++i < digits.length) {
digits[i] = 0
}
}
if (digits.length <= 0) {
digits[0] = 0
digits.length = 1
}
return digits
}
function shiftRight(source, destination, bits, length) {
if (bits === undefined) {
bits = 1
} else if (bits >= DIGIT_BITS || bits < 0) {
throw new Error('Invalid bit count for shiftRight')
}
if (length === undefined) {
length = source.length
}
var n = length - 1
var leftShiftBitCount = DIGIT_BITS - bits
for (var i = 0; i < n; i++) {
destination[i] =
((source[i + 1] << leftShiftBitCount) | (source[i] >>> bits)) &
DIGIT_MASK
}
destination[n] = source[n] >>> bits
}
function shiftLeft(source, destination, bits, length) {
if (bits === undefined) {
bits = 1
} else if (bits >= DIGIT_BITS || bits < 0) {
throw new Error(
'bit count must be smaller than DIGIT_BITS and positive in shiftLeft',
)
}
if (length === undefined) {
length = source.length
}
var rightShiftBitCount = DIGIT_BITS - bits
destination[length] =
source[length - 1] >>> (DIGIT_BITS - bits) || destination[length]
for (var i = length - 1; i > 0; i--) {
destination[i] =
((source[i] << bits) | (source[i - 1] >>> rightShiftBitCount)) &
DIGIT_MASK
}
destination[0] = (source[0] << bits) & DIGIT_MASK
}
function add(addend1, addend2, sum) {
var shortArray = addend1
var longArray = addend2
if (addend2.length < addend1.length) {
shortArray = addend2
longArray = addend1
}
var s = shortArray.length
var carry = 0
var i
for (i = 0; i < s; i += 1) {
carry += shortArray[i] + longArray[i]
sum[i] = carry & DIGIT_MASK
carry = carry >> DIGIT_BITS
}
for (i = s; i < longArray.length; i += 1) {
carry += longArray[i]
sum[i] = carry & DIGIT_MASK
carry = carry >> DIGIT_BITS
}
sum.length = longArray.length
if (carry !== 0) {
sum[i] = carry & DIGIT_MASK
}
return carry
}
function subtract(minuend, subtrahend, difference) {
var s = subtrahend.length
if (minuend.length < subtrahend.length) {
s = mswIndex(subtrahend) + 1
if (minuend.length < s) {
throw new Error('Subtrahend is longer than minuend, not supported.')
}
}
var i,
carry = 0
for (i = 0; i < s; i += 1) {
carry += minuend[i] - subtrahend[i]
difference[i] = carry & DIGIT_MASK
carry = carry >> DIGIT_BITS
}
while (i < minuend.length) {
carry += minuend[i]
difference[i++] = carry & DIGIT_MASK
carry = carry >> DIGIT_BITS
}
return carry
}
function multiply(a, b, p) {
b = typeof b === 'number' ? [b] : b
var i,
j,
k,
l,
c,
t1,
t2,
alen = a.length,
blen = b.length,
bi
for (i = 0; i < alen + blen; i += 1) {
p[i] = 0
}
i = 0
l = 0
var maxRounds = 31
var ks = 0
while (i < blen) {
l = Math.min(l + maxRounds, blen)
for (; i < l; i++) {
bi = b[i]
for (j = 0; j < alen; j++) {
p[i + j] += a[j] * bi
}
}
c = 0
for (k = ks; k < i + alen; k++) {
t1 = p[k] + c
t2 = t1 & DIGIT_MASK
p[k] = t2
c = (t1 - t2) * DIG_INV
}
p[k] = c
ks += maxRounds
}
p.length = alen + blen
return p
}
function divRem(dividend, divisor, quotient, remainder, temp1, temp2) {
var m = mswIndex(dividend) + 1
var n = mswIndex(divisor) + 1
var qhat, rhat, carry, p, t, i, j
if (m < n) {
copyArray(dividend, 0, remainder, 0, dividend.length)
remainder.length = dividend.length
normalizeDigitArray(remainder)
quotient[0] = 0
quotient.length = 1
return
} else if (n === 0 || (n === 1 && divisor[n - 1] === 0)) {
throw new Error('Division by zero.')
} else if (n === 1) {
t = divisor[0]
rhat = 0
for (j = m - 1; j >= 0; j--) {
p = rhat * DIGIT_BASE + dividend[j]
quotient[j] = (p / t) & DIGIT_MASK
rhat = (p - quotient[j] * t) & DIGIT_MASK
}
quotient.length = m
normalizeDigitArray(quotient)
remainder[0] = rhat
remainder.length = 1
return
}
var s = DIGIT_BITS - 1 - bitScanForward(divisor[n - 1])
var vn = temp1 || []
vn.length = n
shiftLeft(divisor, vn, s, n)
var un = temp2 || []
un.length = m
shiftLeft(dividend, un, s, m)
un[m] = un[m] || 0
quotient.length = m - n + 1
remainder.length = n
for (j = m - n; j >= 0; j--) {
qhat = Math.floor(
(un[j + n] * DIGIT_BASE + un[j + n - 1]) / vn[n - 1],
)
rhat = un[j + n] * DIGIT_BASE + un[j + n - 1] - qhat * vn[n - 1]
while (true) {
if (
qhat >= DIGIT_BASE ||
qhat * vn[n - 2] > rhat * DIGIT_BASE + un[j + n - 2]
) {
qhat = qhat - 1
rhat = rhat + vn[n - 1]
if (rhat < DIGIT_BASE) {
continue
}
}
break
}
carry = 0
for (i = 0; i < n; i++) {
p = qhat * vn[i]
t = un[i + j] - carry - (p & DIGIT_MASK)
un[i + j] = t & DIGIT_MASK
carry = Math.floor(p / DIGIT_BASE) - Math.floor(t / DIGIT_BASE)
}
t = un[j + n] - carry
un[j + n] = t & DIGIT_MASK
quotient[j] = qhat & DIGIT_MASK
if (t < 0) {
quotient[j] = quotient[j] - 1
carry = 0
for (i = 0; i < n; i++) {
t = un[i + j] + vn[i] + carry
un[i + j] = t & DIGIT_MASK
carry = t >> DIGIT_BITS
}
un[j + n] = (un[j + n] + carry) & DIGIT_MASK
}
}
for (i = 0; i < n; i++) {
remainder[i] =
((un[i] >>> s) | (un[i + 1] << (DIGIT_BITS - s))) & DIGIT_MASK
}
normalizeDigitArray(quotient)
normalizeDigitArray(remainder)
}
function reduce(number, modulus, remainder, temp1, temp2) {
var quotient = []
divRem(number, modulus, quotient, remainder, temp1, temp2)
return remainder
}
function modMul(
multiplicand,
multiplier,
modulus,
product,
temp1,
temp2,
) {
var quotient = []
multiply(multiplicand, multiplier, quotient)
divRem(quotient, modulus, quotient, product, temp1, temp2)
return product
}
function eea(a, b, upp, vpp, rpp) {
var rp
if (isZero(a)) {
copyArray(b, 0, rpp, 0, b.length)
rpp.length = b.length
return 0
} else if (isZero(b)) {
copyArray(a, 0, rpp, 0, a.length)
rpp.length = a.length
return 0
} else if (compareDigits(a, b) < 0) {
rp = a.slice(0)
copyArray(b, 0, rpp, 0, b.length)
rpp.length = b.length
} else {
rp = b.slice(0)
copyArray(a, 0, rpp, 0, a.length)
rpp.length = a.length
}
normalizeDigitArray(rpp)
normalizeDigitArray(rp)
var q = new Array(rpp.length)
var r = new Array(rpp.length)
var v = new Array(rpp.length)
var vppPresent = vpp !== undefined
var vp
if (vppPresent) {
vp = new Array(rpp.length)
vp[0] = 1
vp.length = 1
vpp[0] = 0
vpp.length = 1
}
var up
var u = new Array(rpp.length)
var uppPresent = upp !== undefined
if (uppPresent) {
up = new Array(rpp.length)
up[0] = 0
up.length = 1
upp[0] = 1
upp.length = 1
}
var k = -1
var upp_out = upp
var vpp_out = vpp
var rpp_out = rpp
var save
while (!isZero(rp)) {
divRem(rpp, rp, q, r, u, v)
if (uppPresent) {
multiply(q, up, u)
add(u, upp, u)
normalizeDigitArray(u)
save = upp
upp = up
up = u
u = save
}
if (vppPresent) {
multiply(q, vp, v)
add(v, vpp, v)
normalizeDigitArray(v)
save = vpp
vpp = vp
vp = v
v = save
}
save = rpp
rpp = rp
rp = r
r = save
k++
}
if (uppPresent) {
copyArray(upp, 0, upp_out, 0, upp.length)
upp_out.length = upp.length
}
if (vppPresent) {
copyArray(vpp, 0, vpp_out, 0, vpp.length)
vpp_out.length = vpp.length
}
copyArray(rpp, 0, rpp_out, 0, rpp.length)
rpp_out.length = rpp.length
return k
}
function gcd(a, b, output) {
var aa = a
var bb = b
if (compareDigits(a, b) > 0) {
aa = b
bb = a
}
eea(aa, bb, undefined, undefined, output)
return normalizeDigitArray(output)
}
function modInv(a, n, aInv, pad) {
var upp = new Array(n.length)
var vpp = new Array(n.length)
var rpp = new Array(n.length)
var k = eea(a, n, vpp, upp, rpp)
aInv = aInv || []
if (compareDigits(rpp, One) !== 0) {
aInv[0] = NaN
aInv.length = 1
} else {
if ((k & 1) === 1) {
subtract(n, upp, aInv)
} else {
copyArray(upp, 0, aInv, 0, upp.length)
aInv.length = upp.length
}
if (pad) {
normalizeDigitArray(aInv, n.length, true)
} else {
normalizeDigitArray(aInv)
}
}
return aInv
}
function modInvCT(a, n, aInv, pad) {
var nMinus2 = []
aInv = aInv || []
subtract(n, [2], nMinus2)
modExp(a, nMinus2, n, aInv)
normalizeDigitArray(aInv)
return aInv
}
function modExp(base, exponent, modulus, result) {
result = result || []
if (compareDigits(exponent, Zero) === 0) {
result[0] = 1
} else if (compareDigits(exponent, One) === 0) {
copyArray(base, 0, result, 0, base.length)
result.length = base.length
} else {
var montmul = new MontgomeryMultiplier(modulus)
normalizeDigitArray(base, montmul.s, true)
montmul.modExp(base, exponent, result)
result.length = modulus.length
}
return result
}
function MontgomeryMultiplier(modulus, context) {
function computeM0Prime(m0) {
var m0Pr = 1
var a = 2
var b = 3
var c = b & m0
for (var i = 2; i <= DIGIT_BITS; i += 1) {
if (a < c) {
m0Pr += a
}
a = a << 1
b = (b << 1) | 1
c = (m0 * m0Pr) & b
}
var result = (~m0Pr & DIGIT_MASK) + 1
return result
}
function montgomeryReduction(t, m, result) {
var m0 = m[0]
var mPrime = computeM0Prime(m0)
var n = m.length
var A = t.slice(0)
var ui = []
var uimbi = []
var uim = []
var bi = [1]
for (var i = 0; i < n; i++) {
ui = (A[i] * mPrime) % DIGIT_BASE
multiply(m, [ui], uim)
multiply(uim, bi, uimbi)
add(A, uimbi, A)
bi.unshift(0)
}
A = A.slice(n)
for (i = 0; i < A.length; i++) {
result[i] = A[i]
}
}
function montgomeryMultiply(multiplicand, multiplier, result, ctx) {
ctx = ctx || this
var m = ctx.m,
s = m.length,
mPrime = ctx.mPrime,
m0 = ctx.m0,
rightI,
r0,
q,
i = 0,
j,
jm1,
t1,
t2,
carry,
rounds = 0
var temp = createArray(s + 2)
while (i < s) {
rounds = Math.min(s, rounds + 16)
for (; i < rounds; ) {
rightI = ~~multiplier[i]
r0 = temp[0] + multiplicand[0] * rightI
q = ((r0 & DIGIT_MASK) * mPrime) & DIGIT_MASK
temp[1] += ((m0 * q + r0) * DIG_INV) | 0
for (j = 1, jm1 = 0; j < s; jm1 = j, j += 1) {
temp[jm1] = temp[j] + m[j] * q + multiplicand[j] * rightI
}
temp[jm1] = temp[j]
temp[j] = 0
i++
}
carry = 0
for (j = 0; j < s; j++) {
t1 = temp[j] + carry
t2 = t1 & DIGIT_MASK
temp[j] = t2
carry = (t1 - t2) * DIG_INV
}
temp[j] = carry
}
for (i = 0; i < s; i += 1) {
result[i] = temp[i]
}
result.length = s
var needSubtract = +(cryptoMath.compareDigits(temp, m) > 0)
cryptoMath.subtract(result, m, ctx.temp2)
ctSetArray(needSubtract, result, ctx.temp2)
return
}
function convertToMontgomeryForm(digits) {
if (digits.length < this.s) {
digits.length = this.s
for (var i = 0; i < this.s; i++) {
digits[i] = isNaN(digits[i]) ? 0 : digits[i]
}
}
var result = createArray(digits.length)
this.montgomeryMultiply(digits, this.rSquaredModm, result)
for (i = 0; i < this.s; i += 1) {
digits[i] = result[i]
}
}
function convertToStandardForm(digits) {
this.montgomeryMultiply(digits, this.one, this.temp1)
for (var i = 0; i < this.s; i += 1) {
digits[i] = this.temp1[i]
}
}
function optimalWindowSize(length) {
var i = 2,
t1,
t0,
bits = length * DIGIT_BITS
t0 = 4 + Math.ceil(bits / 2) * 3 + 1
do {
i++
t1 = t0
t0 = Math.pow(2, i) + Math.ceil(bits / i) * (i + 1) + 1
} while (t0 < t1)
return i - 1
}
function modExp(base, exponent, result, skipSideChannel) {
skipSideChannel = !!skipSideChannel
var windowBits = optimalWindowSize(exponent.length)
var i,
j,
expBits = fixedWindowRecode2(exponent, windowBits).reverse(),
partialResult = this.rModM.slice(0),
baseTableLen = Math.pow(2, windowBits),
bt = baseTable
bt.length = baseTableLen
bt[0] = this.rModM
for (i = 1; i < baseTableLen; i++) {
bt[i] = []
multiply(bt[i - 1], base, bt[i])
this.reduce(bt[i])
}
var tableVal = []
var exp
for (i = 0; i < expBits.length; i++) {
for (j = 0; j < windowBits; j++) {
this.montgomeryMultiply(
partialResult,
partialResult,
partialResult,
)
}
exp = expBits[i]
skipSideChannel
? (tableVal = bt[exp])
: getTableEntry(bt, exp, tableVal)
this.montgomeryMultiply(partialResult, tableVal, partialResult)
}
this.montgomeryMultiply(partialResult, this.one, result)
return result
}
function getTableEntry(bt, exp, tableVal) {
var z, t, mask, tableEntry, k
for (z = 0; z < bt[0].length; z++) {
tableVal[z] = 0
}
for (t = 0; t < bt.length; t++) {
tableEntry = bt[t]
mask = -(exp === t)
for (k = 0; k < tableEntry.length; k++) {
tableVal[k] = tableVal[k] | (tableEntry[k] & mask)
}
}
}
function ctSetArray(condition, a, b) {
var bMask = -condition
var aMask = ~bMask
for (var i = 0; i < a.length; i++) {
a[i] = (a[i] & aMask) | (b[i] & bMask)
}
}
function reduce(x, result) {
var k = this.m.length,
q1,
q2,
q3,
r1,
r2,
i,
needSubtract,
temp = []
result = result || x
q1 = x.slice(k - 1)
q2 = []
multiply(q1, this.mu, q2)
q3 = q2.slice(k + 1)
r1 = x.slice(0, k + 1)
r2 = []
multiply(q3, m, r2)
r2 = r2.slice(0, k + 1)
r1[k + 1] = compareDigits(r1, r2) >>> 31
for (i = 0; i < result.length; i++) {
result[i] = 0
}
subtract(r1, r2, result)
needSubtract = +(compareDigits(result, m) > 0)
cryptoMath.subtract(result, m, temp)
ctSetArray(needSubtract, result, temp)
normalizeDigitArray(result)
return
}
function computeContext(modulus) {
var s = modulus.length
var m0 = modulus[0]
var ctx = {
m: modulus,
mPrime: computeM0Prime(m0),
m0: m0,
temp1: createArray(2 * s + 1),
temp2: createArray(2 * s + 1),
}
var R = createArray(modulus.length * 2)
R[R.length] = 1
ctx.mu = []
divRem(R, modulus, ctx.mu, [])
var quotient = createArray(2 * s + 1)
var rRemainder = createArray(s + 1)
var temp1 = createArray(2 * s + 1)
var temp2 = createArray(2 * s + 1)
var rDigits = rRemainder
rDigits[s] = 1
divRem(rDigits, modulus, quotient, rRemainder, temp1, temp2)
ctx.rModM = normalizeDigitArray(rRemainder, s, true)
var rSquaredModm = createArray(2 * s + 1)
var rSquaredDigits = rSquaredModm
rSquaredDigits[s * 2] = 1
divRem(rSquaredDigits, modulus, quotient, rSquaredModm, temp1, temp2)
ctx.rSquaredModm = normalizeDigitArray(rSquaredModm, s, true)
ctx.rCubedModm = createArray(s)
montgomeryMultiply(rSquaredModm, rSquaredModm, ctx.rCubedModm, ctx)
return ctx
}
context = context || computeContext(modulus)
var m = context.m
var mu = context.mu
var m0 = context.m0
var s = m.length
var zeros = createArray(s + 1)
var one = zeros.slice(0, s)
one[0] = 1
var mPrime = context.mPrime
var rModM = context.rModM
var rSquaredModm = context.rSquaredModm
var rCubedModm = context.rCubedModm
var temp1 = createArray(2 * s + 1)
var temp2 = createArray(2 * s + 1)
var baseTable = new Array(4)
baseTable[0] = rModM
baseTable[1] = new Array(s)
baseTable[2] = new Array(s)
baseTable[3] = new Array(s)
return {
m: m,
m0: m0,
mPrime: mPrime,
mu: mu,
rSquaredModm: rSquaredModm,
s: s,
rModM: rModM,
rCubedModm: rCubedModm,
one: one,
temp1: temp1,
temp2: temp2,
convertToMontgomeryForm: convertToMontgomeryForm,
convertToStandardForm: convertToStandardForm,
montgomeryMultiply: montgomeryMultiply,
modExp: modExp,
reduce: reduce,
ctx: context,
}
}
function IntegerGroup(modulusBytes) {
var m_modulus = bytesToDigits(modulusBytes)
var m_digitWidth = m_modulus.length
var m_zero = intToDigits(0, m_digitWidth)
var m_one = intToDigits(1, m_digitWidth)
var temp0 = createArray(m_digitWidth)
var temp1 = createArray(m_digitWidth)
var montmul = new MontgomeryMultiplier(m_modulus)
function createElementFromBytes(bytes) {
var digits = bytesToDigits(bytes)
if (cryptoMath.compareDigits(digits, this.m_modulus) >= 0) {
throw new Error(
'The number provided is not an element of this group',
)
}
normalizeDigitArray(digits, this.m_digitWidth, true)
return integerGroupElement(digits, this)
}
function createElementFromInteger(integer) {
var digits = intToDigits(integer, this.m_digitWidth)
return integerGroupElement(digits, this)
}
function createElementFromDigits(digits) {
cryptoMath.normalizeDigitArray(digits, this.m_digitWidth, true)
return integerGroupElement(digits, this)
}
function equals(otherGroup) {
return compareDigits(this.m_modulus, otherGroup.m_modulus) === 0
}
function add(addend1, addend2, sum) {
var i
var s = this.m_digitWidth
var result = sum.m_digits
cryptoMath.add(addend1.m_digits, addend2.m_digits, result)
var mask =
((compareDigits(result, this.m_modulus) >>> 31) - 1) & DIGIT_MASK
var carry = 0
for (i = 0; i < s; i += 1) {
carry = result[i] - (this.m_modulus[i] & mask) + carry
result[i] = carry & DIGIT_MASK
carry = carry >> DIGIT_BITS
}
result.length = s
}
function subtract(leftElement, rightElement, outputElement) {
var i,
s = this.m_digitWidth
var result = outputElement.m_digits
var carry = cryptoMath.subtract(
leftElement.m_digits,
rightElement.m_digits,
outputElement.m_digits,
)
if (carry === -1) {
carry = 0
for (i = 0; i < s; i += 1) {
carry += result[i] + this.m_modulus[i]
result[i] = carry & DIGIT_MASK
carry = carry >> DIGIT_BITS
}
}
}
function inverse(element, outputElement) {
cryptoMath.modInv(
element.m_digits,
this.m_modulus,
outputElement.m_digits,
)
}
function multiply(multiplicand, multiplier, product) {
return cryptoMath.modMul(
multiplicand.m_digits,
multiplier.m_digits,
this.m_modulus,
product.m_digits,
temp0,
temp1,
)
}
function modexp(valueElement, exponent, outputElement) {
outputElement = outputElement || integerGroupElement([], this)
if (compareDigits(exponent, m_zero) === 0) {
outputElement.m_digits = intToDigits(1, this.m_digitWidth)
} else if (compareDigits(exponent, m_one) === 0) {
for (var i = 0; i < valueElement.m_digits.length; i++) {
outputElement.m_digits[i] = valueElement.m_digits[i]
}
outputElement.m_digits.length = valueElement.m_digits.length
} else {
this.montmul.modExp(
valueElement.m_digits,
exponent,
outputElement.m_digits,
)
outputElement.m_digits.length = this.montmul.s
}
return outputElement
}
function integerGroupElement(digits, group) {
return {
m_digits: digits,
m_group: group,
equals: function (element) {
return (
compareDigits(this.m_digits, element.m_digits) === 0 &&
this.m_group.equals(this.m_group, element.m_group)
)
},
}
}
return {
m_modulus: m_modulus,
m_digitWidth: m_digitWidth,
montmul: montmul,
createElementFromInteger: createElementFromInteger,
createElementFromBytes: createElementFromBytes,
createElementFromDigits: createElementFromDigits,
equals: equals,
add: add,
subtract: subtract,
multiply: multiply,
inverse: inverse,
modexp: modexp,
}
}
return {
DIGIT_BITS: DIGIT_BITS,
DIGIT_NUM_BYTES: DIGIT_NUM_BYTES,
DIGIT_MASK: DIGIT_MASK,
DIGIT_BASE: DIGIT_BASE,
DIGIT_MAX: DIGIT_MAX,
Zero: Zero,
One: One,
normalizeDigitArray: normalizeDigitArray,
bytesToDigits: bytesToDigits,
stringToDigits: stringToDigits,
digitsToString: digitsToString,
intToDigits: intToDigits,
digitsToBytes: digitsToBytes,
isZero: isZero,
isEven: isEven,
shiftRight: shiftRight,
shiftLeft: shiftLeft,
compareDigits: compareDigits,
bitLength: highestSetBit,
fixedWindowRecode: fixedWindowRecode,
IntegerGroup: IntegerGroup,
add: add,
subtract: subtract,
multiply: multiply,
divRem: divRem,
reduce: reduce,
modInv: modInv,
modInvCT: modInvCT,
modExp: modExp,
modMul: modMul,
MontgomeryMultiplier: MontgomeryMultiplier,
gcd: gcd,
sequenceEqual: sequenceEqual,
swapEndianness: function (bytes) {
return bytes.reverse()
},
computeBitArray: computeBitArray,
}
}
var cryptoMath = cryptoMath || msrcryptoMath()
function MsrcryptoECC() {
var btd = cryptoMath.bytesToDigits
function createArray(parameter) {
var i,
array = null
if (!arguments.length || typeof arguments[0] === 'number') {
array = []
for (i = 0; i < parameter; i += 1) {
array[i] = 0
}
} else if (typeof arguments[0] === 'object') {
array = []
for (i = 0; i < parameter.length; i += 1) {
array[i] = parameter[i]
}
}
return array
}
var EllipticCurveFp = function (p1, a1, b1, order, gx, gy) {
var fieldStorageBitLength = p1.length
var generator = EllipticCurvePointFp(this, false, gx, gy, null, false)
return {
p: p1,
a: a1,
b: b1,
order: order,
generator: generator,
allocatePointStorage: function () {
return EllipticCurvePointFp(
this,
false,
cryptoMath.intToDigits(0, fieldStorageBitLength),
cryptoMath.intToDigits(0, fieldStorageBitLength),
)
},
createPointAtInfinity: function () {
return EllipticCurvePointFp(
this,
true,
cryptoMath.intToDigits(0, fieldStorageBitLength),
cryptoMath.intToDigits(0, fieldStorageBitLength),
)
},
}
}
var createWeierstrassCurve = function (curveData) {
var newCurve = new EllipticCurveFp(
btd(curveData.p),
btd(curveData.a),
btd(curveData.b),
btd(curveData.order),
btd(curveData.gx),
btd(curveData.gy),
)
newCurve.type = curveData.type
newCurve.name = curveData.name
newCurve.generator.curve = newCurve
return newCurve
}
var createTedCurve = function (curveData) {
var newCurve = new EllipticCurveFp(
btd(curveData.p),
btd(curveData.a),
btd(curveData.d),
btd(curveData.order),
btd(curveData.gx),
btd(curveData.gy),
)
newCurve.type = curveData.type
if (newCurve.type === 1) {
newCurve.d = newCurve.b.slice()
delete newCurve.b
}
newCurve.rbits = curveData.info[2]
newCurve.name = curveData.name
newCurve.generator.curve = newCurve
return newCurve
}
var EllipticCurvePointFp = function (
curve,
isInfinity,
x,
y,
z,
isInMontgomeryForm,
) {
var returnObj
if (typeof z === 'undefined') {
z = null
}
if (typeof isInMontgomeryForm === 'undefined') {
isInMontgomeryForm = false
}
function equals(ellipticCurvePointFp) {
if (!ellipticCurvePointFp) {
return false
}
if (returnObj.isInfinity && ellipticCurvePointFp.isInfinity) {
return true
}
if (returnObj.z === null && ellipticCurvePointFp.z !== null) {
return false
}
if (returnObj.z !== null && ellipticCurvePointFp.z === null) {
return false
}
if (returnObj.z === null) {
return (
cryptoMath.compareDigits(returnObj.x, ellipticCurvePointFp.x) ===
0 &&
cryptoMath.compareDigits(returnObj.y, ellipticCurvePointFp.y) ===
0 &&
returnObj.isInMontgomeryForm ===
ellipticCurvePointFp.isInMontgomeryForm
)
}
return (
cryptoMath.compareDigits(returnObj.x, ellipticCurvePointFp.x) ===
0 &&
cryptoMath.compareDigits(returnObj.y, ellipticCurvePointFp.y) ===
0 &&
cryptoMath.compareDigits(returnObj.z, ellipticCurvePointFp.z) ===
0 &&
returnObj.isInMontgomeryForm ===
ellipticCurvePointFp.isInMontgomeryForm
)
}
function copyTo(source, destination) {
destination.curve = source.curve
destination.x = source.x.slice()
destination.y = source.y.slice()
if (source.z !== null) {
destination.z = source.z.slice()
} else {
destination.z = null
}
setterSupport || (destination.isAffine = source.isAffine)
destination.isInMontgomeryForm = source.isInMontgomeryForm
destination.isInfinity = source.isInfinity
if (!destination.equals(source)) {
throw new Error('Instances should be equal.')
}
}
function clone() {
var clonePoint = EllipticCurvePointFp(
returnObj.curve,
returnObj.isInfinity,
createArray(returnObj.x),
createArray(returnObj.y),
returnObj.z ? createArray(returnObj.z) : null,
returnObj.isInMontgomeryForm,
)
returnObj.ta && (clonePoint.ta = createArray(returnObj.ta))
returnObj.tb && (clonePoint.tb = createArray(returnObj.tb))
return clonePoint
}
returnObj = {
equals: function (ellipticCurvePointFp) {
return equals(ellipticCurvePointFp)
},
copy: function (destination) {
copyTo(this, destination)
return
},
clone: function () {
return clone()
},
}
createProperty(
returnObj,
'curve',
curve,
function () {
return curve
},
function (val) {
curve = val
},
)
createProperty(
returnObj,
'x',
x,
function () {
return x
},
function (val) {
x = val
},
)
createProperty(
returnObj,
'y',
y,
function () {
return y
},
function (val) {
y = val
},
)
createProperty(
returnObj,
'z',
z,
function () {
return z
},
function (val) {
z = val
},
)
createProperty(
returnObj,
'isInMontgomeryForm',
isInMontgomeryForm,
function () {
return isInMontgomeryForm
},
function (val) {
isInMontgomeryForm = val
},
)
createProperty(
returnObj,
'isInfinity',
isInfinity,
function () {
return isInfinity
},
function (val) {
isInfinity = val
},
)
createProperty(returnObj, 'isAffine', z === null, function () {
return z === null
})
return returnObj
}
var EllipticCurveOperatorFp = function (curve) {
var m_curve = curve
var tedCurve = curve.type === 1
var fieldElementWidth = curve.p.length
var montgomeryMultiplier = cryptoMath.MontgomeryMultiplier(curve.p)
var montgomerizedA = curve.a.slice()
montgomeryMultiplier.convertToMontgomeryForm(montgomerizedA)
var aequalsZero = cryptoMath.isZero(curve.a)
var one = cryptoMath.One
var onemontgomery = createArray(fieldElementWidth)
onemontgomery[0] = 1
montgomeryMultiplier.convertToMontgomeryForm(onemontgomery)
var group = cryptoMath.IntegerGroup(
cryptoMath.digitsToBytes(montgomeryMultiplier.m),
true,
)
var temp0 = createArray(fieldElementWidth)
var temp1 = createArray(fieldElementWidth)
var temp2 = createArray(fieldElementWidth)
var temp3 = createArray(fieldElementWidth)
var temp4 = createArray(fieldElementWidth)
var temp5 = createArray(fieldElementWidth)
var temp6 = createArray(fieldElementWidth)
var temp7 = createArray(fieldElementWidth)
var swap0 = createArray(fieldElementWidth)
var conversionTemp0 = createArray(fieldElementWidth)
var conversionTemp1 = createArray(fieldElementWidth)
var conversionTemp2 = createArray(fieldElementWidth)
function modSub(left, right, result) {
var resultElement = group.createElementFromInteger(0)
resultElement.m_digits = result
group.subtract(
group.createElementFromDigits(left),
group.createElementFromDigits(right),
resultElement,
)
}
function modAdd(left, right, result) {
var resultElement = group.createElementFromInteger(0)
resultElement.m_digits = result
group.add(
group.createElementFromDigits(left),
group.createElementFromDigits(right),
resultElement,
)
}
function modInv(number, result) {
cryptoMath.modInv(number, m_curve.p, result)
}
function modDivByTwo(dividend, result) {
var s = dividend.length
var modulus = curve.p
if ((dividend[0] & 0x1) === 0x1) {
var carry = 0
for (var i = 0; i < s; i += 1) {
carry += dividend[i] + modulus[i]
result[i] = carry & cryptoMath.DIGIT_MASK
carry = carry >>> cryptoMath.DIGIT_BITS
}
carry = carry << (cryptoMath.DIGIT_BITS - 1)
cryptoMath.shiftRight(result, result)
result[s - 1] |= carry
} else {
cryptoMath.shiftRight(dividend, result)
}
}
function montgomeryMultiply(left, right, result) {
montgomeryMultiplier.montgomeryMultiply(left, right, result)
}
function montgomerySquare(left, result) {
montgomeryMultiplier.montgomeryMultiply(left, left, result)
}
function correctInversion(digits) {
var results = createArray(digits.length)
montgomeryMultiply(digits, montgomeryMultiplier.rCubedModm, results)
for (var i = 0; i < results.length; i += 1) {
digits[i] = results[i]
}
}
function doubleAequalsNeg3(point, outputPoint) {
if (point.isInfinity) {
outputPoint.isInfinity = true
return
}
montgomerySquare(point.z, temp1)
montgomeryMultiply(point.z, point.y, temp4)
modAdd(point.x, temp1, temp2)
modSub(point.x, temp1, temp1)
outputPoint.z = temp4.slice()
montgomeryMultiply(temp1, temp2, temp3)
modDivByTwo(temp3, temp2)
modAdd(temp3, temp2, temp1)
montgomerySquare(point.y, temp2)
montgomerySquare(temp1, temp4)
montgomeryMultiply(point.x, temp2, temp3)
modSub(temp4, temp3, temp4)
modSub(temp4, temp3, outputPoint.x)
modSub(temp3, outputPoint.x, temp4)
montgomerySquare(temp2, temp3)
montgomeryMultiply(temp1, temp4, temp2)
modSub(temp2, temp3, outputPoint.y)
outputPoint.isInfinity = false
outputPoint.isInMontgomeryForm = true
}
function doubleAequals0(point, outputPoint) {
if (point.isInfinity) {
outputPoint.isInfinity = true
return
}
montgomerySquare(point.y, temp3)
montgomerySquare(point.x, temp4)
modAdd(temp4, temp4, temp0)
modAdd(temp0, temp4, temp4)
montgomeryMultiply(point.x, temp3, temp5)
montgomerySquare(temp3, temp0)
modDivByTwo(temp4, temp1)
montgomerySquare(temp1, temp3)
montgomeryMultiply(point.y, point.z, swap0)
for (var i = 0; i < swap0.length; i += 1) {
outputPoint.z[i] = swap0[i]
}
modSub(temp3, temp5, outputPoint.x)
modSub(outputPoint.x, temp5, outputPoint.x)
modSub(temp5, outputPoint.x, temp4)
montgomeryMultiply(temp1, temp4, temp2)
modSub(temp2, temp0, outputPoint.y)
outputPoint.isInfinity = false
outputPoint.isInMontgomeryForm = true
}
function generatePrecomputationTable(w, generatorPoint) {
var validationPoint = generatorPoint.clone()
convertToStandardForm(validationPoint)
if (!validatePoint(validationPoint)) {
throw new Error('Invalid Parameter')
}
var pointJac = generatorPoint.clone()
convertToJacobianForm(pointJac)
var tablePos = [generatorPoint.clone()]
var qJac = pointJac.clone()
var px2 = pointJac.clone()
double(pointJac, px2)
convertToAffineForm(px2)
var qAff
for (var i = 1; i < Math.pow(2, w - 2); i++) {
mixedAdd(qJac, px2, qJac)
qAff = qJac.clone()
convertToAffineForm(qAff)
tablePos[i] = qAff
}
return tablePos
}
function double(point, outputPoint) {
if (typeof point === 'undefined') {
throw new Error('point undefined')
}
if (typeof outputPoint === 'undefined') {
throw new Error('outputPoint undefined')
}
if (point.isAffine) {
throw new Error(
'Given point was in Affine form. Use convertToJacobian() first.',
)
}
if (!point.isInMontgomeryForm) {
throw new Error(
'Given point must be in Montgomery form. Use montgomeryize() first.',
)
}
if (aequalsZero) {
doubleAequals0(point, outputPoint)
} else {
doubleAequalsNeg3(point, outputPoint)
}
}
function mixedDoubleAdd(jacobianPoint, affinePoint, outputPoint) {
if (jacobianPoint.isInfinity) {
affinePoint.copy(outputPoint)
this.convertToJacobianForm(outputPoint)
return
}
if (affinePoint.isInfinity) {
jacobianPoint.copy(outputPoint)
return
}
montgomerySquare(jacobianPoint.z, temp5)
montgomeryMultiply(jacobianPoint.z, temp5, temp6)
montgomeryMultiply(affinePoint.x, temp5, temp4)
montgomeryMultiply(affinePoint.y, temp6, temp5)
modSub(temp4, jacobianPoint.x, temp1)
modSub(temp5, jacobianPoint.y, temp2)
if (cryptoMath.isZero(temp1)) {
if (cryptoMath.isZero(temp2)) {
double(jacobianPoint, outputPoint)
mixedAdd(outputPoint, affinePoint, outputPoint)
return
} else {
outputPoint.x = jacobianPoint.x.slice(0)
outputPoint.y = jacobianPoint.y.slice(0)
outputPoint.z = jacobianPoint.z.slice(0)
return
}
}
montgomerySquare(temp2, temp4)
montgomerySquare(temp1, temp6)
montgomeryMultiply(temp6, jacobianPoint.x, temp5)
montgomeryMultiply(temp1, temp6, temp0)
modSub(temp4, temp5, temp3)
modSub(temp3, temp5, temp3)
montgomeryMultiply(jacobianPoint.z, temp1, temp4)
modSub(temp3, temp5, temp3)
montgomeryMultiply(temp0, jacobianPoint.y, temp6)
modSub(temp3, temp0, temp3)
if (cryptoMath.isZero(temp3)) {
for (i = 0; i < outputPoint.x.length; i++) {
outputPoint.x[i] = 0
outputPoint.y[i] = 0
outputPoint.z[i] = 0
}
outputPoint.y[0] = 1
return
}
modAdd(temp6, temp6, temp1)
montgomeryMultiply(temp4, temp3, outputPoint.z)
montgomeryMultiply(temp2, temp3, temp4)
montgomerySquare(temp3, temp0)
modAdd(temp1, temp4, temp1)
montgomeryMultiply(temp0, temp5, temp4)
montgomerySquare(temp1, temp7)
montgomeryMultiply(temp0, temp3, temp5)
modSub(temp7, temp4, outputPoint.x)
modSub(outputPoint.x, temp4, outputPoint.x)
modSub(outputPoint.x, temp5, outputPoint.x)
modSub(outputPoint.x, temp4, temp3)
montgomeryMultiply(temp5, temp6, temp0)
montgomeryMultiply(temp1, temp3, temp4)
modSub(temp4, temp0, outputPoint.y)
outputPoint.isInfinity = false
outputPoint.isInMontgomeryForm = true
}
function mixedAdd(jacobianPoint, affinePoint, outputPoint) {
if (jacobianPoint === null) {
throw new Error('jacobianPoint')
}
if (affinePoint === null) {
throw new Error('affinePoint')
}
if (outputPoint === null) {
throw new Error('outputPoint')
}
if (
jacobianPoint.curve !== affinePoint.curve ||
jacobianPoint.curve !== outputPoint.curve
) {
throw new Error('All points must be from the same curve object.')
}
if (jacobianPoint.isAffine) {
throw new Error(
'Given jacobianPoint was in Affine form. Use ConvertToJacobian()\
before calling DoubleJacobianAddAffinePoints().',
)
}
if (!affinePoint.isAffine) {
throw new Error(
'Given affinePoint was in Jacobian form. Use ConvertToAffine() before \
calling DoubleJacobianAddAffinePoints().',
)
}
if (outputPoint.isAffine) {
throw new Error(
'Given jacobianPoint was in Jacobian form. Use ConvertToJacobian() before \
calling DoubleJacobianAddAffinePoints().',
)
}
if (!jacobianPoint.isInMontgomeryForm) {
throw new Error('Jacobian point must be in Montgomery form')
}
if (!affinePoint.isInMontgomeryForm) {
throw new Error('Affine point must be in Montgomery form')
}
if (jacobianPoint.isInfinity) {
affinePoint.copy(outputPoint)
this.convertToJacobianForm(outputPoint)
return
}
if (affinePoint.isInfinity) {
jacobianPoint.copy(outputPoint)
return
}
montgomerySquare(jacobianPoint.z, temp1)
montgomeryMultiply(temp1, jacobianPoint.z, temp2)
montgomeryMultiply(temp1, affinePoint.x, temp3)
montgomeryMultiply(temp2, affinePoint.y, temp4)
modSub(temp3, jacobianPoint.x, temp1)
modSub(temp4, jacobianPoint.y, temp2)
var i
for (i = 0; i < temp1.length; i += 1) {
if (temp1[i] !== 0) {
montgomeryMultiply(jacobianPoint.z, temp1, temp0)
for (var j = 0; j < fieldElementWidth; j += 1) {
outputPoint.z[j] = temp0[j]
}
montgomerySquare(temp1, temp3)
montgomeryMultiply(temp3, temp1, temp4)
montgomeryMultiply(temp3, jacobianPoint.x, temp5)
modAdd(temp5, temp5, temp1)
montgomerySquare(temp2, outputPoint.x)
modSub(outputPoint.x, temp1, outputPoint.x)
modSub(outputPoint.x, temp4, outputPoint.x)
modSub(temp5, outputPoint.x, temp3)
montgomeryMultiply(temp2, temp3, temp5)
montgomeryMultiply(jacobianPoint.y, temp4, temp6)
modSub(temp5, temp6, outputPoint.y)
outputPoint.isInfinity = false
outputPoint.isInMontgomeryForm = true
return
}
}
for (i = 0; i < temp2.length; i += 1) {
if (temp2[i] !== 0) {
outputPoint.isInfinity = true
outputPoint.isInMontgomeryForm = true
return
}
}
affinePoint.copy(outputPoint)
this.convertToJacobianForm(outputPoint)
this.double(outputPoint, outputPoint)
outputPoint.isInMontgomeryForm = true
}
function scalarMultiply(k, point, outputPoint, multiplyBy4) {
if (point.isInfinity || cryptoMath.isZero(k)) {
outputPoint.isInfinity = true
return
}
if (cryptoMath.compareDigits(k, curve.order) >= 0) {
throw new Error('The scalar k must be in the range 1 <= k < order.')
}
k = k.slice()
if (point.curve.type === 1) {
var pointIsEP = typeof point.ta !== 'undefined'
if (!pointIsEP) {
convertToExtendedProjective(point)
}
scalarMultiplyTed(k, point, outputPoint, multiplyBy4)
if (!pointIsEP) {
normalizeTed(point)
}
} else {
var pointIsMF = point.isInMontgomeryForm,
outputIsMF = outputPoint.isInMontgomeryForm,
outputIsAffine = outputPoint.isAffine
if (!pointIsMF) {
convertToMontgomeryForm(point)
}
if (!outputIsMF) {
convertToMontgomeryForm(outputPoint)
}
scalarMultiplyW(k, point, outputPoint)
if (outputIsAffine) {
convertToAffineForm(outputPoint)
}
if (!pointIsMF) {
convertToStandardForm(point)
}
if (!outputIsMF) {
convertToStandardForm(outputPoint)
}
}
return
}
function scalarMultiplyW(k, point, outputPoint) {
var validationPoint = point.clone()
convertToStandardForm(validationPoint)
if (!validatePoint(validationPoint)) {
throw new Error('Invalid Parameters.')
}
var odd = k[0] & 1,
tempk = []
modSub(point.curve.order, k, tempk)
for (i = 0; i < k.length; i++) {
k[i] = ((odd - 1) & (k[i] ^ tempk[i])) ^ k[i]
}
var w = fieldElementWidth <= 8 ? 5 : 6
var m = point.curve.p.length * cryptoMath.DIGIT_BITS
var t = Math.ceil(m / (w - 1))
var kDigits = cryptoMath.fixedWindowRecode(k, w, t)
var Tm = generatePrecomputationTable(w, point)
var position = Math.floor(Math.abs(kDigits[t]) - 1) / 2
var Q = Tm[position].clone()
convertToJacobianForm(Q)
for (var i = t - 1; i >= 0; i--) {
for (var j = 0; j < w - 2; j++) {
double(Q, Q)
}
position = Math.floor((Math.abs(kDigits[i]) - 1) / 2)
var L = tableLookupW(Tm, position)
modSub(L.curve.p, L.y, tempk)
var mask = -(kDigits[i] >>> 31)
for (var n = 0; n < L.y.length; n++) {
L.y[n] = (L.y[n] & ~mask) | (tempk[n] & mask)
}
mixedDoubleAdd(Q, L, Q)
}
modSub(point.curve.p, Q.y, tempk)
for (i = 0; i < Q.y.length; i++) {
Q.y[i] = ((odd - 1) & (Q.y[i] ^ tempk[i])) ^ Q.y[i]
}
Q.copy(outputPoint)
return
}
function tableLookupW(table, index) {
var mask, L
for (var i = 0; i < table.length; i++) {
mask = +(i === index)
L = [L, table[i].clone()][mask]
}
return L
}
function tableLookupW0(table, index) {
var pos = (index + 1) % table.length
for (var i = 0; i < table.length; i++) {
var L = table[pos].clone()
pos = (pos + 1) % table.length
}
return L
}
function negate(point, outputPoint) {
if (point !== outputPoint) {
point.copy(outputPoint)
}
modSub(point.curve.p, point.y, outputPoint.y)
}
function convertToMontgomeryForm(point) {
if (point.isInMontgomeryForm) {
throw new Error('The given point is already in Montgomery form.')
}
if (!point.isInfinity) {
montgomeryMultiplier.convertToMontgomeryForm(point.x)
montgomeryMultiplier.convertToMontgomeryForm(point.y)
if (point.z !== null) {
montgomeryMultiplier.convertToMontgomeryForm(point.z)
}
if (typeof point.ta !== 'undefined') {
montgomeryMultiplier.convertToMontgomeryForm(point.ta)
montgomeryMultiplier.convertToMontgomeryForm(point.tb)
}
}
point.isInMontgomeryForm = true
}
function convertToStandardForm(point) {
if (!point.isInMontgomeryForm) {
throw new Error('The given point is not in montgomery form.')
}
if (!point.isInfinity) {
montgomeryMultiplier.convertToStandardForm(point.x)
montgomeryMultiplier.convertToStandardForm(point.y)
if (point.z !== null) {
montgomeryMultiplier.convertToStandardForm(point.z)
}
if (typeof point.ta !== 'undefined') {
montgomeryMultiplier.convertToStandardForm(point.ta)
montgomeryMultiplier.convertToStandardForm(point.tb)
}
}
point.isInMontgomeryForm = false
}
function convertToAffineForm(point) {
if (point.isInfinity) {
point.z = null
setterSupport || (point.isAffine = true)
return
}
cryptoMath.modInv(point.z, curve.p, conversionTemp2, true)
if (point.isInMontgomeryForm) {
montgomeryMultiply(
conversionTemp2,
montgomeryMultiplier.rCubedModm,
conversionTemp1,
)
var swap = conversionTemp2
conversionTemp2 = conversionTemp1
conversionTemp1 = swap
}
montgomerySquare(conversionTemp2, conversionTemp0)
montgomeryMultiply(point.x, conversionTemp0, conversionTemp1)
for (var i = 0; i < fieldElementWidth; i += 1) {
point.x[i] = conversionTemp1[i]
}
montgomeryMultiply(point.y, conversionTemp0, conversionTemp1)
montgomeryMultiply(conversionTemp1, conversionTemp2, point.y)
point.z = null
delete point.ta
delete point.tb
setterSupport || (point.isAffine = true)
}
function convertToJacobianForm(point) {
if (!point.isAffine) {
throw new Error('The given point is not in Affine form.')
}
setterSupport || (point.isAffine = false)
var clonedDigits,
i,
zOne = point.isInMontgomeryForm ? onemontgomery : one
clonedDigits = createArray(zOne.length)
for (i = 0; i < zOne.length; i += 1) {
clonedDigits[i] = zOne[i]
}
point.z = clonedDigits
return
}
function validatePoint(point) {
if (point.isInfinity) {
return false
}
cryptoMath.modMul(point.y, point.y, point.curve.p, temp1)
cryptoMath.modMul(point.x, point.x, point.curve.p, temp2)
cryptoMath.modMul(point.x, temp2, point.curve.p, temp3)
modAdd(temp3, point.curve.b, temp2)
cryptoMath.modMul(point.x, point.curve.a, point.curve.p, temp3)
modAdd(temp2, temp3, temp2)
modSub(temp1, temp2, temp1)
if (cryptoMath.isZero(temp1) === false) {
return false
}
return true
}
function validatePointTed(point) {
if (point.ta) {
point = point.clone()
normalizeTed(point)
}
cryptoMath.modMul(point.y, point.y, point.curve.p, temp3)
cryptoMath.modMul(point.x, point.x, point.curve.p, temp2)
cryptoMath.add(temp2, temp3, temp1)
cryptoMath.reduce(temp4, point.curve.p, temp4)
cryptoMath.modMul(temp2, temp3, point.curve.p, temp4)
cryptoMath.modMul(point.curve.d, temp4, point.curve.p, temp3)
cryptoMath.add(temp3, [1], temp2)
cryptoMath.reduce(temp2, point.curve.p, temp2)
cryptoMath.subtract(temp1, temp2, temp1)
if (cryptoMath.isZero(temp1) === false) {
cryptoMath.reduce(temp1, point.curve.p, temp1)
if (cryptoMath.isZero(temp1) === false) {
return false
}
}
return true
}
function generatePrecomputationTableTed(npoints, point) {
var Q = point.clone(),
P2 = Q.clone(),
T = []
T[0] = convert_R1_to_R2(point)
doubleTed(Q, Q)
P2 = convert_R1_to_R2(Q)
Q = point.clone()
for (var i = 1; i < npoints; i++) {
addTedExtended(P2, Q, Q)
T[i] = convert_R1_to_R2(Q)
}
return T
}
function convertToExtendedProjective(affinePoint) {
affinePoint.ta = affinePoint.x.slice()
affinePoint.tb = affinePoint.y.slice()
affinePoint.z = [1]
}
function scalarMultiplyTed(k, point, outputPoint, multiplyBy4) {
if (!validatePointTed(point)) {
throw new Error('Invalid Parameter')
}
var rbits = point.curve.rbits
multiplyBy4 = typeof multiplyBy4 === 'undefined' ? true : multiplyBy4
var w = fieldElementWidth <= 8 ? 5 : 6
var t = Math.floor((rbits + (w - 2)) / (w - 1))
var i, j
k = k.slice()
var T = point.clone()
convertToExtendedProjective(T)
if (multiplyBy4) {
doubleTed(T, T)
doubleTed(T, T)
}
var precomputationTable = generatePrecomputationTableTed(
1 << (w - 2),
T,
)
var odd = k[0] & 1,
tempk = [],
kisNeg
modSub(point.curve.order, k, tempk)
for (i = 0; i < k.length; i++) {
k[i] = ((odd - 1) & (k[i] ^ tempk[i])) ^ k[i]
}
var kDigits = cryptoMath.fixedWindowRecode(k, w, t)
var position = Math.floor(Math.abs(kDigits[t]) - 1) / 2
var R = precomputationTable[position]
T.x = R.x.slice()
T.y = R.y.slice()
T.z = R.z.slice()
for (i = t - 1; i >= 0; i--) {
for (j = 0; j < w - 1; j++) {
doubleTed(T, T)
}
position = Math.floor((Math.abs(kDigits[i]) - 1) / 2)
var L = tableLookupTed(precomputationTable, position)
var mask = -(kDigits[i] >>> 31)
modSub(point.curve.p, L.x, tempk)
for (var m = 0; m < L.x.length; m++) {
L.x[m] = (L.x[m] & ~mask) | (tempk[m] & mask)
}
modSub(point.curve.p, L.td, tempk)
for (m = 0; m < L.td.length; m++) {
L.td[m] = (L.td[m] & ~mask) | (tempk[m] & mask)
}
addTedExtended(L, T, T)
}
modSub(point.curve.p, T.x, tempk)
for (i = 0; i < T.x.length; i++) {
T.x[i] = ((odd - 1) & (T.x[i] ^ tempk[i])) ^ T.x[i]
}
normalizeTed(T)
outputPoint.x = T.x.slice()
outputPoint.y = T.y.slice()
return
}
function tableLookupTed(table, index) {
var pos = (index + 1) % table.length
for (var i = 0; i < table.length; i++) {
var L = {
x: table[pos].x.slice(),
y: table[pos].y.slice(),
z: table[pos].z.slice(),
td: table[pos].td.slice(),
}
pos = (pos + 1) % table.length
}
return L
}
function normalizeTed(point) {
cryptoMath.modInv(point.z, curve.p, conversionTemp2, true)
cryptoMath.modMul(point.x, conversionTemp2, curve.p, point.x)
cryptoMath.modMul(point.y, conversionTemp2, curve.p, point.y)
delete point.ta
delete point.tb
point.z = null
return
}
function doubleTed(point, outputPoint) {
if (typeof point.ta === 'undefined') {
throw new Error('Point should be in Extended Projective form.')
}
cryptoMath.modMul(point.x, point.x, point.curve.p, temp0)
cryptoMath.modMul(point.y, point.y, point.curve.p, temp1)
cryptoMath.modMul(point.z, point.z, point.curve.p, point.ta)
modSub(temp1, temp0, outputPoint.tb)
modAdd(temp0, temp1, temp0)
modAdd(point.ta, point.ta, point.ta)
modAdd(point.y, point.y, point.y)
modSub(point.ta, temp0, temp1)
cryptoMath.modMul(point.x, point.y, point.curve.p, outputPoint.ta)
cryptoMath.modMul(temp0, outputPoint.tb, point.curve.p, outputPoint.y)
cryptoMath.modMul(temp1, outputPoint.ta, point.curve.p, outputPoint.x)
cryptoMath.modMul(temp0, temp1, point.curve.p, outputPoint.z)
return
}
function addTed(point1, point2, outputPoint) {
var cm = cryptoMath
if (typeof point1.ta === 'undefined') {
throw new Error('Point1 should be in Extended Projective form.')
}
if (typeof point2.ta === 'undefined') {
throw new Error('Point2 should be in Extended Projective form.')
}
var qq = convert_R1_to_R2(point1)
addTedExtended(qq, point2, outputPoint)
return
}
function convert_R1_to_R2(point) {
var curve = point.curve,
modulus = curve.p,
qq = {
x: point.x.slice(),
y: point.y.slice(),
z: point.z.slice(),
td: [],
curve: point.curve,
}
cryptoMath.modMul(point.ta, point.tb, modulus, conversionTemp0)
cryptoMath.modMul(conversionTemp0, curve.d, modulus, qq.td)
return qq
}
function addTedExtended(qq, point2, outputPoint) {
var cm = cryptoMath
var modulus = point2.curve.p
temp1 = []
temp2 = []
temp3 = []
cm.modMul(point2.z, qq.z, modulus, temp3)
cm.modMul(point2.ta, point2.tb, modulus, temp1)
modAdd(point2.x, point2.y, point2.ta)
cm.modMul(temp1, qq.td, modulus, temp2)
modAdd(qq.x, qq.y, point2.tb)
modSub(temp3, temp2, temp1)
modAdd(temp3, temp2, temp3)
cm.modMul(point2.ta, point2.tb, modulus, temp2)
cm.modMul(point2.x, qq.x, modulus, point2.z)
cm.modMul(point2.y, qq.y, modulus, point2.x)
modSub(temp2, point2.z, temp2)
modSub(point2.x, point2.z, outputPoint.ta)
modSub(temp2, point2.x, outputPoint.tb)
cm.modMul(outputPoint.ta, temp3, modulus, outputPoint.y)
cm.modMul(outputPoint.tb, temp1, modulus, outputPoint.x)
cm.modMul(temp3, temp1, modulus, outputPoint.z)
return
}
function convertTedToWeierstrass(tedPoint, wPoint) {
var a = tedPoint.curve.a.slice(),
d = tedPoint.curve.d.slice(),
p = tedPoint.curve.p,
modMul = cryptoMath.modMul,
modInv = cryptoMath.modInv
temp1 = [5]
modMul(a, temp1, p, temp2)
modSub(temp2, d, temp2)
modMul(d, temp1, p, temp3)
modSub(a, temp3, temp1)
modMul(tedPoint.y, temp1, p, temp3)
modAdd(temp3, temp2, temp2)
temp1 = [1]
modSub(temp1, tedPoint.y, temp3)
temp1 = [12]
modMul(temp1, temp3, p, temp4)
modInv(temp4, p, temp4, true)
modMul(tedPoint.x, temp3, p, temp1)
modAdd(temp1, temp1, temp3)
modAdd(temp3, temp3, temp3)
modInv(temp3, p, temp3, true)
modMul(temp4, temp2, p, wPoint.x)
temp1 = [1]
modAdd(tedPoint.y, temp1, temp1)
modSub(a, d, temp2)
modMul(temp1, temp2, p, temp4)
modMul(temp4, temp3, p, wPoint.y)
return
}
function convertWeierstrassToTed(wPoint, tedPoint) {
var a = tedPoint.curve.a.slice(),
d = tedPoint.curve.d.slice(),
p = tedPoint.curve.p,
modMul = cryptoMath.modMul,
modInv = cryptoMath.modInv
modAdd(wPoint.x, wPoint.x, temp1)
modAdd(wPoint.x, temp1, temp1)
modAdd(temp1, temp1, temp1)
modSub(temp1, a, temp2)
modSub(temp2, d, temp2)
modAdd(wPoint.y, wPoint.y, temp3)
modAdd(wPoint.y, temp3, temp3)
modAdd(temp3, temp3, temp3)
modInv(temp3, p, temp3, true)
modMul(temp2, temp3, p, tedPoint.x)
modAdd(temp1, temp1, temp1)
modAdd(temp1, d, temp2)
modAdd(temp1, a, temp1)
modAdd(a, a, temp3)
modSub(temp2, temp3, temp2)
modSub(temp2, temp3, temp2)
modSub(temp2, a, temp2)
modAdd(d, d, temp3)
modSub(temp1, temp3, temp1)
modSub(temp1, temp3, temp1)
modSub(temp1, d, temp1)
modInv(temp1, p, temp1, true)
modMul(temp1, temp2, p, tedPoint.y)
return
}
var methods = {
convertToMontgomeryForm: convertToMontgomeryForm,
convertToStandardForm: convertToStandardForm,
convertToAffineForm: convertToAffineForm,
convertToJacobianForm: convertToJacobianForm,
generatePrecomputationTable: function (w, generatorPoint) {
return generatePrecomputationTable(w, generatorPoint)
},
}
if (tedCurve) {
methods.double = doubleTed
methods.add = addTed
methods.scalarMultiply = scalarMultiply
methods.normalize = normalizeTed
methods.convertToExtendedProjective = convertToExtendedProjective
methods.convertTedToWeierstrass = convertTedToWeierstrass
methods.convertWeierstrassToTed = convertWeierstrassToTed
methods.validatePoint = validatePointTed
methods.generatePrecomputationTable = function (w, generatorPoint) {
return generatePrecomputationTableTed(w, generatorPoint)
}
} else {
methods.double = double
methods.mixedDoubleAdd = mixedDoubleAdd
methods.mixedAdd = mixedAdd
methods.scalarMultiply = scalarMultiply
methods.negate = negate
methods.validatePoint = validatePoint
}
return methods
}
var sec1EncodingFp = function () {
return {
encodePoint: function (point) {
if (!point) {
throw new Error('point')
}
if (!point.isAffine) {
throw new Error('Point must be in affine form.')
}
if (point.isInMontgomeryForm) {
throw new Error('Point must not be in Montgomery form.')
}
if (point.isInfinity) {
return createArray(1)
} else {
var xOctetString = cryptoMath.digitsToBytes(point.x)
var yOctetString = cryptoMath.digitsToBytes(point.y)
var pOctetString = cryptoMath.digitsToBytes(point.curve.p)
var mlen = pOctetString.length
if (mlen < xOctetString.length || mlen < yOctetString.length) {
throw new Error(
'Point coordinate(s) are bigger than the field order.',
)
}
var output = createArray(2 * mlen + 1)
output[0] = 0x04
var offset = mlen - xOctetString.length
for (var i = 0; i < xOctetString.length; i++) {
output[i + 1 + offset] = xOctetString[i]
}
offset = mlen - yOctetString.length
for (i = 0; i < yOctetString.length; i++) {
output[mlen + i + 1 + offset] = yOctetString[i]
}
return output
}
},
decodePoint: function (encoded, curve) {
if (encoded.length < 1) {
throw new Error('Byte array must have non-zero length')
}
var pOctetString = cryptoMath.digitsToBytes(curve.p)
var mlen = pOctetString.length
if (encoded[0] === 0x0 && encoded.length === 1) {
return curve.createPointAtInfinity()
} else if (encoded[0] === 0x04 && encoded.length === 1 + 2 * mlen) {
var xbytes = createArray(mlen)
var ybytes = createArray(mlen)
for (var i = 0; i < mlen; i++) {
xbytes[i] = encoded[i + 1]
ybytes[i] = encoded[mlen + i + 1]
}
var x = cryptoMath.bytesToDigits(xbytes)
var y = cryptoMath.bytesToDigits(ybytes)
return EllipticCurvePointFp(curve, false, x, y)
} else {
throw new Error('Unsupported encoding format')
}
},
}
}
var ModularSquareRootSolver = function (modulus) {
var p = modulus
var specialK = []
if (typeof modulus === 'undefined') {
throw new Error('modulus')
}
if (cryptoMath.isEven(modulus)) {
throw new Error('Only odd moduli are supported')
}
var mul = cryptoMath.MontgomeryMultiplier(p)
if (p[0] % 4 === 3) {
cryptoMath.add(p, cryptoMath.One, specialK)
cryptoMath.shiftRight(specialK, specialK, 2)
} else {
specialK = null
}
var temp0 = new Array(p.length)
var temp1 = new Array(p.length)
function squareRootNistCurves(a) {
var beta = cryptoMath.intToDigits(0, 16)
mul.modExp(a, specialK, beta)
var aPrime = [0]
cryptoMath.modMul(beta, beta, mul.m, aPrime)
if (cryptoMath.compareDigits(a, aPrime) !== 0) {
return null
}
return beta
}
var publicMethods = {
squareRoot: function (a) {
if (specialK !== null) {
return squareRootNistCurves(a)
} else {
throw new Error('GeneralCase not supported.')
}
},
jacobiSymbol: function (a) {
var modEightMask = 0x7,
modFourMask = 0x3,
aPrime,
pPrime
aPrime = a.slice()
pPrime = p.slice()
cryptoMath.reduce(aPrime, pPrime, aPrime, temp0, temp1)
var t = 1
while (!cryptoMath.isZero(aPrime)) {
while (cryptoMath.isEven(aPrime)) {
cryptoMath.shiftRight(aPrime, aPrime)
var pMod8 = pPrime[0] & modEightMask
if (pMod8 === 3 || pMod8 === 5) {
t = -t
}
}
var tmp = aPrime
aPrime = pPrime
pPrime = tmp
var aMod4 = aPrime[0] & modFourMask
var pMod4 = pPrime[0] & modFourMask
if (aMod4 === 3 && pMod4 === 3) {
t = -t
}
cryptoMath.reduce(aPrime, pPrime, aPrime, temp0, temp1)
}
if (cryptoMath.compareDigits(pPrime, cryptoMath.One) === 0) {
return t
} else {
return 0
}
},
}
return publicMethods
}
var curvesInternal = {}
var createCurve = function (curveName) {
var curveData = curvesInternal[curveName.toUpperCase()]
if (!curveData) {
throw new Error(curveName + ' Unsupported curve.')
}
if (curveData.type === 0) {
return createWeierstrassCurve(curveData)
}
if (curveData.type === 1) {
return createTedCurve(curveData)
}
throw new Error(curveName + ' Unsupported curve type.')
}
var validateEccPoint = function (curveName, x, y, z) {
var curve = createCurve(curveName)
var point = new EllipticCurvePointFp(
curve,
false,
btd(x),
btd(y),
z && btd(z),
false,
)
var opp = new EllipticCurveOperatorFp(curve)
return opp.validatePoint(point)
}
return {
createCurve: createCurve,
curves: curvesInternal,
sec1EncodingFp: sec1EncodingFp,
validatePoint: validateEccPoint,
EllipticCurvePointFp: EllipticCurvePointFp,
EllipticCurveOperatorFp: EllipticCurveOperatorFp,
ModularSquareRootSolver: ModularSquareRootSolver,
}
}
var cryptoECC = cryptoECC || MsrcryptoECC()
var curve_P256 = {
name: 'P-256',
type: 0,
p: [
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
],
a: [
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
],
b: [
0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55,
0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6,
0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b,
],
order: [
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84,
0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
],
gx: [
0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5,
0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96,
],
gy: [
0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a,
0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
],
cf: 1,
}
var curve_P384 = {
name: 'P-384',
type: 0,
p: [
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
],
a: [
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc,
],
b: [
0xb3, 0x31, 0x2f, 0xa7, 0xe2, 0x3e, 0xe7, 0xe4, 0x98, 0x8e, 0x05, 0x6b,
0xe3, 0xf8, 0x2d, 0x19, 0x18, 0x1d, 0x9c, 0x6e, 0xfe, 0x81, 0x41, 0x12,
0x03, 0x14, 0x08, 0x8f, 0x50, 0x13, 0x87, 0x5a, 0xc6, 0x56, 0x39, 0x8d,
0x8a, 0x2e, 0xd1, 0x9d, 0x2a, 0x85, 0xc8, 0xed, 0xd3, 0xec, 0x2a, 0xef,
],
order: [
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf, 0x58, 0x1a, 0x0d, 0xb2,
0x48, 0xb0, 0xa7, 0x7a, 0xec, 0xec, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73,
],
gx: [
0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37, 0x8e, 0xb1, 0xc7, 0x1e,
0xf3, 0x20, 0xad, 0x74, 0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98,
0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38, 0x55, 0x02, 0xf2, 0x5d,
0xbf, 0x55, 0x29, 0x6c, 0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7,
],
gy: [
0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf,
0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce,
0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f,
],
cf: 1,
}
var curve_P521 = {
name: 'P-521',
type: 0,
p: [
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
],
a: [
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
],
b: [
0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, 0x9a, 0x1f, 0x92, 0x9a,
0x21, 0xa0, 0xb6, 0x85, 0x40, 0xee, 0xa2, 0xda, 0x72, 0x5b, 0x99, 0xb3,
0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, 0x09, 0xe1, 0x56, 0x19,
0x39, 0x51, 0xec, 0x7e, 0x93, 0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1,
0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, 0x34, 0xf1, 0xef, 0x45,
0x1f, 0xd4, 0x6b, 0x50, 0x3f, 0x00,
],
order: [
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x51, 0x86,
0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09,
0xa5, 0xd0, 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, 0xbb, 0x6f,
0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09,
],
gx: [
0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, 0x9e, 0x3e,
0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f,
0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba, 0xa1, 0x4b,
0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff,
0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 0xf9, 0x7e,
0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66,
],
gy: [
0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a,
0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee,
0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,
0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,
],
cf: 1,
}
if (typeof cryptoECC !== 'undefined') {
cryptoECC.curves['P-256'] = curve_P256
cryptoECC.curves['P-384'] = curve_P384
cryptoECC.curves['P-521'] = curve_P521
}
var curve_BN254 = {
name: 'BN-254',
type: 0,
p: [
0x25, 0x23, 0x64, 0x82, 0x40, 0x00, 0x00, 0x01, 0xba, 0x34, 0x4d, 0x80,
0x00, 0x00, 0x00, 0x08, 0x61, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
0xa7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
],
a: [0x00],
b: [0x02],
order: [
0x25, 0x23, 0x64, 0x82, 0x40, 0x00, 0x00, 0x01, 0xba, 0x34, 0x4d, 0x80,
0x00, 0x00, 0x00, 0x07, 0xff, 0x9f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x10,
0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
],
gx: [
0x25, 0x23, 0x64, 0x82, 0x40, 0x00, 0x00, 0x01, 0xba, 0x34, 0x4d, 0x80,
0x00, 0x00, 0x00, 0x08, 0x61, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
0xa7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
],
gy: [0x01],
cf: 1,
}
if (typeof cryptoECC !== 'undefined') {
cryptoECC.curves['BN-254'] = curve_BN254
}
var curve_numsp256d1 = {
info: ['numsp256d1', 256, 256, 256],
type: 0,
p: [
0x43, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
].reverse(),
a: [
0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
].reverse(),
b: [0x81, 0x55, 0x02].reverse(),
order: [
0x25, 0xa8, 0x51, 0x47, 0x29, 0x20, 0xab, 0x20, 0x60, 0x5c, 0x26, 0xea,
0x75, 0x82, 0x3c, 0xe4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
].reverse(),
gx: [
0xb1, 0xac, 0x1a, 0xb2, 0x1e, 0xee, 0x52, 0xbc, 0x3a, 0xc7, 0xd4, 0x03,
0x09, 0x9b, 0x57, 0x83, 0x09, 0xcb, 0x42, 0x4f, 0xa0, 0x95, 0x7a, 0x29,
0x61, 0xdb, 0xaa, 0x5a, 0xb6, 0xd6, 0x9e, 0xbc,
].reverse(),
gy: [
0x9f, 0xde, 0x84, 0x21, 0xcb, 0xb9, 0xb5, 0x80, 0xbb, 0x0f, 0x31, 0x15,
0xd1, 0xc3, 0x55, 0xc9, 0x35, 0xe0, 0x04, 0x7e, 0xf7, 0x8b, 0x44, 0x73,
0xa6, 0xb6, 0x99, 0x33, 0xf1, 0xc0, 0x8f, 0xd0,
].reverse(),
cf: 1,
}
var curve_numsp256t1 = {
info: ['numsp256t1', 256, 255, 256],
name: 'numsp256t1',
type: 1,
p: [
0x43, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
].reverse(),
a: [0x01],
d: [
0x55, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
].reverse(),
order: [
0xf5, 0x4a, 0xdd, 0xee, 0x90, 0xb1, 0x47, 0x1a, 0x9b, 0x43, 0x59, 0x2f,
0xa5, 0x5a, 0x95, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
].reverse(),
gx: [
0xda, 0x13, 0xed, 0x2e, 0x90, 0xc0, 0xde, 0xa0, 0x86, 0x35, 0x08, 0xe3,
0x0e, 0x8a, 0x39, 0x0c, 0xd6, 0x9b, 0x20, 0x69, 0x5f, 0x3d, 0x1e, 0xcd,
0x7d, 0x23, 0xea, 0x6a, 0xfb, 0x14, 0x75, 0x8a,
].reverse(),
gy: [
0xe6, 0x89, 0x8a, 0x79, 0xe7, 0x16, 0xa6, 0x2f, 0xd3, 0x6e, 0x85, 0x10,
0xd8, 0x61, 0x5f, 0x71, 0x10, 0x80, 0x4b, 0xa6, 0xd9, 0x65, 0x96, 0xce,
0xc7, 0x25, 0xd9, 0xd9, 0x9f, 0x3e, 0xd5, 0x44,
].reverse(),
cf: 4,
}
var curve_numsp384d1 = {
info: ['numsp384d1', 384, 384, 384],
name: 'numsp384d1',
type: 0,
p: [
0xc3, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
].reverse(),
a: [
0xc0, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
].reverse(),
b: [
0xbb, 0x77, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
].reverse(),
order: [
0xb9, 0x61, 0x0e, 0x7b, 0xf6, 0x81, 0x4d, 0x60, 0x7a, 0xe2, 0x37, 0x4c,
0x3d, 0x9d, 0xda, 0xbe, 0x81, 0x68, 0x5d, 0xeb, 0x1e, 0xaf, 0x1e, 0xd6,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
].reverse(),
gx: [
0x2a, 0x15, 0x98, 0x20, 0x04, 0xba, 0x9c, 0xeb, 0x7b, 0xc4, 0x61, 0x0f,
0x10, 0xed, 0x2e, 0x52, 0x42, 0xc7, 0x6c, 0x2a, 0x1b, 0x29, 0xbd, 0xf3,
0xf4, 0xf9, 0x81, 0xfb, 0xcd, 0xc1, 0x25, 0x02, 0xa6, 0xf1, 0x05, 0x41,
0x22, 0xca, 0x80, 0x48, 0x1c, 0x18, 0x6f, 0xb1, 0xf0, 0x56, 0x79, 0x75,
].reverse(),
gy: [
0x16, 0x07, 0x18, 0x66, 0xec, 0xb8, 0x74, 0x5c, 0x26, 0xad, 0xf4, 0xbf,
0xdb, 0xb4, 0xd6, 0xbc, 0x7e, 0x83, 0x1a, 0x12, 0x7d, 0x83, 0x20, 0xb9,
0x9c, 0x73, 0x7f, 0xf8, 0x77, 0x69, 0x04, 0xb0, 0x7e, 0xcf, 0x84, 0x05,
0x30, 0x3d, 0xe3, 0xd7, 0x38, 0x8e, 0x9b, 0xe1, 0x68, 0xe3, 0xde, 0xac,
].reverse(),
cf: 1,
}
var curve_numsp384t1 = {
info: ['numsp384t1', 384, 382, 384],
name: 'numsp384t1',
type: 1,
p: [
0xc3, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
].reverse(),
a: [0x01],
d: [
0x9f, 0xd1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
].reverse(),
order: [
0x7d, 0x89, 0xa3, 0xe6, 0xc4, 0xdc, 0xb9, 0x20, 0x79, 0xc8, 0x35, 0xab,
0x5a, 0x55, 0xe4, 0x61, 0xcf, 0xe1, 0x6b, 0xb4, 0x1c, 0x1a, 0x47, 0xe2,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
].reverse(),
gx: [
0xde, 0x6b, 0x20, 0x6c, 0xe4, 0x40, 0xd5, 0x50, 0x13, 0x94, 0x45, 0x65,
0xb1, 0x92, 0xf2, 0x6f, 0x40, 0x63, 0x31, 0xf3, 0xa8, 0xff, 0x63, 0x57,
0x00, 0x4c, 0xbe, 0xe5, 0x46, 0xf4, 0x0b, 0xb3, 0xb5, 0x5d, 0xe5, 0x9a,
0x12, 0xa2, 0xb6, 0xc0, 0x6c, 0x26, 0xa9, 0x45, 0xfb, 0x11, 0xb1, 0x61,
].reverse(),
gy: [
0x92, 0x93, 0x72, 0xf0, 0xe1, 0x03, 0x8d, 0x9d, 0xdc, 0x48, 0xec, 0x46,
0xf9, 0xb0, 0x72, 0x00, 0x4b, 0x96, 0x45, 0xf6, 0xf7, 0x98, 0x0f, 0x83,
0x56, 0x5f, 0x42, 0xf1, 0x74, 0x82, 0xad, 0x16, 0xd7, 0x0d, 0xb1, 0x23,
0xa4, 0xb1, 0x38, 0x87, 0xb0, 0xee, 0xa6, 0xb9, 0x67, 0x3e, 0x98, 0x82,
].reverse(),
cf: 4,
}
var curve_numsp512d1 = {
info: ['numsp512d1', 512, 512, 512],
name: 'numsp512d1',
type: 0,
p: [
0xc7, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
].reverse(),
a: [
0xc4, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
].reverse(),
b: [0x9b, 0xd9, 0x01].reverse(),
order: [
0x5d, 0x55, 0x33, 0x04, 0x39, 0x3f, 0x15, 0xce, 0x43, 0xd2, 0x7c, 0x60,
0x36, 0x8b, 0x56, 0x3b, 0xc6, 0xbd, 0xd0, 0x97, 0xed, 0x58, 0xc2, 0x4f,
0x1b, 0x83, 0xe7, 0x94, 0xfb, 0xa4, 0x3c, 0x5b, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
].reverse(),
gx: [
0x57, 0xae, 0xab, 0x8c, 0x95, 0x87, 0x82, 0xdc, 0xe2, 0x5d, 0x6f, 0x7d,
0x13, 0x60, 0x5d, 0x1d, 0x83, 0x15, 0x56, 0x25, 0x86, 0x42, 0x79, 0x93,
0x9e, 0x35, 0x6b, 0x07, 0x51, 0xa1, 0x21, 0x50, 0xf9, 0xd9, 0x06, 0x53,
0xc2, 0xe0, 0x06, 0x45, 0x85, 0xf6, 0x01, 0xb5, 0x3b, 0xd8, 0xca, 0x98,
0x52, 0x3b, 0x3d, 0xa0, 0x02, 0x70, 0x2b, 0xda, 0x93, 0x0a, 0x1d, 0x14,
0x47, 0x34, 0xc0, 0x3a,
].reverse(),
gy: [
0xa6, 0x27, 0x35, 0x38, 0x60, 0x87, 0xa0, 0x23, 0xe9, 0x0f, 0xfd, 0x4c,
0x1e, 0x5c, 0x2b, 0xcf, 0x02, 0x56, 0x5a, 0xb2, 0x40, 0xa8, 0x21, 0xc1,
0xe9, 0xed, 0x0e, 0x8b, 0xda, 0x15, 0x84, 0xa2, 0x14, 0x4f, 0xd1, 0x7b,
0x0c, 0x26, 0x4b, 0x8f, 0x8c, 0xbb, 0xbc, 0xab, 0xde, 0xdb, 0x97, 0x4b,
0x00, 0xb1, 0xeb, 0x63, 0xdc, 0xee, 0x0e, 0xce, 0xb3, 0x56, 0xad, 0x29,
0xca, 0x54, 0x3a, 0x94,
].reverse(),
cf: 4,
}
var curve_numsp512t1 = {
info: ['numsp512t1', 512, 510, 512],
name: 'numsp512t1',
type: 1,
p: [
0xc7, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
].reverse(),
a: [0x01].reverse(),
d: [
0xef, 0xcb, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
].reverse(),
order: [
0x6d, 0xd4, 0xee, 0x1b, 0xf5, 0x8c, 0x46, 0x67, 0xff, 0xec, 0xef, 0x6d,
0x78, 0x05, 0x46, 0x2a, 0xf5, 0x86, 0xb6, 0x70, 0xc9, 0xd8, 0x3f, 0x9e,
0xba, 0x91, 0xcf, 0x2f, 0x6d, 0x63, 0xf0, 0xb4, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x3f,
].reverse(),
gx: [
0xfe, 0x57, 0xec, 0x99, 0x29, 0xab, 0xb9, 0xc5, 0x15, 0xf0, 0xc4, 0x7c,
0x42, 0x25, 0xe5, 0x0f, 0xad, 0x04, 0x89, 0x56, 0x92, 0xc9, 0xbd, 0x78,
0x0f, 0x73, 0x46, 0xee, 0x4e, 0xc1, 0x21, 0x46, 0x47, 0x81, 0x3b, 0x27,
0xbe, 0x7e, 0xa1, 0x27, 0x82, 0xa3, 0xc4, 0x4d, 0x9f, 0xe7, 0xd1, 0x2f,
0x33, 0xc5, 0xd3, 0x88, 0x78, 0xcb, 0x18, 0x7a, 0x9c, 0xb6, 0x8d, 0x12,
0x6d, 0x31, 0x8e, 0xdf,
].reverse(),
gy: [
0xe1, 0xf5, 0xe2, 0xc1, 0xc0, 0xde, 0x6d, 0x32, 0x1f, 0xd0, 0xf1, 0x9b,
0x8a, 0xd3, 0x66, 0x02, 0xfd, 0xc1, 0xec, 0x2a, 0x86, 0x06, 0x1a, 0x60,
0x62, 0x35, 0x96, 0xe9, 0xf2, 0x53, 0xca, 0x20, 0x41, 0x83, 0x9e, 0x90,
0x95, 0x6b, 0x2b, 0xa9, 0x22, 0x9d, 0x25, 0xd8, 0x26, 0xf7, 0x76, 0xe4,
0x6e, 0x25, 0x2a, 0xa8, 0x77, 0xf5, 0xb0, 0x98, 0x71, 0xca, 0x49, 0x9d,
0xf3, 0xbf, 0x09, 0x6d,
].reverse(),
cf: 4,
}
if (typeof cryptoECC !== 'undefined') {
cryptoECC.curves.NUMSP256D1 = curve_numsp256d1
cryptoECC.curves.NUMSP384D1 = curve_numsp384d1
cryptoECC.curves.NUMSP512D1 = curve_numsp512d1
cryptoECC.curves.NUMSP256T1 = curve_numsp256t1
cryptoECC.curves.NUMSP384T1 = curve_numsp384t1
cryptoECC.curves.NUMSP512T1 = curve_numsp512t1
}
var msrcryptoSha = function (
name,
der,
h,
k,
blockBytes,
blockFunction,
truncateTo,
) {
var utils = msrcryptoUtilities
var hv = h.slice(),
w = new Array(blockBytes),
buffer = [],
blocksProcessed = 0
function hashBlocks(message) {
var blockCount = Math.floor(message.length / blockBytes)
for (var block = 0; block < blockCount; block++) {
blockFunction(message, block, hv, k, w)
}
blocksProcessed += blockCount
return message.slice(blockCount * blockBytes)
}
function hashToBytes() {
var hash = []
for (var i = 0; i < hv.length; i++) {
hash = hash.concat(utils.int32ToBytes(hv[i]))
}
hash.length = truncateTo / 8
return hash
}
function addPadding(messageBytes) {
var padLen = blockBytes - (messageBytes.length % blockBytes)
padLen <= blockBytes / 8 && (padLen += blockBytes)
var padding = utils.getVector(padLen)
padding[0] = 128
var messageLenBits =
(messageBytes.length + blocksProcessed * blockBytes) * 8
for (var i = 1; i <= 8; i++) {
padding[padLen - i] = messageLenBits % 0x100
messageLenBits = Math.floor(messageLenBits / 0x100)
}
return messageBytes.concat(padding)
}
function computeHash(messageBytes) {
buffer = hashBlocks(messageBytes)
return finish()
}
function process(messageBytes) {
buffer = buffer.concat(messageBytes)
if (buffer.length >= blockBytes) {
buffer = hashBlocks(buffer)
}
return
}
function finish() {
if (hashBlocks(addPadding(buffer)).length !== 0) {
throw new Error('buffer.length !== 0')
}
var result = hashToBytes()
buffer = []
hv = h.slice()
blocksProcessed = 0
return result
}
return {
name: name,
computeHash: computeHash,
process: process,
finish: finish,
der: der,
hashLen: truncateTo,
maxMessageSize: 0xffffffff,
}
}
var msrcryptoSha1 = (function () {
function hashBlock(message, blockIndex, hv, k, w) {
var t,
i,
temp,
x0,
blockSize = 64,
mask = 0xffffffff
var ra = hv[0],
rb = hv[1],
rc = hv[2],
rd = hv[3],
re = hv[4]
for (i = 0; i < 16; i++) {
w[i] = utils.bytesToInt32(message, blockIndex * blockSize + i * 4)
}
for (t = 16; t < 80; t++) {
x0 = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]
w[t] = (x0 << 1) | (x0 >>> 31)
}
for (i = 0; i < 80; i++) {
temp = (ra << 5) | (ra >>> 27)
temp +=
i >= 60
? rb ^ rc ^ rd
: i >= 40
? (rb & rc) ^ (rb & rd) ^ (rc & rd)
: i >= 20
? rb ^ rc ^ rd
: (rb & rc) ^ (~rb & rd)
temp += re + k[i] + w[i]
re = rd
rd = rc
rc = (rb << 30) | (rb >>> 2)
rb = ra
ra = temp
}
hv[0] += ra & mask
hv[1] += rb & mask
hv[2] += rc & mask
hv[3] += rd & mask
hv[4] += re & mask
return hv
}
var utils = msrcryptoUtilities,
upd = utils.unpackData,
h = upd('Z0UjAe/Nq4mYutz+EDJUdsPS4fA=', 4, 1),
k = upd(
'WoJ5mVqCeZlagnmZWoJ5mVqCeZlagnmZWoJ5mVqCeZlagnmZWoJ5mVqCeZlagnmZWoJ5mVqCeZlagnmZWoJ5mVqCeZlagnmZWoJ5mVqCeZlu2euhbtnroW7Z66Fu2euhbtnroW7Z66Fu2euhbtnroW7Z66Fu2euhbtnroW7Z66Fu2euhbtnroW7Z66Fu2euhbtnroW7Z66Fu2euhbtnroY8bvNyPG7zcjxu83I8bvNyPG7zcjxu83I8bvNyPG7zcjxu83I8bvNyPG7zcjxu83I8bvNyPG7zcjxu83I8bvNyPG7zcjxu83I8bvNyPG7zcymLB1spiwdbKYsHWymLB1spiwdbKYsHWymLB1spiwdbKYsHWymLB1spiwdbKYsHWymLB1spiwdbKYsHWymLB1spiwdbKYsHWymLB1spiwdY',
4,
1,
),
der = upd('MCEwCQYFKw4DAhoFAAQU')
return {
sha1: function () {
return msrcryptoSha('SHA-1', der, h, k, 64, hashBlock, 160)
},
}
})()
if (typeof operations !== 'undefined') {
msrcryptoSha1.instances = {}
msrcryptoSha1.getInstance = function (id) {
return (
msrcryptoSha1.instances[id] ||
(msrcryptoSha1.instances[id] = msrcryptoSha1.sha1())
)
}
msrcryptoSha1.deleteInstance = function (id) {
msrcryptoSha1.instances[id] = null
delete msrcryptoSha1.instances[id]
}
msrcryptoSha1.hash = function (p) {
if (p.operationSubType === 'process') {
msrcryptoSha1.sha1.process(p.buffer)
return
}
if (p.operationSubType === 'finish') {
return msrcryptoSha1.sha1.finish()
}
return msrcryptoSha1.sha1().computeHash(p.buffer)
}
operations.register('digest', 'SHA-1', msrcryptoSha1.hash)
}
msrcryptoHashFunctions['SHA-1'] = msrcryptoSha1.sha1
var msrcryptoSha256 = (function () {
var utils = msrcryptoUtilities
function hashBlock(message, blockIndex, hv, k, w) {
var t,
i,
temp,
x0,
x1,
blockSize = 64,
mask = 0xffffffff
var ra = hv[0],
rb = hv[1],
rc = hv[2],
rd = hv[3],
re = hv[4],
rf = hv[5],
rg = hv[6],
rh = hv[7]
for (i = 0; i < 16; i++) {
w[i] = utils.bytesToInt32(message, blockIndex * blockSize + i * 4)
}
for (t = 16; t < 64; t++) {
x0 = w[t - 15]
x1 = w[t - 2]
w[t] =
(((x1 >>> 17) | (x1 << 15)) ^
((x1 >>> 19) | (x1 << 13)) ^
(x1 >>> 10)) +
w[t - 7] +
(((x0 >>> 7) | (x0 << 25)) ^
((x0 >>> 18) | (x0 << 14)) ^
(x0 >>> 3)) +
w[t - 16]
w[t] = w[t] & mask
}
for (i = 0; i < 64; i++) {
temp =
rh +
(((re >>> 6) | (re << 26)) ^
((re >>> 11) | (re << 21)) ^
((re >>> 25) | (re << 7))) +
((re & rf) ^ (~re & rg)) +
k[i] +
w[i]
rd += temp
temp +=
(((ra >>> 2) | (ra << 30)) ^
((ra >>> 13) | (ra << 19)) ^
((ra >>> 22) | (ra << 10))) +
((ra & (rb ^ rc)) ^ (rb & rc))
rh = rg
rg = rf
rf = re
re = rd
rd = rc
rc = rb
rb = ra
ra = temp
}
hv[0] = (hv[0] + ra) >>> 0
hv[1] = (hv[1] + rb) >>> 0
hv[2] = (hv[2] + rc) >>> 0
hv[3] = (hv[3] + rd) >>> 0
hv[4] = (hv[4] + re) >>> 0
hv[5] = (hv[5] + rf) >>> 0
hv[6] = (hv[6] + rg) >>> 0
hv[7] = (hv[7] + rh) >>> 0
return hv
}
var k256,
h224,
h256,
der224,
der256,
upd = utils.unpackData
h224 = upd('wQWe2DZ81QcwcN0X9w5ZOf/ACzFoWBURZPmPp776T6Q', 4, 1)
h256 = upd('agnmZ7tnroU8bvNypU/1OlEOUn+bBWiMH4PZq1vgzRk', 4, 1)
k256 = upd(
'QoovmHE3RJG1wPvP6bXbpTlWwltZ8RHxkj+CpKscXtXYB6qYEoNbASQxhb5VDH3Dcr5ddIDesf6b3AanwZvxdOSbacHvvkeGD8GdxiQMocwt6SxvSnSEqlywqdx2+YjamD5RUqgxxm2wAyfIv1l/x8bgC/PVp5FHBspjURQpKWcntwqFLhshOE0sbfxTOA0TZQpzVHZqCruBwskuknIshaK/6KGoGmZLwkuLcMdsUaPRkugZ1pkGJPQONYUQaqBwGaTBFh43bAgnSHdMNLC8tTkcDLNO2KpKW5zKT2gub/N0j4LueKVjb4TIeBSMxwIIkL7/+qRQbOu++aP3xnF48g',
4,
1,
)
der224 = upd('MC0wDQYJYIZIAWUDBAIEBQAEHA')
der256 = upd('MDEwDQYJYIZIAWUDBAIBBQAEIA')
return {
sha224: function () {
return msrcryptoSha('SHA-224', der224, h224, k256, 64, hashBlock, 224)
},
sha256: function () {
return msrcryptoSha('SHA-256', der256, h256, k256, 64, hashBlock, 256)
},
}
})()
if (typeof operations !== 'undefined') {
msrcryptoSha256.instance224 =
msrcryptoSha256.instance224 || msrcryptoSha256.sha224()
msrcryptoSha256.instance256 =
msrcryptoSha256.instance256 || msrcryptoSha256.sha256()
msrcryptoSha256.instances = {}
msrcryptoSha256.getInstance224 = function (id) {
return (
msrcryptoSha256.instances[id] ||
(msrcryptoSha256.instances[id] = msrcryptoSha256.sha224())
)
}
msrcryptoSha256.getInstance256 = function (id) {
return (
msrcryptoSha256.instances[id] ||
(msrcryptoSha256.instances[id] = msrcryptoSha256.sha256())
)
}
msrcryptoSha256.deleteInstance = function (id) {
msrcryptoSha256.instances[id] = null
delete msrcryptoSha256.instances[id]
}
msrcryptoSha256.hash256 = function (p) {
if (p.operationSubType === 'process') {
msrcryptoSha256.getInstance256(p.workerid).process(p.buffer)
return null
}
if (p.operationSubType === 'finish') {
var result = msrcryptoSha256.getInstance256(p.workerid).finish()
msrcryptoSha256.deleteInstance(p.workerid)
return result
}
if (p.operationSubType === 'abort') {
msrcryptoSha256.deleteInstance(p.workerid)
return
}
return msrcryptoSha256.instance256.computeHash(p.buffer)
}
msrcryptoSha256.hash224 = function (p) {
if (p.operationSubType === 'process') {
msrcryptoSha256.getInstance224(p.workerid).process(p.buffer)
return
}
if (p.operationSubType === 'finish') {
var result = msrcryptoSha256.getInstance224(p.workerid).finish()
}
if (p.operationSubType === 'abort') {
msrcryptoSha224.deleteInstance(p.workerid)
return
}
return msrcryptoSha256.instance224.computeHash(p.buffer)
}
operations.register('digest', 'SHA-224', msrcryptoSha256.hash224)
operations.register('digest', 'SHA-256', msrcryptoSha256.hash256)
}
msrcryptoHashFunctions['SHA-224'] = msrcryptoSha256.sha224
msrcryptoHashFunctions['SHA-256'] = msrcryptoSha256.sha256
var msrcryptoSha512 = (function () {
var utils = msrcryptoUtilities
function add(x0, x1, y0, y1, resultArray) {
var lowSum = (x1 + y1) | 0
var carry = lowSum >>> 0 < y1 >>> 0
resultArray[0] = (x0 + y0 + carry) | 0
resultArray[1] = lowSum
return
}
function hashBlock(message, blockIndex, hv, k, w) {
var t,
i,
blockBytes = 128,
tah,
tal,
tbh,
tbl,
xh,
xl,
tc = [],
td = [],
te = [],
index
var ah = hv[0],
al = hv[1],
bh = hv[2],
bl = hv[3],
ch = hv[4],
cl = hv[5],
dh = hv[6],
dl = hv[7],
eh = hv[8],
el = hv[9],
fh = hv[10],
fl = hv[11],
gh = hv[12],
gl = hv[13],
hh = hv[14],
hl = hv[15]
for (t = 0; t < 32; t++) {
index = blockIndex * blockBytes + t * 4
w[t] = message.slice(index, index + 4)
w[t] = (w[t][0] << 24) | (w[t][1] << 16) | (w[t][2] << 8) | w[t][3]
}
for (t = 32; t < 160; t += 2) {
xh = w[t - 30]
xl = w[t - 29]
tah =
((xh >>> 1) | (xl << 31)) ^ ((xh >>> 8) | (xl << 24)) ^ (xh >>> 7)
tal =
((xl >>> 1) | (xh << 31)) ^
((xl >>> 8) | (xh << 24)) ^
((xl >>> 7) | (xh << 25))
xh = w[t - 4]
xl = w[t - 3]
tbh =
((xh >>> 19) | (xl << 13)) ^ ((xl >>> 29) | (xh << 3)) ^ (xh >>> 6)
tbl =
((xl >>> 19) | (xh << 13)) ^
((xh >>> 29) | (xl << 3)) ^
((xl >>> 6) | (xh << 26))
add(tbh, tbl, w[t - 14], w[t - 13], tc)
add(tah, tal, tc[0], tc[1], tc)
add(w[t - 32], w[t - 31], tc[0], tc[1], tc)
w[t] = tc[0]
w[t + 1] = tc[1]
}
for (i = 0; i < 160; i += 2) {
tah =
((eh >>> 14) | (el << 18)) ^
((eh >>> 18) | (el << 14)) ^
((el >>> 9) | (eh << 23))
tal =
((el >>> 14) | (eh << 18)) ^
((el >>> 18) | (eh << 14)) ^
((eh >>> 9) | (el << 23))
tbh = (eh & fh) ^ (gh & ~eh)
tbl = (el & fl) ^ (gl & ~el)
add(hh, hl, tah, tal, tc)
add(tbh, tbl, k[i], k[i + 1], td)
add(tc[0], tc[1], w[i], w[i + 1], te)
add(td[0], td[1], te[0], te[1], te)
add(te[0], te[1], dh, dl, tc)
dh = tc[0]
dl = tc[1]
tal =
((al >>> 28) | (ah << 4)) ^
((ah >>> 2) | (al << 30)) ^
((ah >>> 7) | (al << 25))
tah =
((ah >>> 28) | (al << 4)) ^
((al >>> 2) | (ah << 30)) ^
((al >>> 7) | (ah << 25))
tbl = (al & (bl ^ cl)) ^ (bl & cl)
tbh = (ah & (bh ^ ch)) ^ (bh & ch)
add(te[0], te[1], tah, tal, tc)
tah = tc[0]
tal = tc[1]
add(tbh, tbl, tah, tal, tc)
tah = tc[0]
tal = tc[1]
hh = gh
hl = gl
gh = fh
gl = fl
fh = eh
fl = el
eh = dh
el = dl
dh = ch
dl = cl
ch = bh
cl = bl
bh = ah
bl = al
ah = tah
al = tal
}
add(hv[0], hv[1], ah, al, tc)
hv[0] = tc[0]
hv[1] = tc[1]
add(hv[2], hv[3], bh, bl, tc)
hv[2] = tc[0]
hv[3] = tc[1]
add(hv[4], hv[5], ch, cl, tc)
hv[4] = tc[0]
hv[5] = tc[1]
add(hv[6], hv[7], dh, dl, tc)
hv[6] = tc[0]
hv[7] = tc[1]
add(hv[8], hv[9], eh, el, tc)
hv[8] = tc[0]
hv[9] = tc[1]
add(hv[10], hv[11], fh, fl, tc)
hv[10] = tc[0]
hv[11] = tc[1]
add(hv[12], hv[13], gh, gl, tc)
hv[12] = tc[0]
hv[13] = tc[1]
add(hv[14], hv[15], hh, hl, tc)
hv[14] = tc[0]
hv[15] = tc[1]
return hv
}
var h384,
h512,
k512,
der384,
der512,
der512_224,
der512_256,
upd = utils.unpackData
h384 = upd(
'y7udXcEFnthimikqNnzVB5FZAVowcN0XFS/s2PcOWTlnMyZn/8ALMY60SodoWBUR2wwuDWT5j6dHtUgdvvpPpA==',
4,
1,
)
h512 = upd(
'agnmZ/O8yQi7Z66FhMqnOzxu83L+lPgrpU/1Ol8dNvFRDlJ/reaC0ZsFaIwrPmwfH4PZq/tBvWtb4M0ZE34heQ',
4,
1,
)
k512 = upd(
'QoovmNcoriJxN0SRI+9lzbXA+8/sTTsv6bXbpYGJ27w5VsJb80i1OFnxEfG2BdAZkj+CpK8ZT5urHF7' +
'V2m2BGNgHqpijAwJCEoNbAUVwb74kMYW+TuSyjFUMfcPV/7Ticr5ddPJ7iW+A3rH+OxaWsZvcBqclxx' +
'I1wZvxdM9pJpTkm2nBnvFK0u++R4Y4TyXjD8GdxouM1bUkDKHMd6ycZS3pLG9ZKwJ1SnSEqm6m5INcs' +
'KncvUH71Hb5iNqDEVO1mD5RUu5m36uoMcZtLbQyELADJ8iY+yE/v1l/x77vDuTG4AvzPaiPwtWnkUeT' +
'CqclBspjUeADgm8UKSlnCg5ucCe3CoVG0i/8LhshOFwmySZNLG38WsQq7VM4DROdlbPfZQpzVIuvY95' +
'2agq7PHeyqIHCyS5H7a7mknIshRSCNTuiv+ihTPEDZKgaZku8QjABwkuLcND4l5HHbFGjBlS+MNGS6B' +
'nW71IY1pkGJFVlqRD0DjWFV3EgKhBqoHAyu9G4GaTBFrjS0MgeN2wIUUGrUydId0zfjuuZNLC8teGbS' +
'Kg5HAyzxclaY07YqkrjQYrLW5zKT3dj43NoLm/z1rK4o3SPgu5d77L8eKVjb0MXL2CEyHgUofCrcozH' +
'AggaZDnskL7/+iNjHiikUGzr3oK96b75o/eyxnkVxnF48uNyUyvKJz7O6iZhnNGGuMchwMIH6tp91s3' +
'g6x71fU9/7m7ReAbwZ6pyF2+6CmN9xaLImKYRP5gEvvkNrhtxCzUTHEcbKNt39SMEfYQyyqt7QMckkz' +
'yevgoVyb68Qx1nxJwQDUxMxdS+yz5Ctll/KZz8ZX4qX8tvqzrW+uxsRBmMSkdYFw==',
4,
1,
)
der384 = upd('MEEwDQYJYIZIAWUDBAICBQAEMA')
der512 = upd('MFEwDQYJYIZIAWUDBAIDBQAEQA')
der512_224 = upd('MC0wDQYJYIZIAWUDBAIFBQAEHA')
der512_256 = upd('MDEwDQYJYIZIAWUDBAIGBQAEIA')
return {
sha384: function () {
return msrcryptoSha(
'SHA-384',
der384,
h384,
k512,
128,
hashBlock,
384,
)
},
sha512: function () {
return msrcryptoSha(
'SHA-512',
der512,
h512,
k512,
128,
hashBlock,
512,
)
},
sha512_224: function () {
return msrcryptoSha(
'SHA-512.224',
der512_224,
h512,
k512,
128,
hashBlock,
224,
)
},
sha512_256: function () {
return msrcryptoSha(
'SHA-512.256',
der512_256,
h512,
k512,
128,
hashBlock,
256,
)
},
}
})()
if (typeof operations !== 'undefined') {
msrcryptoSha512.instances = {}
msrcryptoSha512.getInstance384 = function (id) {
return (
msrcryptoSha512.instances[id] ||
(msrcryptoSha512.instances[id] = msrcryptoSha512.sha384())
)
}
msrcryptoSha512.getInstance512 = function (id) {
return (
msrcryptoSha512.instances[id] ||
(msrcryptoSha512.instances[id] = msrcryptoSha512.sha512())
)
}
msrcryptoSha512.deleteInstance = function (id) {
msrcryptoSha512.instances[id] = null
delete msrcryptoSha512.instances[id]
}
msrcryptoSha512.hash384 = function (p) {
if (p.operationSubType === 'process') {
msrcryptoSha512.sha384.process(p.buffer)
return
}
if (p.operationSubType === 'finish') {
return msrcryptoSha512.sha384.finish()
}
return msrcryptoSha512.sha384().computeHash(p.buffer)
}
msrcryptoSha512.hash512 = function (p) {
if (p.operationSubType === 'process') {
msrcryptoSha512.sha512.process(p.buffer)
return
}
if (p.operationSubType === 'finish') {
return msrcryptoSha512.sha512.finish()
}
return msrcryptoSha512.sha512().computeHash(p.buffer)
}
operations.register('digest', 'SHA-384', msrcryptoSha512.hash384)
operations.register('digest', 'SHA-512', msrcryptoSha512.hash512)
}
msrcryptoHashFunctions['SHA-384'] = msrcryptoSha512.sha384
msrcryptoHashFunctions['SHA-512'] = msrcryptoSha512.sha512
var msrcryptoHmac = function (keyBytes, hashFunction) {
var blockSize =
{
384: 128,
512: 128,
}[hashFunction.name.replace(/SHA-/, '')] || 64
var ipad
var opad
var paddedKey = padKey()
var keyXorOpad
var keyXorIpad
var k0IpadText
function xorArrays(array1, array2) {
var newArray = new Array(array1)
for (var j = 0; j < array1.length; j++) {
newArray[j] = array1[j] ^ array2[j]
}
return newArray
}
function padZeros(bytes, paddedLength) {
var paddedArray = bytes.slice()
for (var j = bytes.length; j < paddedLength; j++) {
paddedArray.push(0)
}
return paddedArray
}
function padKey() {
if (keyBytes.length === blockSize) {
return keyBytes
}
if (keyBytes.length > blockSize) {
return padZeros(hashFunction.computeHash(keyBytes), blockSize)
}
return padZeros(keyBytes, blockSize)
}
function processHmac(messageBytes) {
if (!k0IpadText) {
k0IpadText = keyXorIpad.concat(messageBytes)
hashFunction.process(k0IpadText)
} else {
hashFunction.process(messageBytes)
}
return
}
function finishHmac() {
var hashK0IpadText = hashFunction.finish()
var k0IpadK0OpadText = keyXorOpad.concat(hashK0IpadText)
return hashFunction.computeHash(k0IpadK0OpadText)
}
function clearState() {
keyBytes = null
hashFunction = null
paddedKey = null
}
ipad = new Array(blockSize)
opad = new Array(blockSize)
for (var i = 0; i < blockSize; i++) {
ipad[i] = 0x36
opad[i] = 0x5c
}
keyXorIpad = xorArrays(paddedKey, ipad)
keyXorOpad = xorArrays(paddedKey, opad)
return {
computeHmac: function (dataBytes, key, hashAlgorithm) {
processHmac(dataBytes)
var result = finishHmac()
clearState()
return result
},
process: function (dataBytes, key, hashAlgorithm) {
processHmac(dataBytes)
return null
},
finish: function (key, hashAlgorithm) {
var result = finishHmac()
clearState()
return result
},
}
}
if (typeof operations !== 'undefined') {
var hmacInstances = {}
msrcryptoHmac.signHmac = function (p) {
var hashName = p.keyHandle.algorithm.hash.name.toUpperCase(),
hashAlg = msrcryptoHashFunctions[hashName](),
result,
id = p.workerid
if (!hmacInstances[id]) {
hmacInstances[id] = msrcryptoHmac(p.keyData, hashAlg)
}
if (p.operationSubType === 'process') {
hmacInstances[id].process(p.buffer)
return null
}
if (p.operationSubType === 'finish') {
result = hmacInstances[id].finish()
hmacInstances[id] = null
return result
}
result = hmacInstances[id].computeHmac(p.buffer)
hmacInstances[id] = null
return result
}
msrcryptoHmac.verifyHmac = function (p) {
var hashName = p.keyHandle.algorithm.hash.name.toUpperCase(),
hashAlg = msrcryptoHashFunctions[hashName](),
result,
id = p.workerid
if (!hmacInstances[id]) {
hmacInstances[id] = msrcryptoHmac(p.keyData, hashAlg)
}
if (p.operationSubType === 'process') {
hmacInstances[id].process(p.buffer)
return null
}
if (p.operationSubType === 'finish') {
result = hmacInstances[id].finish()
result = msrcryptoUtilities.arraysEqual(result, p.signature)
hmacInstances[id] = null
return result
}
result = hmacInstances[id].computeHmac(p.buffer)
result = msrcryptoUtilities.arraysEqual(result, p.signature)
hmacInstances[id] = null
return result
}
msrcryptoHmac.generateKey = function (p) {
var defaultKeyLengths = {
'SHA-1': 64,
'SHA-224': 64,
'SHA-256': 64,
'SHA-384': 128,
'SHA-512': 128,
}
var keyLength = p.algorithm.length
if (!keyLength) {
keyLength = defaultKeyLengths[p.algorithm.hash.name.toUpperCase()]
}
return {
type: 'keyGeneration',
keyData: msrcryptoPseudoRandom.getBytes(keyLength),
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable,
usages: null || p.usages,
type: 'secret',
},
}
}
msrcryptoHmac.importKey = function (p) {
var keyObject,
keyBits = p.keyData.length * 8
if (p.format === 'jwk') {
keyObject = msrcryptoJwk.jwkToKey(p.keyData, p.algorithm, ['k'])
keyObject.alg = keyObject.alg.replace('HS', 'SHA-')
} else if (p.format === 'raw') {
keyObject = {
k: msrcryptoUtilities.toArray(p.keyData),
}
} else {
throw new Error('unsupported import format')
}
return {
type: 'keyImport',
keyData: keyObject.k,
keyHandle: {
algorithm: {
name: 'HMAC',
hash: {
name: p.algorithm.hash.name,
},
},
extractable: p.extractable || keyObject.extractable,
usages: p.usages,
type: 'secret',
},
}
}
msrcryptoHmac.exportKey = function (p) {
if (p.format === 'jwk') {
return {
type: 'keyExport',
keyHandle: msrcryptoJwk.keyToJwk(p.keyHandle, p.keyData),
}
}
if (p.format === 'raw') {
return {
type: 'keyExport',
keyHandle: p.keyData,
}
}
throw new Error('unsupported export format')
}
operations.register('importKey', 'HMAC', msrcryptoHmac.importKey)
operations.register('exportKey', 'HMAC', msrcryptoHmac.exportKey)
operations.register('generateKey', 'HMAC', msrcryptoHmac.generateKey)
operations.register('sign', 'HMAC', msrcryptoHmac.signHmac)
operations.register('verify', 'HMAC', msrcryptoHmac.verifyHmac)
}
var msrcryptoBlockCipher = (function () {
var aesConstants,
x2,
x3,
x14,
x13,
x11,
x9,
sBoxTable,
invSBoxTable,
rConTable
return {
aes: function (keyBytes) {
if (!aesConstants) {
aesConstants = msrcryptoUtilities.unpackData(
'AAIEBggKDA4QEhQWGBocHiAiJCYoKiwuMDI0Njg6PD5AQkRGSEpMTlBSVFZYWlxeYGJkZmhqbG5wcnR2eHp8foCChIaIioyOkJKUlpianJ6goqSmqKqsrrCytLa4ury+wMLExsjKzM7Q0tTW2Nrc3uDi5Obo6uzu8PL09vj6/P4bGR8dExEXFQsJDw0DAQcFOzk/PTMxNzUrKS8tIyEnJVtZX11TUVdVS0lPTUNBR0V7eX99c3F3dWtpb21jYWdlm5mfnZORl5WLiY+Ng4GHhbu5v72zsbe1q6mvraOhp6Xb2d/d09HX1cvJz83DwcfF+/n//fPx9/Xr6e/t4+Hn5QADBgUMDwoJGBseHRQXEhEwMzY1PD86OSgrLi0kJyIhYGNmZWxvaml4e359dHdycVBTVlVcX1pZSEtOTURHQkHAw8bFzM/Kydjb3t3U19LR8PP29fz/+vno6+7t5Ofi4aCjpqWsr6qpuLu+vbS3srGQk5aVnJ+amYiLjo2Eh4KBm5idnpeUkZKDgIWGj4yJiquora6npKGis7C1tr+8ubr7+P3+9/Tx8uPg5ebv7Onqy8jNzsfEwcLT0NXW39zZ2ltYXV5XVFFSQ0BFRk9MSUpraG1uZ2RhYnNwdXZ/fHl6Ozg9Pjc0MTIjICUmLywpKgsIDQ4HBAECExAVFh8cGRoADhwSODYkKnB+bGJIRlRa4O788tjWxMqQnoyCqKa0utvVx8nj7f/xq6W3uZOdj4E7NScpAw0fEUtFV1lzfW9hraOxv5WbiYfd08HP5ev5901DUV91e2lnPTMhLwULGRd2eGpkTkBSXAYIGhQ+MCIslpiKhK6gsrzm6Pr03tDCzEFPXVN5d2VrMT8tIwkHFRuhr72zmZeFi9HfzcPp5/X7mpSGiKKsvrDq5Pb40tzOwHp0ZmhCTF5QCgQWGDI8LiDs4vD+1NrIxpySgI6kqri2DAIQHjQ6KCZ8cmBuREpYVjc5KyUPARMdR0lbVX9xY23X2cvF7+Hz/aepu7WfkYONAA0aFzQ5LiNoZXJ/XFFGS9Ddysfk6f7zuLWir4yBlpu7tqGsj4KVmNPeycTn6v3wa2ZxfF9SRUgDDhkUNzotIG1gd3pZVENOBQgfEjE8Kya9sKeqiYSTntXYz8Lh7Pv21tvMweLv+PW+s6SpioeQnQYLHBEyPyglbmN0eVpXQE3a18DN7uP0+bK/qKWGi5yRCgcQHT4zJClib3h1VltMQWFse3ZVWE9CCQQTHj0wJyqxvKumhYifktnUw87t4Pf6t7qtoIOOmZTf0sXI6+bx/GdqfXBTXklEDwIVGDs2ISwMARYbODUiL2RpfnNQXUpH3NHGy+jl8v+0ua6jgI2alwALFh0sJzoxWFNORXR/Ymmwu6atnJeKgejj/vXEz9LZe3BtZldcQUojKDU+DwQZEsvA3dbn7PH6k5iFjr+0qaL2/eDr2tHMx66luLOCiZSfRk1QW2phfHceFQgDMjkkL42Gm5Chqre81d7DyPny7+Q9NisgERoHDGVuc3hJQl9U9/zh6tvQzcavpLmyg4iVnkdMUVprYH12HxQJAjM4JS6Mh5qRoKu2vdTfwsn48+7lPDcqIRAbBg1kb3J5SENeVQEKFxwtJjswWVJPRHV+Y2ixuqesnZaLgOni//TFztPYenFsZ1ZdQEsiKTQ/DgUYE8rB3Nfm7fD7kpmEj761qKMACRIbJC02P0hBWlNsZX53kJmCi7S9pq/Y0crD/PXu5zsyKSAfFg0Ec3phaFdeRUyrormwj4adlOPq8fjHztXcdn9kbVJbQEk+NywlGhMIAebv9P3Cy9DZrqe8tYqDmJFNRF9WaWB7cgUMFx4hKDM63dTPxvnw6+KVnIeOsbijquzl/vfIwdrTpK22v4CJkpt8dW5nWFFKQzQ9Ji8QGQIL197FzPP64eiflo2Eu7KpoEdOVVxjanF4DwYdFCsiOTCak4iBvrespdLbwMn2/+TtCgMYES4nPDVCS1BZZm90faGos7qFjJee6eD78s3E39YxOCMqFRwHDnlwa2JdVE9GY3x3e/Jrb8UwAWcr/terdsqCyX36WUfwrdSir5ykcsC3/ZMmNj/3zDSl5fFx2DEVBMcjwxiWBZoHEoDi6yeydQmDLBobblqgUjvWsynjL4RT0QDtIPyxW2rLvjlKTFjP0O+q+0NNM4VF+QJ/UDyfqFGjQI+SnTj1vLbaIRD/89LNDBPsX5dEF8Snfj1kXRlzYIFP3CIqkIhG7rgU3l4L2+AyOgpJBiRcwtOsYpGV5HnnyDdtjdVOqWxW9Opleq4IunglLhymtMbo3XQfS72LinA+tWZIA/YOYTVXuYbBHZ7h+JgRadmOlJseh+nOVSjfjKGJDb/mQmhBmS0PsFS7FlIJatUwNqU4v0CjnoHz1/t84zmCmy//hzSOQ0TE3unLVHuUMqbCIz3uTJULQvrDTgguoWYo2SSydluiSW2L0SVy+PZkhmiYFtSkXMxdZbaSbHBIUP3tudpeFUZXp42dhJDYqwCMvNMK9+RYBbizRQbQLB6Pyj8PAsGvvQMBE4prOpERQU9n3OqX8s/O8LTmc5asdCLnrTWF4vk36Bx1325H8RpxHSnFiW+3Yg6qGL4b/FY+S8bSeSCa28D+eM1a9B/dqDOIB8cxsRIQWSeA7F9gUX+pGbVKDS3lep+TyZzvoOA7Ta4q9bDI67s8g1OZYRcrBH66d9Ym4WkUY1UhDH2NAQIECBAgQIAbNmzYq02aL168Y8aXNWrUs33678WROXLk071hwp8lSpQzZsyDHTp06MuNAQIECBAgQIAbNmzYq02aL168Y8aXNWrUs33678WROXLk071hwp8lSpQzZsyDHTp06MuNAQIECBAgQIAbNmzYq02aL168Y8aXNWrUs33678WROXLk071hwp8lSpQzZsyDHTp06MuNAQIECBAgQIAbNmzYq02aL168Y8aXNWrUs33678WROXLk071hwp8lSpQzZsyDHTp06MuNAQIECBAgQIAbNmzYq02aL168Y8aXNWrUs33678WROXLk071hwp8lSpQzZsyDHTp06MuN',
256,
false,
)
x2 = aesConstants[0]
x3 = aesConstants[1]
x14 = aesConstants[2]
x13 = aesConstants[3]
x11 = aesConstants[4]
x9 = aesConstants[5]
sBoxTable = aesConstants[6]
invSBoxTable = aesConstants[7]
rConTable = aesConstants[8]
}
var blockSize = 128,
keyLength,
nK,
nB = 4,
nR,
key
keyLength = keyBytes.length * 8
switch (keyLength) {
case 128:
case 192:
case 256:
break
default:
throw new Error('Unsupported keyLength')
}
nK = keyLength / 32
nR = nK + 6
var shiftRows = function (a) {
var tmp = a[1]
a[1] = a[5]
a[5] = a[9]
a[9] = a[13]
a[13] = tmp
tmp = a[2]
a[2] = a[10]
a[10] = tmp
tmp = a[6]
a[6] = a[14]
a[14] = tmp
tmp = a[15]
a[15] = a[11]
a[11] = a[7]
a[7] = a[3]
a[3] = tmp
}
var invShiftRows = function (a) {
var tmp = a[13]
a[13] = a[9]
a[9] = a[5]
a[5] = a[1]
a[1] = tmp
tmp = a[10]
a[10] = a[2]
a[2] = tmp
tmp = a[14]
a[14] = a[6]
a[6] = tmp
tmp = a[3]
a[3] = a[7]
a[7] = a[11]
a[11] = a[15]
a[15] = tmp
}
var mixColumns = function (state) {
var a = state[0],
b = state[1],
c = state[2],
d = state[3],
e = state[4],
f = state[5],
g = state[6],
h = state[7],
i = state[8],
j = state[9],
k = state[10],
l = state[11],
m = state[12],
n = state[13],
o = state[14],
p = state[15]
state[0] = x2[a] ^ x3[b] ^ c ^ d
state[1] = a ^ x2[b] ^ x3[c] ^ d
state[2] = a ^ b ^ x2[c] ^ x3[d]
state[3] = x3[a] ^ b ^ c ^ x2[d]
state[4] = x2[e] ^ x3[f] ^ g ^ h
state[5] = e ^ x2[f] ^ x3[g] ^ h
state[6] = e ^ f ^ x2[g] ^ x3[h]
state[7] = x3[e] ^ f ^ g ^ x2[h]
state[8] = x2[i] ^ x3[j] ^ k ^ l
state[9] = i ^ x2[j] ^ x3[k] ^ l
state[10] = i ^ j ^ x2[k] ^ x3[l]
state[11] = x3[i] ^ j ^ k ^ x2[l]
state[12] = x2[m] ^ x3[n] ^ o ^ p
state[13] = m ^ x2[n] ^ x3[o] ^ p
state[14] = m ^ n ^ x2[o] ^ x3[p]
state[15] = x3[m] ^ n ^ o ^ x2[p]
}
var invMixColumns = function (state) {
var a = state[0],
b = state[1],
c = state[2],
d = state[3],
e = state[4],
f = state[5],
g = state[6],
h = state[7],
i = state[8],
j = state[9],
k = state[10],
l = state[11],
m = state[12],
n = state[13],
o = state[14],
p = state[15]
state[0] = x14[a] ^ x11[b] ^ x13[c] ^ x9[d]
state[1] = x9[a] ^ x14[b] ^ x11[c] ^ x13[d]
state[2] = x13[a] ^ x9[b] ^ x14[c] ^ x11[d]
state[3] = x11[a] ^ x13[b] ^ x9[c] ^ x14[d]
state[4] = x14[e] ^ x11[f] ^ x13[g] ^ x9[h]
state[5] = x9[e] ^ x14[f] ^ x11[g] ^ x13[h]
state[6] = x13[e] ^ x9[f] ^ x14[g] ^ x11[h]
state[7] = x11[e] ^ x13[f] ^ x9[g] ^ x14[h]
state[8] = x14[i] ^ x11[j] ^ x13[k] ^ x9[l]
state[9] = x9[i] ^ x14[j] ^ x11[k] ^ x13[l]
state[10] = x13[i] ^ x9[j] ^ x14[k] ^ x11[l]
state[11] = x11[i] ^ x13[j] ^ x9[k] ^ x14[l]
state[12] = x14[m] ^ x11[n] ^ x13[o] ^ x9[p]
state[13] = x9[m] ^ x14[n] ^ x11[o] ^ x13[p]
state[14] = x13[m] ^ x9[n] ^ x14[o] ^ x11[p]
state[15] = x11[m] ^ x13[n] ^ x9[o] ^ x14[p]
}
var xorWord = function (a, b) {
return [a[0] ^ b[0], a[1] ^ b[1], a[2] ^ b[2], a[3] ^ b[3]]
}
var addRoundKey = function (state, keySchedule, offset) {
for (var i = 0; i < state.length; i += 1) {
state[i] ^= keySchedule[i + offset]
}
}
var rotWord = function (word) {
var a = word[0]
word[0] = word[1]
word[1] = word[2]
word[2] = word[3]
word[3] = a
}
var subWord = function (word) {
for (var i = 0; i < word.length; i += 1) {
word[i] = sBoxTable[word[i]]
}
}
var invSubWord = function (word) {
for (var i = 0; i < word.length; i += 1) {
word[i] = invSBoxTable[word[i]]
}
}
var getWord = function (tab, i) {
return [tab[4 * i], tab[4 * i + 1], tab[4 * i + 2], tab[4 * i + 3]]
}
var setWord = function (left, right, indexL, indexR) {
left[4 * indexL] = right[4 * indexR]
left[4 * indexL + 1] = right[4 * indexR + 1]
left[4 * indexL + 2] = right[4 * indexR + 2]
left[4 * indexL + 3] = right[4 * indexR + 3]
}
var expandKey = function (keyIn) {
var temp,
res = [],
i = 0
while (i < 4 * nK) {
res.push(keyIn[i++])
}
i = nK
while (i < nB * (nR + 1)) {
temp = getWord(res, i - 1)
if (i % nK === 0) {
var index = i / nK
var rcon = [rConTable[index], 0, 0, 0]
rotWord(temp)
subWord(temp)
temp = xorWord(temp, rcon)
} else if (nK > 6 && i % nK === 4) {
subWord(temp)
}
var newWord = xorWord(getWord(res, i - nK), temp)
setWord(res, newWord, i, 0)
i += 1
}
return res
}
key = expandKey(keyBytes)
return {
encrypt: function (dataBytes) {
var state = dataBytes,
round
addRoundKey(state, key, 0)
for (round = 1; round <= nR - 1; round += 1) {
subWord(state)
shiftRows(state)
mixColumns(state)
addRoundKey(state, key, 4 * round * nB)
}
subWord(state)
shiftRows(state)
addRoundKey(state, key, 4 * nR * nB)
return state
},
decrypt: function (dataBytes) {
var state = dataBytes,
round
addRoundKey(state, key, 4 * nR * nB)
for (round = nR - 1; round >= 1; round -= 1) {
invShiftRows(state)
invSubWord(state)
addRoundKey(state, key, 4 * round * nB)
invMixColumns(state)
}
invShiftRows(state)
invSubWord(state)
addRoundKey(state, key, 0)
return state
},
clear: function () {},
keyLength: keyLength,
blockSize: blockSize,
}
},
}
})()
var msrcryptoPadding = msrcryptoPadding || {}
msrcryptoPadding.pkcsv7 = function (blockSize) {
function pad(messageBlocks) {
var lastIndex =
messageBlocks.length - 1 >= 0 ? messageBlocks.length - 1 : 0
var lastBlock = messageBlocks[lastIndex]
var lastBlockLength = lastBlock.length
var createNewBlock = lastBlockLength === blockSize
if (createNewBlock) {
var newBlock = []
var i
for (i = 0; i < blockSize; i += 1) {
newBlock.push(blockSize)
}
messageBlocks.push(newBlock)
} else {
var byteToAdd = (blockSize - lastBlockLength) & 0xff
while (lastBlock.length !== blockSize) {
lastBlock.push(byteToAdd)
}
}
}
function unpad(messageBytes) {
var verified = true
if (messageBytes.length % blockSize !== 0) {
verified = false
}
var lastBlock = messageBytes.slice(-blockSize)
var padLen = lastBlock[lastBlock.length - 1]
for (var i = 0; i < blockSize; i++) {
var isPaddingElement = blockSize - i <= padLen
var isCorrectValue = lastBlock[i] === padLen
verified = (isPaddingElement ? isCorrectValue : true) && verified
}
var trimLen = verified ? padLen : 0
messageBytes.length -= trimLen
return verified
}
return {
pad: pad,
unpad: unpad,
}
}
var msrcryptoCbc = function (blockCipher) {
var blockSize = blockCipher.blockSize / 8
var paddingScheme = msrcryptoPadding.pkcsv7(blockSize)
var mergeBlocks = function (tab) {
var res = [],
i,
j
for (i = 0; i < tab.length; i += 1) {
var block = tab[i]
for (j = 0; j < block.length; j += 1) {
res.push(block[j])
}
}
return res
}
function getBlocks(dataBytes) {
var blocks = []
mBuffer = mBuffer.concat(dataBytes)
var blockCount = Math.floor(mBuffer.length / blockSize)
for (var i = 0; i < blockCount; i++) {
blocks.push(mBuffer.slice(i * blockSize, (i + 1) * blockSize))
}
mBuffer = mBuffer.slice(blockCount * blockSize)
return blocks
}
function encryptBlocks(blocks) {
var result = [],
toEncrypt
for (var i = 0; i < blocks.length; i++) {
toEncrypt = msrcryptoUtilities.xorVectors(mIvBytes, blocks[i])
result.push(blockCipher.encrypt(toEncrypt))
mIvBytes = result[i]
}
return result
}
function decryptBlocks(blocks) {
var result = [],
toDecrypt,
decrypted
for (var i = 0; i < blocks.length; i += 1) {
toDecrypt = blocks[i].slice(0, blocks[i].length)
decrypted = blockCipher.decrypt(toDecrypt)
result.push(msrcryptoUtilities.xorVectors(mIvBytes, decrypted))
mIvBytes = blocks[i]
}
return result
}
function clearState() {
mBuffer = []
mResultBuffer = []
mIvBytes = null
}
var mBuffer = [],
mResultBuffer = [],
mIvBytes
return {
init: function (ivBytes) {
if (ivBytes.length !== blockSize) {
throw new Error('Invalid iv size')
}
mIvBytes = ivBytes.slice()
},
encrypt: function (plainBytes) {
var result = encryptBlocks(getBlocks(plainBytes))
mResultBuffer = mResultBuffer.concat(mergeBlocks(result))
return this.finishEncrypt()
},
processEncrypt: function (plainBytes) {
var result = mergeBlocks(encryptBlocks(getBlocks(plainBytes)))
return result
},
finishEncrypt: function () {
var blocks = mBuffer.length === 1 ? [[mBuffer[0]]] : [mBuffer]
paddingScheme.pad(blocks)
var result = mResultBuffer.concat(mergeBlocks(encryptBlocks(blocks)))
clearState()
return result
},
decrypt: function (cipherBytes) {
this.processDecrypt(cipherBytes)
return this.finishDecrypt()
},
processDecrypt: function (cipherBytes) {
var result = decryptBlocks(getBlocks(cipherBytes))
mResultBuffer = mResultBuffer.concat(mergeBlocks(result))
return
},
finishDecrypt: function () {
var result = mResultBuffer
var verified = paddingScheme.unpad(result)
clearState()
return result
},
}
}
if (typeof operations !== 'undefined') {
var cbcInstances = {}
msrcryptoCbc.workerEncrypt = function (p) {
var result,
id = p.workerid
if (!cbcInstances[id]) {
cbcInstances[id] = msrcryptoCbc(msrcryptoBlockCipher.aes(p.keyData))
cbcInstances[id].init(p.algorithm.iv)
}
if (p.operationSubType === 'process') {
return cbcInstances[id].processEncrypt(p.buffer)
}
if (p.operationSubType === 'finish') {
result = cbcInstances[id].finishEncrypt()
cbcInstances[id] = null
return result
}
result = cbcInstances[id].encrypt(p.buffer)
cbcInstances[id] = null
return result
}
msrcryptoCbc.workerDecrypt = function (p) {
var result,
id = p.workerid
if (!cbcInstances[id]) {
cbcInstances[id] = msrcryptoCbc(msrcryptoBlockCipher.aes(p.keyData))
cbcInstances[id].init(p.algorithm.iv)
}
if (p.operationSubType === 'process') {
cbcInstances[id].processDecrypt(p.buffer)
return
}
if (p.operationSubType === 'finish') {
result = cbcInstances[id].finishDecrypt()
cbcInstances[id] = null
return result
}
result = cbcInstances[id].decrypt(p.buffer)
cbcInstances[id] = null
return result
}
msrcryptoCbc.generateKey = function (p) {
if (p.algorithm.length % 8 !== 0) {
throw new Error()
}
return {
type: 'keyGeneration',
keyData: msrcryptoPseudoRandom.getBytes(
Math.floor(p.algorithm.length / 8),
),
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable,
usages: null || p.usages,
type: 'secret',
},
}
}
msrcryptoCbc.importKey = function (p) {
var keyObject
var keyBits = p.keyData.length * 8
if (p.format === 'jwk') {
keyObject = msrcryptoJwk.jwkToKey(p.keyData, p.algorithm, ['k'])
} else if (p.format === 'raw') {
if (keyBits !== 128 && keyBits !== 192 && keyBits !== 256) {
throw new Error(
'invalid key length (should be 128, 192, or 256 bits)',
)
}
keyObject = {
k: msrcryptoUtilities.toArray(p.keyData),
}
} else {
throw new Error('unsupported import format')
}
p.algorithm.length = keyObject.k.length * 8
return {
keyData: keyObject.k,
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable || keyObject.extractable,
usages: null || p.usages,
type: 'secret',
},
type: 'keyImport',
}
}
msrcryptoCbc.exportKey = function (p) {
if (p.format === 'jwk') {
return {
type: 'keyExport',
keyHandle: msrcryptoJwk.keyToJwk(p.keyHandle, p.keyData),
}
}
if (p.format === 'raw') {
return {
type: 'keyExport',
keyHandle: p.keyData,
}
}
throw new Error('unsupported export format')
}
operations.register('importKey', 'AES-CBC', msrcryptoCbc.importKey)
operations.register('exportKey', 'AES-CBC', msrcryptoCbc.exportKey)
operations.register('generateKey', 'AES-CBC', msrcryptoCbc.generateKey)
operations.register('encrypt', 'AES-CBC', msrcryptoCbc.workerEncrypt)
operations.register('decrypt', 'AES-CBC', msrcryptoCbc.workerDecrypt)
}
var msrcryptoGcm = function (blockCipher) {
var utils = msrcryptoUtilities
var mBuffer = [],
mIvBytes,
mAdditionalBytes,
mTagLength,
mJ0,
mJ0inc,
mH = blockCipher.encrypt(utils.getVector(16)),
mGHashState = utils.getVector(16),
mGHashBuffer = [],
mCipherText = [],
mGctrCb,
mBytesProcessed = 0
function ghash(hashSubkey, dataBytes) {
var blockCount = Math.floor(dataBytes.length / 16),
dataBlock
for (var i = 0; i < blockCount; i++) {
dataBlock = dataBytes.slice(i * 16, i * 16 + 16)
mGHashState = blockMultiplication(
utils.xorVectors(mGHashState, dataBlock),
hashSubkey,
)
}
mGHashBuffer = dataBytes.slice(blockCount * 16)
return mGHashState
}
function finishGHash() {
var u = 16 * Math.ceil(mBytesProcessed / 16) - mBytesProcessed
var lenA = numberTo8Bytes(mAdditionalBytes.length * 8),
lenC = numberTo8Bytes(mBytesProcessed * 8)
var p = mGHashBuffer
.concat(utils.getVector(u))
.concat(lenA)
.concat(lenC)
return ghash(mH, p)
}
function blockMultiplication(blockX, blockY) {
var z = utils.getVector(16),
v = blockY.slice(0),
mask,
j,
i
for (i = 0; i < 128; i++) {
mask = -getBit(blockX, i) & 0xff
for (j = 0; j < 16; j++) {
z[j] = z[j] ^ (v[j] & mask)
}
mask = -(v[15] & 1) & 0xff
shiftRight(v)
v[0] ^= 0xe1 & mask
}
return z
}
function shiftRight(dataBytes) {
for (var i = dataBytes.length - 1; i > 0; i--) {
dataBytes[i] = ((dataBytes[i - 1] & 1) << 7) | (dataBytes[i] >>> 1)
}
dataBytes[0] = dataBytes[0] >>> 1
return dataBytes
}
function getBit(byteArray, bitNumber) {
var byteIndex = Math.floor(bitNumber / 8)
return (byteArray[byteIndex] >> (7 - (bitNumber % 8))) & 1
}
function inc(dataBytes) {
var carry = 256
for (var i = 1; i <= 4; i++) {
carry = (carry >>> 8) + dataBytes[dataBytes.length - i]
dataBytes[dataBytes.length - i] = carry & 255
}
return dataBytes
}
function gctr(icb, dataBytes) {
var blockCount = Math.ceil(dataBytes.length / 16),
dataBlock,
result = []
if (mGctrCb !== icb) {
mGctrCb = icb.slice()
}
for (var block = 0; block < blockCount; block++) {
dataBlock = dataBytes.slice(block * 16, block * 16 + 16)
var e = blockCipher.encrypt(mGctrCb.slice())
result = result.concat(utils.xorVectors(dataBlock, e))
mGctrCb = inc(mGctrCb)
}
return result
}
function numberTo8Bytes(integer) {
return [
0,
0,
0,
0,
(integer >>> 24) & 255,
(integer >>> 16) & 255,
(integer >>> 8) & 255,
integer & 255,
]
}
function padBlocks(dataBytes) {
var padLen =
16 * Math.ceil(mAdditionalBytes.length / 16) - mAdditionalBytes.length
return dataBytes.concat(utils.getVector(padLen))
}
function clearState() {
mBytesProcessed = 0
mBuffer = []
mCipherText = []
mGHashState = utils.getVector(16)
mGHashBuffer = []
mGctrCb = mIvBytes = mAdditionalBytes = null
}
function init(ivBytes, additionalBytes, tagLength) {
mAdditionalBytes = additionalBytes || []
mTagLength = isNaN(tagLength) ? 128 : tagLength
if (mTagLength % 8 !== 0) {
throw new Error('DataError')
}
mIvBytes = ivBytes
if (mIvBytes.length === 12) {
mJ0 = mIvBytes.concat([0, 0, 0, 1])
} else {
var l = 16 * Math.ceil(mIvBytes.length / 16) - mIvBytes.length
mJ0 = ghash(
mH,
mIvBytes
.concat(utils.getVector(l + 8))
.concat(numberTo8Bytes(mIvBytes.length * 8)),
)
mGHashState = utils.getVector(16)
}
mJ0inc = inc(mJ0.slice())
ghash(mH, padBlocks(mAdditionalBytes))
}
function encrypt(plainBytes) {
mBytesProcessed = plainBytes.length
var c = gctr(mJ0inc, plainBytes)
ghash(mH, c)
var s = finishGHash()
var t = gctr(mJ0, s).slice(0, mTagLength / 8)
clearState()
return c.slice().concat(t)
}
function decrypt(cipherBytes, tagBytes) {
mBytesProcessed = cipherBytes.length
var p = gctr(mJ0inc, cipherBytes)
ghash(mH, cipherBytes)
var s = finishGHash()
var t = gctr(mJ0, s).slice(0, mTagLength / 8)
clearState()
if (utils.arraysEqual(t, tagBytes)) {
return p
} else {
return null
}
}
function processEncrypt(plainBytes) {
mBuffer = mBuffer.concat(plainBytes)
var fullBlocks = mBuffer.slice(0, Math.floor(mBuffer.length / 16) * 16)
mBytesProcessed += fullBlocks.length
mBuffer = mBuffer.slice(fullBlocks.length)
var c = gctr(mGctrCb || mJ0inc, fullBlocks)
mCipherText = mCipherText.concat(c)
ghash(mH, c)
}
function processDecrypt(cipherBytes) {
mBuffer = mBuffer.concat(cipherBytes)
var fullBlocks = mBuffer.slice(
0,
Math.floor((mBuffer.length - mTagLength / 8) / 16) * 16,
)
mBytesProcessed += fullBlocks.length
mBuffer = mBuffer.slice(fullBlocks.length)
var c = gctr(mGctrCb || mJ0inc, fullBlocks)
mCipherText = mCipherText.concat(c)
ghash(mH, fullBlocks)
}
function finishEncrypt() {
var c = gctr(mGctrCb, mBuffer)
mCipherText = mCipherText.concat(c)
mBytesProcessed += mBuffer.length
var s = finishGHash()
var t = gctr(mJ0, s).slice(0, mTagLength / 8)
var result = mCipherText.slice().concat(t)
clearState()
return result
}
function finishDecrypt() {
var tagLength = Math.floor(mTagLength / 8)
var tagBytes = mBuffer.slice(-tagLength)
mBuffer = mBuffer.slice(0, mBuffer.length - tagLength)
var c = gctr(mGctrCb, mBuffer)
mCipherText = mCipherText.concat(c)
mBytesProcessed += mBuffer.length
var s = finishGHash()
var t = gctr(mJ0, s).slice(0, mTagLength / 8)
var result = mCipherText.slice()
clearState()
if (utils.arraysEqual(t, tagBytes)) {
return result
} else {
return null
}
}
return {
init: init,
encrypt: encrypt,
decrypt: decrypt,
processEncrypt: processEncrypt,
processDecrypt: processDecrypt,
finishEncrypt: finishEncrypt,
finishDecrypt: finishDecrypt,
}
}
if (typeof operations !== 'undefined') {
var gcmInstances = {}
msrcryptoGcm.encrypt = function (p) {
var result,
id = p.workerid
if (!gcmInstances[id]) {
gcmInstances[id] = msrcryptoGcm(msrcryptoBlockCipher.aes(p.keyData))
gcmInstances[id].init(
p.algorithm.iv,
p.algorithm.additionalData,
p.algorithm.tagLength,
)
}
if (p.operationSubType === 'process') {
gcmInstances[id].processEncrypt(p.buffer)
return
}
if (p.operationSubType === 'finish') {
result = gcmInstances[id].finishEncrypt()
gcmInstances[id] = null
return result
}
result = gcmInstances[id].encrypt(p.buffer)
gcmInstances[id] = null
return result
}
msrcryptoGcm.decrypt = function (p) {
var result,
id = p.workerid
if (!gcmInstances[id]) {
gcmInstances[id] = msrcryptoGcm(msrcryptoBlockCipher.aes(p.keyData))
gcmInstances[id].init(
p.algorithm.iv,
p.algorithm.additionalData,
p.algorithm.tagLength,
)
}
if (p.operationSubType === 'process') {
gcmInstances[id].processDecrypt(p.buffer)
return
}
if (p.operationSubType === 'finish') {
result = gcmInstances[id].finishDecrypt()
gcmInstances[id] = null
if (result === null) {
throw new Error('OperationError')
}
return result
}
var tagLength = p.algorithm.tagLength
? Math.floor(p.algorithm.tagLength / 8)
: 16
var cipherBytes = p.buffer.slice(0, p.buffer.length - tagLength)
var tagBytes = p.buffer.slice(-tagLength)
result = gcmInstances[id].decrypt(cipherBytes, tagBytes)
gcmInstances[id] = null
if (result === null) {
throw new Error('OperationError')
}
return result
}
msrcryptoGcm.generateKey = function (p) {
if (p.algorithm.length % 8 !== 0) {
throw new Error()
}
return {
type: 'keyGeneration',
keyData: msrcryptoPseudoRandom.getBytes(
Math.floor(p.algorithm.length / 8),
),
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable,
usages: null || p.usages,
type: 'secret',
},
}
}
msrcryptoGcm.importKey = function (p) {
var keyObject,
keyBits = p.keyData.length * 8
if (p.format === 'jwk') {
keyObject = msrcryptoJwk.jwkToKey(p.keyData, p.algorithm, ['k'])
} else if (p.format === 'raw') {
if (keyBits !== 128 && keyBits !== 192 && keyBits !== 256) {
throw new Error(
'invalid key length (should be 128, 192, or 256 bits)',
)
}
keyObject = {
k: msrcryptoUtilities.toArray(p.keyData),
}
} else {
throw new Error('unsupported import format')
}
return {
type: 'keyImport',
keyData: keyObject.k,
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable || keyObject.extractable,
usages: null || p.usages,
type: 'secret',
},
}
}
msrcryptoGcm.exportKey = function (p) {
if (p.format === 'jwk') {
return {
type: 'keyExport',
keyHandle: msrcryptoJwk.keyToJwk(p.keyHandle, p.keyData),
}
}
if (p.format === 'raw') {
return {
type: 'keyExport',
keyHandle: p.keyData,
}
}
throw new Error('unsupported export format')
}
operations.register('importKey', 'AES-GCM', msrcryptoGcm.importKey)
operations.register('exportKey', 'AES-GCM', msrcryptoGcm.exportKey)
operations.register('generateKey', 'AES-GCM', msrcryptoGcm.generateKey)
operations.register('encrypt', 'AES-GCM', msrcryptoGcm.encrypt)
operations.register('decrypt', 'AES-GCM', msrcryptoGcm.decrypt)
}
function MsrcryptoPrng() {
if (!(this instanceof MsrcryptoPrng)) {
throw new Error('create MsrcryptoPrng object with new keyword')
}
var initialized = false
var key
var v
var keyLen
var seedLen
var reseedCounter = 1
var reseedInterval = Math.pow(2, 48)
initialize()
function addOne(counter) {
var i
for (i = counter.length - 1; i >= 0; i -= 1) {
counter[i] += 1
if (counter[i] >= 256) {
counter[i] = 0
}
if (counter[i]) {
break
}
}
}
function initialize() {
key = msrcryptoUtilities.getVector(32)
v = msrcryptoUtilities.getVector(16)
keyLen = 32
seedLen = 48
reseedCounter = 1
}
function reseed(entropy, additionalEntropy) {
additionalEntropy = additionalEntropy || [0]
if (additionalEntropy.length > seedLen) {
throw new Error('Incorrect entropy or additionalEntropy length')
}
additionalEntropy = additionalEntropy.concat(
msrcryptoUtilities.getVector(seedLen - additionalEntropy.length),
)
entropy = entropy.concat(
msrcryptoUtilities.getVector(
(seedLen - (entropy.length % seedLen)) % seedLen,
),
)
for (var i = 0; i < entropy.length; i += seedLen) {
var seedMaterial = msrcryptoUtilities.xorVectors(
entropy.slice(i, i + seedLen),
additionalEntropy,
)
update(seedMaterial)
}
reseedCounter = 1
}
function update(providedData) {
var temp = []
var blockCipher = new msrcryptoBlockCipher.aes(key)
while (temp.length < seedLen) {
addOne(v)
var toEncrypt = v.slice(0, 16)
var outputBlock = blockCipher.encrypt(toEncrypt)
temp = temp.concat(outputBlock)
}
temp = msrcryptoUtilities.xorVectors(temp, providedData)
key = temp.slice(0, keyLen)
v = temp.slice(keyLen)
}
function generate(requestedBytes, additionalInput) {
if (requestedBytes >= 65536) {
throw new Error('too much random requested')
}
if (reseedCounter > reseedInterval) {
throw new Error('Reseeding is required')
}
if (additionalInput && additionalInput.length > 0) {
while (additionalInput.length < seedLen) {
additionalInput = additionalInput.concat(
msrcryptoUtilities.getVector(seedLen - additionalInput.length),
)
}
update(additionalInput)
} else {
additionalInput = msrcryptoUtilities.getVector(seedLen)
}
var temp = []
var blockCipher = new msrcryptoBlockCipher.aes(key)
while (temp.length < requestedBytes) {
addOne(v)
var toEncrypt = v.slice(0, v.length)
var outputBlock = blockCipher.encrypt(toEncrypt)
temp = temp.concat(outputBlock)
}
temp = temp.slice(0, requestedBytes)
update(additionalInput)
reseedCounter += 1
return temp
}
return {
reseed: reseed,
getBytes: function (length, additionalInput) {
if (!initialized) {
throw new Error("can't get randomness before initialization")
}
return generate(length, additionalInput)
},
getNonZeroBytes: function (length, additionalInput) {
if (!initialized) {
throw new Error("can't get randomness before initialization")
}
var result = []
var buff
while (result.length < length) {
buff = generate(length, additionalInput)
for (var i = 0; i < buff.length; i += 1) {
if (buff[i] !== 0) {
result.push(buff[i])
}
}
}
return result.slice(0, length)
},
init: function (entropy, personalization) {
if (entropy.length < seedLen) {
throw new Error('Initial entropy length too short')
}
initialize()
reseed(entropy, personalization)
initialized = true
},
}
}
var msrcryptoPseudoRandom = new MsrcryptoPrng()
function MsrcryptoEntropy(global) {
var poolLength = 48
var collectorPool = []
var collectorPoolLength = 128
var collectorsRegistered = 0
var entropyPoolPrng = new MsrcryptoPrng()
var initialized = false
var cryptographicPRNGPresent = false
var globalScope = global
function collectEntropy() {
var headerList = [
'Cookie',
'RedirectUri',
'ETag',
'x-ms-client-antiforgery-id',
'x-ms-client-request-id',
'x-ms-client-session-id',
'SubscriptionPool',
]
var i,
pool = []
for (i = 0; i < poolLength; i += 1) {
pool[i] = Math.floor(Math.random() * 256)
}
var prngCrypto = globalScope.crypto || globalScope.msCrypto
if (prngCrypto && typeof prngCrypto.getRandomValues === 'function') {
if (global.Uint8Array) {
var res = new global.Uint8Array(poolLength)
prngCrypto.getRandomValues(res)
pool = pool.concat(Array.apply(null, res))
cryptographicPRNGPresent = true
}
}
if (typeof XMLHttpRequest !== 'undefined') {
var req = new XMLHttpRequest()
for (i = 0; i < headerList.length; i += 1) {
try {
var header = req.getResponseHeader(headerList[i])
if (header) {
var arr = msrcryptoUtilities.stringToBytes(header)
pool = pool.concat(arr)
}
} catch (err) {}
}
}
if (!cryptographicPRNGPresent && canCollect) {
pool = pool.concat(collectorPool.splice(0, collectorPool.length))
collectors.startCollectors()
}
initialized ? entropyPoolPrng.reseed(pool) : entropyPoolPrng.init(pool)
initialized = true
}
function updatePool(entropyData) {
for (var i = 0; i < entropyData.length; ++i) {
collectorPool.push(entropyData[i])
}
if (collectorPool.length >= collectorPoolLength) {
collectors.stopCollectors()
}
}
var canCollect =
(global && global.addEventListener) ||
(typeof document !== 'undefined' && document.attachEvent)
var collectors = (function () {
return {
startCollectors: function () {
if (!this.collectorsRegistered) {
if (global.addEventListener) {
global.addEventListener(
'mousemove',
this.MouseEventCallBack,
true,
)
global.addEventListener('load', this.LoadTimeCallBack, true)
} else if (document.attachEvent) {
document.attachEvent('onmousemove', this.MouseEventCallBack)
document.attachEvent('onload', this.LoadTimeCallBack)
} else {
throw new Error("Can't attach events for entropy collection")
}
this.collectorsRegistered = 1
}
},
stopCollectors: function () {
if (this.collectorsRegistered) {
if (global.removeEventListener) {
global.removeEventListener(
'mousemove',
this.MouseEventCallBack,
1,
)
global.removeEventListener('load', this.LoadTimeCallBack, 1)
} else if (global.detachEvent) {
global.detachEvent('onmousemove', this.MouseEventCallBack)
global.detachEvent('onload', this.LoadTimeCallBack)
}
this.collectorsRegistered = 0
}
},
MouseEventCallBack: function (eventData) {
var d = new Date().valueOf()
var x = eventData.x || eventData.clientX || eventData.offsetX || 0
var y = eventData.y || eventData.clientY || eventData.offsetY || 0
var arr = [
d & 0x0ff,
(d >> 8) & 0x0ff,
(d >> 16) & 0x0ff,
(d >> 24) & 0x0ff,
x & 0x0ff,
(x >> 8) & 0x0ff,
y & 0x0ff,
(y >> 8) & 0x0ff,
]
updatePool(arr)
},
LoadTimeCallBack: function () {
var d = new Date().valueOf()
var dateArray = [
d & 0x0ff,
(d >> 8) & 0x0ff,
(d >> 16) & 0x0ff,
(d >> 24) & 0x0ff,
]
updatePool(dateArray)
},
}
})()
return {
init: function () {
collectEntropy()
if (
!cryptographicPRNGPresent &&
!collectorsRegistered &&
canCollect
) {
try {
collectors.startCollectors()
} catch (e) {}
}
},
reseed: function (entropy) {
entropyPoolPrng.reseed(entropy)
},
read: function (length) {
if (!initialized) {
throw new Error('Entropy pool is not initialized.')
}
var ret = entropyPoolPrng.getBytes(length)
collectEntropy()
return ret
},
}
}
var prime = (function () {
var smallPrimes = []
var trialValues = []
var MAX_SMALL_PRIMES = 4096 * 4
function primeSieve(max) {
var numbers = new Array(max + 1),
results = [],
i,
j,
limit = Math.sqrt(max) | 0
for (i = 3; i <= limit; i += 2) {
for (j = i * i; j <= max; j += i * 2) {
numbers[j] = 0
}
}
for (i = 3; i <= max; i += 2) {
if (numbers[i] !== 0) {
results.push(i)
}
}
return results
}
function incrementalTrialDivision(increment) {
var i,
len = trialValues.length
for (i = 0; i < len; i++) {
if ((trialValues[i] + increment) % smallPrimes[i] === 0) {
return false
}
}
return true
}
function setupIncrementalTrialDivision(candidate) {
var i,
j,
r,
p,
y,
primeCount,
len = candidate.length - 1,
db = cryptoMath.DIGIT_BASE,
h = candidate[len]
if (smallPrimes.length === 0) {
smallPrimes = primeSieve(MAX_SMALL_PRIMES)
}
primeCount = smallPrimes.length
trialValues = new Array(primeCount)
for (i = 0; i < primeCount; i++) {
j = len
y = smallPrimes[i]
if (h < y) {
r = h
j--
} else {
r = 0
}
while (j >= 0) {
p = r * db + candidate[j--]
r = p - ((p / y) | 0) * y
}
trialValues[i] = r
}
return
}
function largestDivisibleByPowerOfTwo(number) {
var k = 0,
i = 0,
s = 0,
j
if (cryptoMath.isZero(number)) {
return 0
}
for (k = 0; number[k] === 0; k++) {}
for (i = 0, j = 2; number[k] % j === 0; j *= 2, i++) {}
return k * cryptoMath.DIGIT_BITS + i
}
function sizeInBits(digits) {
var k = 0,
i = 0,
j = 0
if (cryptoMath.isZero(digits)) {
return 0
}
for (k = digits.length - 1; digits[k] === 0; k--) {}
for (
i = cryptoMath.DIGIT_BITS - 1, j = 1 << i;
i > 0;
j = j >>> 1, i--
) {
if ((digits[k] & j) !== 0) {
break
}
}
return k * cryptoMath.DIGIT_BITS + i
}
function millerRabin(number, iterations) {
var w = number
var wminus1 = []
cryptoMath.subtract(w, [1], wminus1)
var a = largestDivisibleByPowerOfTwo(wminus1)
var m = []
cryptoMath.shiftRight(wminus1, m, a)
var wlen = sizeInBits(w)
var b
var montmul = cryptoMath.MontgomeryMultiplier(w)
for (var i = 1; i <= iterations; i++) {
var status = false
do {
b = getRandomOddNumber(wlen)
} while (cryptoMath.compareDigits(b, wminus1) >= 0)
var z = []
montmul.modExp(b, m, z, true)
if (
cryptoMath.compareDigits(z, [1]) === 0 ||
cryptoMath.compareDigits(z, wminus1) === 0
) {
continue
}
for (var j = 1; j < a; j++) {
montmul.montgomeryMultiply(z, z, z)
if (cryptoMath.compareDigits(z, wminus1) === 0) {
status = true
break
}
if (cryptoMath.compareDigits(z, [1]) === 0) {
return false
}
}
if (status === false) {
return false
}
}
return true
}
function generatePrime(bits) {
var candidate = getRandomOddNumber(bits),
inc = 0,
possiblePrime,
isPrime = false,
candidatePlusInc = []
setupIncrementalTrialDivision(candidate)
while (true) {
possiblePrime = incrementalTrialDivision(inc)
if (possiblePrime) {
cryptoMath.add(candidate, [inc], candidatePlusInc)
if (millerRabin(candidatePlusInc, 6) === true) {
return candidatePlusInc
}
}
inc += 2
}
}
function getRandomOddNumber(bits) {
var numBytes = Math.ceil(bits / 8),
bytes = msrcryptoPseudoRandom.getBytes(numBytes),
digits
bytes[0] |= 128
bytes[bytes.length - 1] |= 1
return cryptoMath.bytesToDigits(bytes)
}
return {
generatePrime: generatePrime,
}
})()
var msrcryptoRsaBase = function (keyStruct) {
var utils = msrcryptoUtilities,
keyIsPrivate =
keyStruct.hasOwnProperty('n') && keyStruct.hasOwnProperty('d'),
keyIsCrt =
keyStruct.hasOwnProperty('p') && keyStruct.hasOwnProperty('q'),
modulusLength = keyStruct.n.length
function toBytes(digits) {
var bytes = cryptoMath.digitsToBytes(digits)
utils.padFront(bytes, 0, modulusLength)
return bytes
}
function modExp(dataBytes, expBytes, modulusBytes) {
var exponent = cryptoMath.bytesToDigits(expBytes)
var group = cryptoMath.IntegerGroup(modulusBytes)
var base = group.createElementFromBytes(dataBytes)
var result = group.modexp(base, exponent)
return result.m_digits
}
function decryptModExp(cipherBytes) {
var resultElement = modExp(cipherBytes, keyStruct.d, keyStruct.n)
return toBytes(resultElement)
}
function decryptCrt(cipherBytes) {
var b2d = cryptoMath.bytesToDigits,
p = keyStruct.p,
q = keyStruct.q,
dp = keyStruct.dp,
dq = keyStruct.dq,
invQ = keyStruct.qi,
pDigits = b2d(p),
qDigits = b2d(q),
temp = new Array(pDigits.length + qDigits.length),
m1Digits = new Array(pDigits.length + 1),
m2Digits = new Array(qDigits.length + 1),
cDigits = b2d(cipherBytes),
mm = cryptoMath.MontgomeryMultiplier,
mmp = new mm(keyStruct.ctxp ? undefined : pDigits, keyStruct.ctxp),
mmq = new mm(keyStruct.ctxq ? undefined : qDigits, keyStruct.ctxq)
mmp.reduce(cDigits, temp)
mmp.modExp(temp, b2d(dp), m1Digits)
mmq.reduce(cDigits, temp)
mmq.modExp(temp, b2d(dq), m2Digits)
var carry = cryptoMath.subtract(m1Digits, m2Digits, temp)
if (carry !== 0) {
cryptoMath.subtract(m2Digits, m1Digits, temp)
}
cryptoMath.modMul(temp, b2d(invQ), pDigits, cDigits)
if (carry !== 0) {
cryptoMath.subtract(pDigits, cDigits, cDigits)
}
cryptoMath.multiply(cDigits, qDigits, temp)
cryptoMath.add(m2Digits, temp, m1Digits)
return toBytes(m1Digits)
}
return {
encrypt: function (messageBytes) {
var bytes = toBytes(
modExp(messageBytes, keyStruct.e, keyStruct.n, true),
)
return bytes
},
decrypt: function (cipherBytes) {
if (keyIsCrt) {
return decryptCrt(cipherBytes)
}
if (keyIsPrivate) {
return decryptModExp(cipherBytes)
}
throw new Error('missing private key')
},
}
}
var rsaShared = {
mgf1: function (seedBytes, maskLen, hashFunction) {
var t = [],
bytes,
hash,
counter,
hashByteLen = hashFunction.hashLen / 8
for (
counter = 0;
counter <= Math.floor(maskLen / hashByteLen);
counter += 1
) {
bytes = [
(counter >>> 24) & 0xff,
(counter >>> 16) & 0xff,
(counter >>> 8) & 0xff,
counter & 0xff,
]
hash = hashFunction.computeHash(seedBytes.concat(bytes))
t = t.concat(hash)
}
return t.slice(0, maskLen)
},
checkMessageVsMaxHash: function (messageBytes, hashFunction) {
if (messageBytes.length > (hashFunction.maxMessageSize || 0xffffffff)) {
throw new Error('message too long')
}
return
},
}
var rsaMode = rsaMode || {}
rsaMode.oaep = function (keyStruct, hashFunction) {
var utils = msrcryptoUtilities,
random = msrcryptoPseudoRandom,
size = keyStruct.n.length
if (hashFunction === null) {
throw new Error('must supply hashFunction')
}
function pad(message, label) {
var lHash, psLen, psArray, i, db, seed
var dbMask, maskeddb, seedMask, maskedSeed
var encodedMessage
if (message.length > size - 2 * (hashFunction.hashLen / 8) - 2) {
throw new Error('Message too long.')
}
if (label == null) {
label = []
}
lHash = hashFunction.computeHash(label)
psLen = size - message.length - 2 * lHash.length - 2
psArray = utils.getVector(psLen)
db = lHash.concat(psArray, [1], message)
seed = random.getBytes(lHash.length)
dbMask = rsaShared.mgf1(seed, size - lHash.length - 1, hashFunction)
maskeddb = utils.xorVectors(db, dbMask)
seedMask = rsaShared.mgf1(maskeddb, lHash.length, hashFunction)
maskedSeed = utils.xorVectors(seed, seedMask)
encodedMessage = [0].concat(maskedSeed).concat(maskeddb)
message = encodedMessage.slice()
return message
}
function unpad(encodedBytes, labelBytes) {
var lHash, maskedSeed, maskeddb, seedMask
var seed, dbMask, db
var lHashp,
i = 0
var valid = encodedBytes[0] === 0
if (!labelBytes) {
labelBytes = []
}
lHash = hashFunction.computeHash(labelBytes)
maskedSeed = encodedBytes.slice(1, lHash.length + 1)
maskeddb = encodedBytes.slice(lHash.length + 1)
seedMask = rsaShared.mgf1(maskeddb, lHash.length, hashFunction)
seed = utils.xorVectors(maskedSeed, seedMask)
dbMask = rsaShared.mgf1(seed, size - lHash.length - 1, hashFunction)
db = utils.xorVectors(maskeddb, dbMask)
lHashp = db.slice(0, lHash.length)
valid = valid && utils.arraysEqual(lHash, lHashp)
db = db.slice(lHash.length)
while (!db[i++]) {}
return {
valid: valid,
data: db.slice(i),
}
}
return {
pad: function (messageBytes, labelBytes) {
return pad(messageBytes, labelBytes)
},
unpad: function (encodedBytes, labelBytes) {
return unpad(encodedBytes, labelBytes)
},
}
}
var rsaMode = rsaMode || {}
rsaMode.pkcs1Encrypt = function (keyStruct) {
var random = msrcryptoPseudoRandom,
size = keyStruct.n.length
function pad(data) {
var randomness
if (data.length > size - 11) {
throw new Error('message too long')
}
randomness = random.getNonZeroBytes(size - data.length - 3)
return [0, 2].concat(randomness, [0], data)
}
function validatePadding(paddedData) {
var paddingValid = paddedData[0] === 0 && paddedData[1] === 2
for (var i = 2; i < 10; i++) {
paddingValid = paddingValid && !!paddedData[i]
}
return paddingValid
}
function unpad(paddedData) {
var i,
paddingIsValid = validatePadding(paddedData),
startOfData = 0
for (i = 1; i < paddedData.length; i += 1) {
startOfData = startOfData || (+!paddedData[i] && i + 1)
}
startOfData = -paddingIsValid && startOfData
return {
data: paddedData.slice(startOfData),
valid: paddingIsValid,
}
}
return {
pad: function (messageBytes) {
return pad(messageBytes)
},
unpad: function (encodedBytes) {
return unpad(encodedBytes)
},
}
}
rsaMode.pkcs1Sign = function (keyStruct, hashFunction) {
var utils = msrcryptoUtilities,
size = keyStruct.n.length
function emsa_pkcs1_v15_encode(messageBytes) {
var paddedData, hash, tlen
hash = hashFunction.computeHash(messageBytes.slice())
paddedData = hashFunction.der.concat(hash)
tlen = paddedData.length
if (size < tlen + 11) {
throw new Error('intended encoded message length too short')
}
return [0x00, 0x01].concat(
utils.getVector(size - tlen - 3, 0xff),
[0],
paddedData,
)
}
return {
sign: function (messageBytes) {
return emsa_pkcs1_v15_encode(messageBytes)
},
verify: function (signatureBytes, messageBytes) {
var emp = emsa_pkcs1_v15_encode(messageBytes)
return utils.arraysEqual(signatureBytes, emp)
},
}
}
var rsaMode = rsaMode || {}
rsaMode.pss = function (keyStruct, hashFunction) {
var utils = msrcryptoUtilities,
random = msrcryptoPseudoRandom
function emsa_pss_encode(messageBytes, saltLength, salt) {
var modulusBits = cryptoMath.bitLength(keyStruct.n),
emBits = modulusBits - 1,
emLen = Math.ceil(emBits / 8),
mHash = hashFunction.computeHash(messageBytes)
saltLength = salt
? salt.length
: saltLength == null
? mHash.length
: saltLength
if (emLen < mHash.length + saltLength + 2) {
throw new Error('encoding error')
}
salt = salt || random.getBytes(saltLength)
var mp = [0, 0, 0, 0, 0, 0, 0, 0].concat(mHash, salt)
var h = hashFunction.computeHash(mp)
var ps = utils.getVector(emLen - salt.length - h.length - 2)
var db = ps.concat([1], salt)
var dbMask = rsaShared.mgf1(h, emLen - h.length - 1, hashFunction)
var maskedDb = utils.xorVectors(db, dbMask)
var mask = 0
for (var i = 0; i < 8 - (8 * emLen - emBits); i++) {
mask += 1 << i
}
maskedDb[0] &= mask
var em = maskedDb.concat(h, [0xbc])
return em
}
function emsa_pss_verify(signatureBytes, messageBytes, saltLength) {
var modulusBits = cryptoMath.bitLength(keyStruct.n)
var emBits = modulusBits - 1
var emLen = Math.ceil(emBits / 8)
var mHash = hashFunction.computeHash(messageBytes)
var hLen = mHash.length
saltLength = saltLength == null ? hLen : saltLength
if (emLen < hLen + saltLength + 2) {
return false
}
var maskedDb = signatureBytes.slice(0, emLen - hLen - 1)
var h = signatureBytes.slice(maskedDb.length, maskedDb.length + hLen)
var dbMask = rsaShared.mgf1(h, emLen - hLen - 1, hashFunction)
var db = utils.xorVectors(maskedDb, dbMask)
db[0] &= 0xff >>> (8 - (8 * emLen - emBits))
for (var i = 0; i < emLen - hLen - saltLength - 2; i++) {
if (db[i] !== 0) {
return false
}
}
if (db[emLen - hLen - saltLength - 2] !== 0x01) {
return false
}
var salt = db.slice(db.length - saltLength)
var mp = [0, 0, 0, 0, 0, 0, 0, 0].concat(mHash, salt)
var hp = hashFunction.computeHash(mp)
return utils.arraysEqual(hp, h)
}
return {
sign: function (messageBytes, saltLength, salt) {
return emsa_pss_encode(messageBytes, saltLength, salt)
},
verify: function (signatureBytes, messageBytes, saltLength) {
return emsa_pss_verify(signatureBytes, messageBytes, saltLength)
},
}
}
var msrcryptoRsa = function (keyStruct, mode, hashFunction) {
var rsaBase = msrcryptoRsaBase(keyStruct)
if (!mode) {
throw new Error('padding mode')
}
function checkHash() {
if (!hashFunction || !hashFunction.computeHash) {
throw new Error('missing hash function')
}
}
var paddingFunction = null,
unPaddingFunction = null
var padding
switch (mode) {
case 'RSAES-PKCS1-V1_5':
padding = rsaMode.pkcs1Encrypt(keyStruct)
break
case 'RSASSA-PKCS1-V1_5':
checkHash()
padding = rsaMode.pkcs1Sign(keyStruct, hashFunction)
break
case 'RSA-OAEP':
checkHash()
padding = rsaMode.oaep(keyStruct, hashFunction)
break
case 'RSA-PSS':
checkHash()
padding = rsaMode.pss(keyStruct, hashFunction)
break
case 'raw':
padding = {
pad: function (mb) {
return mb
},
unpad: function (eb) {
return eb
},
}
break
default:
throw new Error('invalid mode')
}
if (padding) {
paddingFunction = padding.pad || padding.sign
unPaddingFunction = padding.unpad || padding.verify
}
var returnObj = {
encrypt: function (dataBytes, labelBytes) {
var paddedData
var encryptedData
if (paddingFunction !== null) {
paddedData = paddingFunction(dataBytes, labelBytes)
} else {
paddedData = dataBytes.slice()
}
encryptedData = rsaBase.encrypt(paddedData)
return encryptedData
},
decrypt: function (cipherBytes, labelBytes) {
var decryptedData = rsaBase.decrypt(cipherBytes)
if (unPaddingFunction !== null) {
decryptedData = unPaddingFunction(decryptedData, labelBytes)
if (decryptedData.valid === false) {
throw new Error('OperationError')
}
decryptedData = decryptedData.data
} else {
decryptedData = decryptedData.slice(0)
}
return decryptedData
},
signData: function (messageBytes, saltLength, salt) {
return rsaBase.decrypt(
paddingFunction(messageBytes, saltLength, salt),
)
},
verifySignature: function (signature, messageBytes, saltLength) {
var decryptedSig = rsaBase.encrypt(signature)
return unPaddingFunction(decryptedSig, messageBytes, saltLength)
},
generateKeyPair: function (bits) {
var keyPair = genRsaKeyFromRandom(bits)
},
mode: mode,
}
return returnObj
}
if (typeof operations !== 'undefined') {
msrcryptoRsa.sign = function (p) {
var rsaObj,
hashName = p.keyHandle.algorithm.hash.name,
hashFunc = msrcryptoHashFunctions[hashName.toUpperCase()](),
saltLength = p.algorithm.saltLength,
salt = p.algorithm.salt
rsaObj = msrcryptoRsa(p.keyData, p.algorithm.name, hashFunc)
return rsaObj.signData(p.buffer, saltLength, salt)
}
msrcryptoRsa.verify = function (p) {
var hashName = p.keyHandle.algorithm.hash.name,
hashFunc = msrcryptoHashFunctions[hashName.toUpperCase()](),
rsaObj,
saltLength = p.algorithm.saltLength
rsaObj = msrcryptoRsa(p.keyData, p.algorithm.name, hashFunc)
return rsaObj.verifySignature(p.signature, p.buffer, saltLength)
}
msrcryptoRsa.workerEncrypt = function (p) {
var result, rsaObj, hashFunc, hashName
switch (p.algorithm.name) {
case 'RSAES-PKCS1-V1_5':
rsaObj = msrcryptoRsa(p.keyData, p.algorithm.name)
result = rsaObj.encrypt(p.buffer)
break
case 'RSA-OAEP':
hashName = p.keyHandle.algorithm.hash.name
if (!hashName) {
throw new Error('unsupported hash algorithm')
}
hashFunc = msrcryptoHashFunctions[hashName.toUpperCase()]()
rsaObj = msrcryptoRsa(p.keyData, p.algorithm.name, hashFunc)
result = rsaObj.encrypt(p.buffer)
break
default:
throw new Error('unsupported algorithm')
}
return result
}
msrcryptoRsa.workerDecrypt = function (p) {
var result, rsaObj, hashFunc
switch (p.algorithm.name) {
case 'RSAES-PKCS1-V1_5':
rsaObj = msrcryptoRsa(p.keyData, p.algorithm.name)
result = rsaObj.decrypt(p.buffer)
break
case 'RSA-OAEP':
var hashName = p.keyHandle.algorithm.hash.name
if (!hashName) {
throw new Error('unsupported hash algorithm')
}
hashFunc = msrcryptoHashFunctions[hashName.toUpperCase()]()
rsaObj = msrcryptoRsa(p.keyData, p.algorithm.name, hashFunc)
result = rsaObj.decrypt(p.buffer)
break
default:
throw new Error('unsupported algorithm')
}
return result
}
msrcryptoRsa.importKey = function (p) {
var keyObject
if (p.format === 'jwk') {
keyObject = msrcryptoJwk.jwkToKey(p.keyData, p.algorithm, [
'n',
'e',
'd',
'q',
'p',
'dq',
'dp',
'qi',
])
if (keyObject.d) {
keyObject.ctxp = new cryptoMath.MontgomeryMultiplier(
cryptoMath.bytesToDigits(keyObject.p),
).ctx
keyObject.ctxq = new cryptoMath.MontgomeryMultiplier(
cryptoMath.bytesToDigits(keyObject.q),
).ctx
}
} else if (p.format === 'spki') {
var publicKeyInfo = asn1.parse(p.keyData)
if (publicKeyInfo == null) {
throw new Error('invalid key data.')
}
var bitString = publicKeyInfo[1]
var keySequence = asn1.parse(
bitString.data.slice(bitString.header + 1),
true,
)
if (keySequence == null) {
throw new Error('invalid key data.')
}
var n = keySequence[0],
e = keySequence[1]
if (n.type !== 'INTEGER' || e.type !== 'INTEGER') {
throw new Error('invalid key data.')
}
n = n.data.slice(n.header)
e = e.data.slice(e.header)
if (n[0] === 0 && n[1] & 128) {
n = n.slice(1)
}
if (e[0] === 0 && e[1] & 128) {
e = e.slice(1)
}
keyObject = {
n: n,
e: e,
}
} else {
throw new Error('unsupported key import format.')
}
return {
type: 'keyImport',
keyData: keyObject,
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable,
usages: p.usages,
type: keyObject.d || keyObject.dq ? 'private' : 'public',
},
}
}
msrcryptoRsa.exportKey = function (p) {
var jsonKeyStringArray = msrcryptoJwk.keyToJwk(p.keyHandle, p.keyData)
return {
type: 'keyExport',
keyHandle: jsonKeyStringArray,
}
}
msrcryptoRsa.genRsaKeyFromRandom = function (bits, e) {
var exp = e ? cryptoMath.bytesToDigits(e) : [65537]
do {
var p = prime.generatePrime(bits / 2)
var q = prime.generatePrime(bits / 2)
if (cryptoMath.compareDigits(q, p) > 0) {
var t = p
p = q
q = t
}
var n = []
cryptoMath.multiply(p, q, n)
var p_1 = []
cryptoMath.subtract(p, [1], p_1)
var q_1 = []
cryptoMath.subtract(q, [1], q_1)
var p_1q_1 = []
cryptoMath.multiply(p_1, q_1, p_1q_1)
var gcd = []
cryptoMath.gcd(exp, p_1q_1, gcd)
var gcdEqual1 = cryptoMath.compareDigits(gcd, cryptoMath.One) === 0
} while (!gcdEqual1)
var d = []
cryptoMath.modInv(exp, p_1q_1, d)
var dp = []
cryptoMath.reduce(d, p_1, dp)
var dq = []
cryptoMath.reduce(d, q_1, dq)
var qi = []
cryptoMath.modInv(q, p, qi)
var d2b = cryptoMath.digitsToBytes
return {
privateKey: {
n: d2b(n),
e: d2b(exp),
d: d2b(d),
p: d2b(p),
q: d2b(q),
dp: d2b(dp),
dq: d2b(dq),
qi: d2b(qi),
},
publicKey: {
n: d2b(n),
e: d2b(exp),
},
}
}
msrcryptoRsa.generateKeyPair = function (p) {
if (typeof p.algorithm.modulusLength === 'undefined') {
throw new Error('missing modulusLength')
}
var keyPair
var b2d = cryptoMath.bytesToDigits
switch (p.algorithm.modulusLength) {
case 1024:
case 2048:
case 4096:
keyPair = msrcryptoRsa.genRsaKeyFromRandom(
p.algorithm.modulusLength,
p.algorithm.publicExponent,
)
break
default:
throw new Error('invalid modulusLength')
}
var pk = keyPair.privateKey
pk.ctxp = new cryptoMath.MontgomeryMultiplier(b2d(pk.p)).ctx
pk.ctxq = new cryptoMath.MontgomeryMultiplier(b2d(pk.q)).ctx
var algName = p.algorithm.name
var rsaKeyType = algName.slice(algName.indexOf('-') + 1).toUpperCase()
var publicUsage, privateUsage
if (algName === 'RSASSA-PKCS1-V1_5' || algName === 'RSA-PSS') {
publicUsage = ['verify']
privateUsage = ['sign']
} else {
publicUsage = ['encrypt']
privateUsage = ['decrypt']
}
return {
type: 'keyGeneration',
keyPair: {
publicKey: {
keyData: keyPair.publicKey,
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable,
usages: null || publicUsage,
type: 'public',
},
},
privateKey: {
keyData: keyPair.privateKey,
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable,
usages: null || privateUsage,
type: 'private',
},
},
},
}
}
operations.register('sign', 'RSASSA-PKCS1-V1_5', msrcryptoRsa.sign)
operations.register('sign', 'RSA-PSS', msrcryptoRsa.sign)
operations.register('verify', 'RSASSA-PKCS1-V1_5', msrcryptoRsa.verify)
operations.register('verify', 'RSA-PSS', msrcryptoRsa.verify)
operations.register(
'encrypt',
'RSAES-PKCS1-V1_5',
msrcryptoRsa.workerEncrypt,
)
operations.register(
'decrypt',
'RSAES-PKCS1-V1_5',
msrcryptoRsa.workerDecrypt,
)
operations.register('encrypt', 'RSA-OAEP', msrcryptoRsa.workerEncrypt)
operations.register('decrypt', 'RSA-OAEP', msrcryptoRsa.workerDecrypt)
operations.register('importKey', 'RSA-OAEP', msrcryptoRsa.importKey)
operations.register(
'importKey',
'RSAES-PKCS1-V1_5',
msrcryptoRsa.importKey,
)
operations.register(
'importKey',
'RSASSA-PKCS1-V1_5',
msrcryptoRsa.importKey,
)
operations.register('importKey', 'RSA-PSS', msrcryptoRsa.importKey)
operations.register('exportKey', 'RSA-OAEP', msrcryptoRsa.exportKey)
operations.register(
'exportKey',
'RSAES-PKCS1-V1_5',
msrcryptoRsa.exportKey,
)
operations.register(
'exportKey',
'RSASSA-PKCS1-V1_5',
msrcryptoRsa.exportKey,
)
operations.register('exportKey', 'RSA-PSS', msrcryptoRsa.exportKey)
operations.register(
'generateKey',
'RSA-OAEP',
msrcryptoRsa.generateKeyPair,
)
operations.register(
'generateKey',
'RSAES-PKCS1-V1_5',
msrcryptoRsa.generateKeyPair,
)
operations.register(
'generateKey',
'RSASSA-PKCS1-V1_5',
msrcryptoRsa.generateKeyPair,
)
operations.register(
'generateKey',
'RSA-PSS',
msrcryptoRsa.generateKeyPair,
)
}
var msrcryptoConcatKdf = (function () {
function deriveBits(p) {
var hashName = p.algorithm.hash.name,
hashFunction = msrcryptoHashFunctions[hashName.toUpperCase()](),
alg = p.algorithm
var otherInfo = utils
.toArray(alg.algorithmId)
.concat(
utils.toArray(alg.partyUInfo),
utils.toArray(alg.partyVInfo),
utils.toArray(alg.publicInfo) || [],
utils.toArray(alg.privateInfo) || [],
)
var reps = Math.ceil(p.length / hashFunction.hashLen),
counter = 1,
digest = p.keyData.concat(otherInfo),
output = []
for (var i = 0; i < reps; i++) {
var data = utils.int32ToBytes(counter++).concat(digest)
var h = hashFunction.computeHash(data)
output = output.concat(h)
}
return output.slice(0, p.length / 8)
}
return {
deriveBits: deriveBits,
}
})()
var msrcryptoConcatKdfInstance = null
if (typeof operations !== 'undefined') {
msrcryptoConcatKdf.importKey = function (p) {
var keyData
if (p.format === 'raw') {
keyData = msrcryptoUtilities.toArray(p.keyData)
} else {
throw new Error('unsupported import format')
}
if (p.extractable !== false) {
throw new Error('only extractable=false is supported.')
}
return {
type: 'keyImport',
keyData: keyData,
keyHandle: {
algorithm: {
name: 'CONCAT',
},
extractable: false,
usages: p.usages,
type: 'secret',
},
}
}
operations.register('deriveBits', 'CONCAT', msrcryptoConcatKdf.deriveBits)
operations.register('importKey', 'CONCAT', msrcryptoConcatKdf.importKey)
}
var msrcryptoPbkdf2 = (function () {
function deriveBits(p) {
var algorithm = p.algorithm,
keyBytes = p.keyData,
bits = p.length,
iterations = algorithm.iterations,
saltBytes = Array.apply(null, algorithm.salt),
byteLen = Math.ceil(bits / 8),
hLen,
blockCount,
output = []
switch (algorithm.hash.name.toUpperCase()) {
case 'SHA-1':
hLen = 20
break
case 'SHA-256':
hLen = 32
break
case 'SHA-384':
hLen = 48
break
case 'SHA-512':
hLen = 64
break
default:
throw new Error('Unsupported hash algorithm')
}
blockCount = Math.ceil(byteLen / hLen)
var hmacKey = msrcryptoHmac.importKey({
format: 'raw',
keyData: keyBytes,
algorithm: {
name: 'HMAC',
hash: algorithm.hash,
},
})
var hmacContext = {
algorithm: algorithm,
keyHandle: hmacKey.keyHandle,
keyData: hmacKey.keyData,
workerid: 0,
buffer: null,
}
function F(S, c, i) {
var result = [],
u = S.concat([
(i >>> 24) & 0xff,
(i >>> 16) & 0xff,
(i >>> 8) & 0xff,
i & 0xff,
])
for (var j = 0; j < c; j++) {
hmacContext.buffer = u
u = msrcryptoHmac.signHmac(hmacContext)
for (var k = 0; k < hLen; k++) {
result[k] = ~~result[k] ^ u[k]
}
}
return result
}
for (var block = 1; block <= blockCount; block++) {
output = output.concat(F(saltBytes, iterations, block))
}
output.length = byteLen
return output
}
return {
deriveBits: deriveBits,
}
})()
var msrcryptoKdfInstance = null
if (typeof operations !== 'undefined') {
msrcryptoPbkdf2.importKey = function (p) {
var keyData
if (p.format === 'raw') {
keyData = msrcryptoUtilities.toArray(p.keyData)
} else {
throw new Error('unsupported import format')
}
if (p.extractable !== false) {
throw new Error('only extractable=false is supported.')
}
return {
type: 'keyImport',
keyData: keyData,
keyHandle: {
algorithm: {
name: 'PBKDF2',
},
extractable: false,
usages: p.usages,
type: 'secret',
},
}
}
operations.register('deriveBits', 'PBKDF2', msrcryptoPbkdf2.deriveBits)
operations.register('importKey', 'PBKDF2', msrcryptoPbkdf2.importKey)
}
var msrcryptoHkdf = (function () {
function deriveBits(p) {
var algorithm = p.algorithm,
keyBytes = p.keyData,
bits = p.length,
saltBytes = algorithm.salt,
byteLen = Math.ceil(bits / 8),
hLen,
output = [],
infoBytes = msrcryptoUtilities.toArray(algorithm.info),
t = [],
i,
hmacContext
switch (algorithm.hash.name.toUpperCase()) {
case 'SHA-1':
hLen = 20
break
case 'SHA-256':
hLen = 32
break
case 'SHA-384':
hLen = 48
break
case 'SHA-512':
hLen = 64
break
default:
throw new Error('Unsupported hash algorithm.')
}
if (algorithm.salt == null) {
throw new Error('HkdfParams: salt: Missing required property.')
}
if (algorithm.info == null) {
throw new Error('HkdfParams: info: Missing required property.')
}
if (bits % 8 !== 0) {
throw new Error(
'The length provided for HKDF is not a multiple of 8 bits.',
)
}
if (byteLen > 255 * hLen) {
throw new Error('The length provided for HKDF is too large.')
}
if (saltBytes.length === 0) {
saltBytes = msrcryptoUtilities.getVector(hLen)
}
hmacContext = {
workerid: 0,
keyHandle: {
algorithm: algorithm,
},
keyData: saltBytes,
buffer: keyBytes,
}
hmacContext.keyData = msrcryptoHmac.signHmac(hmacContext)
for (i = 0; i < Math.ceil(byteLen / hLen); i++) {
hmacContext.buffer = t.concat(infoBytes).concat([1 + i])
t = msrcryptoHmac.signHmac(hmacContext)
output = output.concat(t)
}
return output.slice(0, byteLen)
}
return {
deriveBits: deriveBits,
}
})()
var msrcryptoKdfInstance = null
if (typeof operations !== 'undefined') {
msrcryptoHkdf.importKey = function (p) {
var keyData
if (p.format === 'raw') {
keyData = msrcryptoUtilities.toArray(p.keyData)
} else {
throw new Error('unsupported import format')
}
if (p.extractable !== false) {
throw new Error('only extractable=false is supported.')
}
return {
type: 'keyImport',
keyData: keyData,
keyHandle: {
algorithm: {
name: 'HKDF',
},
extractable: false,
usages: p.usages,
type: 'secret',
},
}
}
operations.register('deriveBits', 'HKDF', msrcryptoHkdf.deriveBits)
operations.register('importKey', 'HKDF', msrcryptoHkdf.importKey)
}
var msrcryptoHkdfCtr = (function () {
function deriveBits(p) {
var algorithm = p.algorithm,
keyBytes = p.keyData,
bits = p.length,
labelBytes = algorithm.label,
contextBytes = algorithm.context,
byteLen = Math.ceil(bits / 8),
hLen,
output = [],
i,
hmacContext
switch (algorithm.hash.name.toUpperCase()) {
case 'SHA-1':
hLen = 20
break
case 'SHA-256':
hLen = 32
break
case 'SHA-384':
hLen = 48
break
case 'SHA-512':
hLen = 64
break
default:
throw new Error('Unsupported hash algorithm.')
}
if (algorithm.label == null) {
throw new Error('HkdfCtrParams: label: Missing required property.')
}
if (algorithm.context == null) {
throw new Error('HkdfCtrParams: context: Missing required property.')
}
if (bits % 8 !== 0) {
throw new Error(
'The length provided for HKDF-CTR is not a multiple of 8 bits.',
)
}
if (byteLen > 255 * hLen) {
throw new Error('The length provided for HKDF-CTR is too large.')
}
hmacContext = {
workerid: 0,
keyHandle: {
algorithm: algorithm,
},
keyData: keyBytes,
buffer: keyBytes,
}
var fixed = labelBytes.concat(
[0],
contextBytes,
utils.int32ToBytes(bits),
)
for (i = 1; i <= Math.ceil(byteLen / hLen); i++) {
hmacContext.buffer = utils.int32ToBytes(i).concat(fixed)
output = output.concat(msrcryptoHmac.signHmac(hmacContext))
}
return output.slice(0, byteLen)
}
return {
deriveBits: deriveBits,
}
})()
if (typeof operations !== 'undefined') {
msrcryptoHkdfCtr.importKey = function (p) {
var keyData
if (p.format === 'raw') {
keyData = msrcryptoUtilities.toArray(p.keyData)
} else {
throw new Error('unsupported import format')
}
if (p.extractable !== false) {
throw new Error('only extractable=false is supported.')
}
return {
type: 'keyImport',
keyData: keyData,
keyHandle: {
algorithm: {
name: 'HKDF-CTR',
},
extractable: false,
usages: p.usages,
type: 'secret',
},
}
}
operations.register('deriveBits', 'HKDF-CTR', msrcryptoHkdfCtr.deriveBits)
operations.register('importKey', 'HKDF-CTR', msrcryptoHkdfCtr.importKey)
}
var msrcryptoEcdh = function (curve) {
var btd = cryptoMath.bytesToDigits,
dtb = cryptoMath.digitsToBytes,
e = curve,
ecop = new cryptoECC.EllipticCurveOperatorFp(curve)
function generateKey(privateKeyBytes) {
var privateKey = [],
randomBytes = msrcryptoPseudoRandom.getBytes(
curve.order.length * cryptoMath.DIGIT_NUM_BYTES,
)
cryptoMath.reduce(
cryptoMath.bytesToDigits(randomBytes),
e.order,
privateKey,
)
var publicKey = e.allocatePointStorage()
ecop.scalarMultiply(privateKey, e.generator, publicKey)
return {
privateKey: {
x: dtb(publicKey.x),
y: dtb(publicKey.y),
d: dtb(privateKey),
},
publicKey: {
x: dtb(publicKey.x),
y: dtb(publicKey.y),
},
}
}
function deriveBits(privateKey, publicKey, length) {
var publicPoint = new cryptoECC.EllipticCurvePointFp(
e,
false,
btd(publicKey.x),
btd(publicKey.y),
null,
false,
)
var sharedSecretPoint = e.allocatePointStorage()
ecop.convertToJacobianForm(sharedSecretPoint)
ecop.convertToMontgomeryForm(sharedSecretPoint)
ecop.scalarMultiply(btd(privateKey.d), publicPoint, sharedSecretPoint)
ecop.convertToAffineForm(sharedSecretPoint)
ecop.convertToStandardForm(sharedSecretPoint)
var secretBytes = cryptoMath.digitsToBytes(
sharedSecretPoint.x,
true,
publicKey.x.length,
)
if (length && secretBytes.length * 8 < length) {
throw new Error('DataError')
}
secretBytes = length
? secretBytes.slice(0, Math.ceil(length / 8))
: secretBytes
var bits = length % 8
var mask = bits === 0 ? 0xff : 0xff00 >>> bits
secretBytes[secretBytes.length - 1] =
secretBytes[secretBytes.length - 1] & mask
return secretBytes
}
function computePublicKey(privateKeyBytes) {
if (!e.generator.isInMontgomeryForm) {
ecop.convertToMontgomeryForm(e.generator)
}
var publicKey = e.allocatePointStorage()
ecop.convertToJacobianForm(publicKey)
ecop.convertToMontgomeryForm(publicKey)
ecop.scalarMultiply(btd(privateKeyBytes), e.generator, publicKey)
return {
x: dtb(publicKey.x),
y: dtb(publicKey.y),
}
}
return {
generateKey: generateKey,
deriveBits: deriveBits,
computePublicKey: computePublicKey,
}
}
var ecdhInstance = null
if (typeof operations !== 'undefined') {
msrcryptoEcdh.deriveBits = function (p) {
var curve = cryptoECC.createCurve(p.algorithm.namedCurve.toUpperCase())
var privateKey = p.keyData
var publicKey = p.additionalKeyData
ecdhInstance = msrcryptoEcdh(curve)
var secretBytes = ecdhInstance.deriveBits(
privateKey,
publicKey,
p.length,
)
return secretBytes
}
msrcryptoEcdh.deriveKey = function (p) {
throw new Error('not supported')
return secretBytes
}
msrcryptoEcdh.generateKey = function (p) {
var curve = cryptoECC.createCurve(p.algorithm.namedCurve.toUpperCase())
ecdhInstance = msrcryptoEcdh(curve)
var keyPairData = ecdhInstance.generateKey()
return {
type: 'keyPairGeneration',
keyPair: {
publicKey: {
keyData: keyPairData.publicKey,
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable,
usages: [],
type: 'public',
},
},
privateKey: {
keyData: keyPairData.privateKey,
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable,
usages: p.usages,
type: 'private',
},
},
},
}
}
msrcryptoEcdh.importKey = function (p) {
if (p.format === 'raw') {
var keyData = p.keyData
if (keyData[0] !== 4) {
throw new Error('DataError')
}
var elementSize = ~~((keyData.length - 1) / 2)
var curveName = p.algorithm.namedCurve.toUpperCase()
var x = keyData.slice(1, elementSize + 1),
y = keyData.slice(elementSize + 1)
if (cryptoECC.validatePoint(curveName, x, y) === false) {
throw new Error('DataError')
}
return {
type: 'keyImport',
keyData: {
x: x,
y: y,
},
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable || false,
usages: p.usages,
type: 'public',
},
}
}
if (p.format === 'jwk') {
var keyObject = msrcryptoJwk.jwkToKey(p.keyData, p.algorithm, [
'x',
'y',
'd',
'crv',
])
if (keyObject.d && (!keyObject.x || !keyObject.y)) {
var curve = cryptoECC.createCurve(
p.algorithm.namedCurve.toUpperCase(),
)
ecdhInstance = msrcryptoEcdh(curve)
var publicKey = ecdhInstance.computePublicKey(keyObject.d)
keyObject.x = publicKey.x
keyObject.y = publicKey.y
}
if (
cryptoECC.validatePoint(
p.algorithm.namedCurve.toUpperCase(),
keyObject.x,
keyObject.y,
) === false
) {
throw new Error('DataError')
}
return {
type: 'keyImport',
keyData: keyObject,
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable || keyObject.extractable,
usages: p.usages,
type: keyObject.d ? 'private' : 'public',
},
}
}
}
msrcryptoEcdh.exportKey = function (p) {
if (p.format === 'raw' && p.keyHandle.type === 'public') {
var keyData = [4].concat(p.keyData.x, p.keyData.y)
return {
type: 'keyExport',
keyHandle: keyData,
}
}
if (p.format === 'jwk') {
var jsonKeyStringArray = msrcryptoJwk.keyToJwk(p.keyHandle, p.keyData)
return {
type: 'keyExport',
keyHandle: jsonKeyStringArray,
}
}
throw new Error('unsupported export format.')
}
operations.register('importKey', 'ECDH', msrcryptoEcdh.importKey)
operations.register('exportKey', 'ECDH', msrcryptoEcdh.exportKey)
operations.register('generateKey', 'ECDH', msrcryptoEcdh.generateKey)
operations.register('deriveBits', 'ECDH', msrcryptoEcdh.deriveBits)
operations.register('deriveKey', 'ECDH', msrcryptoEcdh.deriveKey)
}
var msrcryptoEcdsa = function (curve) {
var btd = cryptoMath.bytesToDigits,
dtb = cryptoMath.digitsToBytes,
ecop = new cryptoECC.EllipticCurveOperatorFp(curve),
orderByteLength = dtb(curve.order).length,
tedCurve = curve.type === 1
function createKey(privateKeyBytes) {
return createKeyInternal(btd(privateKeyBytes))
}
function createKeyInternal(privateKeyDigits) {
var publicKey = curve.allocatePointStorage()
ecop.scalarMultiply(privateKeyDigits, curve.generator, publicKey)
return {
publicKey: publicKey,
privateKey: privateKeyDigits,
}
}
function generateKey(randomBytes) {
var privateKey = []
if (!randomBytes) {
randomBytes = msrcryptoPseudoRandom.getBytes(
curve.order.length * cryptoMath.DIGIT_NUM_BYTES,
)
}
cryptoMath.reduce(
cryptoMath.bytesToDigits(randomBytes),
curve.order,
privateKey,
)
return createKeyInternal(privateKey)
}
function getDigest(messageBytes) {
if (messageBytes.length > orderByteLength) {
messageBytes.length = orderByteLength
}
var digest = btd(messageBytes)
if (tedCurve) {
var shift = 8 - (curve.rbits % 8)
cryptoMath.shiftRight(digest, digest, shift)
}
cryptoMath.reduce(digest, curve.order, digest)
return digest
}
function sign(privateKey, messageBytes, ephemeralKey) {
if (!ephemeralKey) {
ephemeralKey = generateKey()
}
var r = ephemeralKey.publicKey.x,
k = ephemeralKey.privateKey,
d = btd(privateKey.d),
digest = getDigest(messageBytes.slice()),
s = [],
tmp = [],
signature = null
cryptoMath.reduce(r, curve.order, r)
cryptoMath.modMul(r, d, curve.order, s)
cryptoMath.add(s, digest, s)
cryptoMath.reduce(s, curve.order, s)
cryptoMath.modInvCT(k, curve.order, tmp)
cryptoMath.modMul(s, tmp, curve.order, s)
var rBytes = msrcryptoUtilities.padFront(
dtb(r, true, orderByteLength),
0,
orderByteLength,
)
var sBytes = msrcryptoUtilities.padFront(
dtb(s, true, orderByteLength),
0,
orderByteLength,
)
signature = rBytes.concat(sBytes)
return signature
}
function verify(publicKey, signatureBytes, messageBytes) {
var split = Math.floor(signatureBytes.length / 2),
r = btd(signatureBytes.slice(0, split)),
s = btd(signatureBytes.slice(split)),
digest = getDigest(messageBytes.slice()),
u1 = [],
u2 = []
var publicPoint = new cryptoECC.EllipticCurvePointFp(
curve,
false,
btd(publicKey.x),
btd(publicKey.y),
null,
false,
)
cryptoMath.modInv(s, curve.order, s)
cryptoMath.modMul(digest, s, curve.order, u1)
cryptoMath.modMul(r, s, curve.order, u2)
var r0 = curve.allocatePointStorage()
var r1 = curve.allocatePointStorage()
if (tedCurve) {
cryptoMath.add(u1, u1, u1)
cryptoMath.add(u1, u1, u1)
cryptoMath.reduce(u1, curve.order, u1)
ecop.scalarMultiply(u1, curve.generator, r0, false)
ecop.scalarMultiply(u2, publicPoint, r1, false)
ecop.convertToExtendedProjective(r0)
ecop.convertToExtendedProjective(r1)
ecop.add(r1, r0, r0)
ecop.normalize(r0)
} else {
ecop.scalarMultiply(u1, curve.generator, r0)
ecop.scalarMultiply(u2, publicPoint, r1)
ecop.convertToJacobianForm(r0)
ecop.convertToMontgomeryForm(r0)
ecop.convertToMontgomeryForm(r1)
ecop.mixedAdd(r0, r1, r0)
ecop.convertToAffineForm(r0)
ecop.convertToStandardForm(r0)
}
if (r0.isInfinity) {
return false
}
cryptoMath.reduce(r0.x, curve.order, r0.x)
return cryptoMath.compareDigits(r0.x, r) === 0
}
return {
createKey: createKey,
generateKey: generateKey,
sign: sign,
verify: verify,
}
}
if (typeof operations !== 'undefined') {
msrcryptoEcdsa.sign = function (p) {
msrcryptoUtilities.checkParam(
p.algorithm.hash,
'Object',
'algorithm.hash',
)
msrcryptoUtilities.checkParam(
p.algorithm.hash.name,
'String',
'algorithm.hash.name',
)
msrcryptoUtilities.checkParam(
p.keyHandle.algorithm.namedCurve,
'String',
'p.keyHandle.algorithm.namedCurve',
)
var hashName = p.algorithm.hash.name,
curve = cryptoECC.createCurve(
p.keyHandle.algorithm.namedCurve.toUpperCase(),
),
hashFunc = msrcryptoHashFunctions[hashName.toUpperCase()](),
digest = hashFunc.computeHash(p.buffer)
var ecdsa = msrcryptoEcdsa(curve)
return ecdsa.sign(p.keyData, digest)
}
msrcryptoEcdsa.verify = function (p) {
var hashName = p.algorithm.hash.name,
curve = cryptoECC.createCurve(
p.keyHandle.algorithm.namedCurve.toUpperCase(),
),
hashFunc = msrcryptoHashFunctions[hashName.toUpperCase()](),
digest = hashFunc.computeHash(p.buffer)
var ecdsa = msrcryptoEcdsa(curve)
return ecdsa.verify(p.keyData, p.signature, digest)
}
msrcryptoEcdsa.generateKey = function (p) {
var curve = cryptoECC.createCurve(p.algorithm.namedCurve.toUpperCase())
var ecdsa = msrcryptoEcdsa(curve)
var keyPairData = ecdsa.generateKey()
var dtb = cryptoMath.digitsToBytes
function padTo8BytesIncrement(array) {
return array
}
var x = padTo8BytesIncrement(dtb(keyPairData.publicKey.x))
var y = padTo8BytesIncrement(dtb(keyPairData.publicKey.y))
var d = padTo8BytesIncrement(dtb(keyPairData.privateKey))
return {
type: 'keyPairGeneration',
keyPair: {
publicKey: {
keyData: {
x: x,
y: y,
},
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable,
usages: ['verify'],
type: 'public',
},
},
privateKey: {
keyData: {
x: x,
y: y,
d: d,
},
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable,
usages: ['sign'],
type: 'private',
},
},
},
}
}
msrcryptoEcdsa.importKey = function (p) {
if (p.format === 'raw') {
var keyData = p.keyData
if (keyData[0] !== 4) {
throw new Error('DataError')
}
var elementSize = ~~((keyData.length - 1) / 2)
var curveName = p.algorithm.namedCurve.toUpperCase()
var x = keyData.slice(1, elementSize + 1),
y = keyData.slice(elementSize + 1)
if (cryptoECC.validatePoint(curveName, x, y) === false) {
throw new Error('DataError')
}
return {
type: 'keyImport',
keyData: {
x: x,
y: y,
},
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable || false,
usages: p.usages,
type: 'public',
},
}
}
if (p.format === 'jwk') {
var keyObject = msrcryptoJwk.jwkToKey(p.keyData, p.algorithm, [
'x',
'y',
'd',
'crv',
])
if (keyObject.d && (!keyObject.x || !keyObject.y)) {
var curve = msrcryptoEcdsa.curves[p.algorithm.namedCurve]()
var ecdsa = msrcryptoEcdsa(curve)
var publicKey = ecdsa.computePublicKey(keyObject.d)
keyObject.x = publicKey.x
keyObject.y = publicKey.y
}
if (
cryptoECC.validatePoint(
p.algorithm.namedCurve.toUpperCase(),
keyObject.x,
keyObject.y,
) === false
) {
throw new Error('DataError')
}
return {
type: 'keyImport',
keyData: keyObject,
keyHandle: {
algorithm: p.algorithm,
extractable: p.extractable || keyObject.extractable,
usages: null || p.usages,
type: keyObject.d ? 'private' : 'public',
},
}
}
}
msrcryptoEcdsa.exportKey = function (p) {
if (p.format === 'raw' && p.keyHandle.type === 'public') {
var keyData = [4].concat(p.keyData.x, p.keyData.y)
return {
type: 'keyExport',
keyHandle: keyData,
}
}
if (p.format === 'jwk') {
var jsonKeyStringArray = msrcryptoJwk.keyToJwk(p.keyHandle, p.keyData)
return {
type: 'keyExport',
keyHandle: jsonKeyStringArray,
}
}
throw new Error('unsupported export format.')
}
operations.register('sign', 'ECDSA', msrcryptoEcdsa.sign)
operations.register('verify', 'ECDSA', msrcryptoEcdsa.verify)
operations.register('generateKey', 'ECDSA', msrcryptoEcdsa.generateKey)
operations.register('importKey', 'ECDSA', msrcryptoEcdsa.importKey)
operations.register('exportKey', 'ECDSA', msrcryptoEcdsa.exportKey)
}
var msrcryptoSubtle
var utils = msrcryptoUtilities
msrcryptoSubtle = (function () {
function syncWorker() {
var result
function postMessage(data) {
try {
data.workerid = this.id
result = msrcryptoWorker.jsCryptoRunner({
data: data,
})
} catch (ex) {
this.onerror({
data: ex,
type: 'error',
})
return
}
this.onmessage({
data: result,
})
}
return {
postMessage: postMessage,
onmessage: null,
onerror: null,
terminate: function () {},
}
}
var streamObject = function (op) {
return {
process: function (buffer) {
return op.process(buffer)
},
finish: function () {
return op.finish()
},
abort: function () {
return op.abort()
},
}
}
function baseOperation(processResults) {
var result = null,
oncompleteCallback = null,
onerrorCallback = null,
retObj,
promise,
resolveFunc,
rejectFunc
promise = new Promise(function (resolve, reject) {
resolveFunc = resolve
rejectFunc = reject
})
function opDispatchEvent(e) {
if (e.type === 'error') {
if (rejectFunc) {
rejectFunc.apply(promise, [e])
}
return
}
if (e.data.type === 'process') {
processResults(e.data.result, true)
return
}
if (e.data.type === 'finish') {
processResults(e.data.result, true)
return
}
this.result = processResults(e.data)
resolveFunc.apply(promise, [this.result])
return
}
retObj = {
dispatchEvent: opDispatchEvent,
promise: promise,
result: null,
}
return retObj
}
function keyOperation() {
function processResult(result) {
var publicKey, privateKey
switch (result.type) {
case 'keyGeneration':
case 'keyImport':
case 'keyDerive':
if (result.keyPair) {
keys.add(
result.keyPair.publicKey.keyHandle,
result.keyPair.publicKey.keyData,
)
keys.add(
result.keyPair.privateKey.keyHandle,
result.keyPair.privateKey.keyData,
)
return {
publicKey: result.keyPair.publicKey.keyHandle,
privateKey: result.keyPair.privateKey.keyHandle,
}
} else {
keys.add(result.keyHandle, result.keyData)
return result.keyHandle
}
case 'keyExport':
return result.keyHandle
case 'keyPairGeneration':
privateKey = result.keyPair.privateKey
publicKey = result.keyPair.publicKey
keys.add(publicKey.keyHandle, publicKey.keyData)
keys.add(privateKey.keyHandle, privateKey.keyData)
return {
publicKey: publicKey.keyHandle,
privateKey: privateKey.keyHandle,
}
default:
throw new Error('Unknown key operation')
}
}
return baseOperation(processResult)
}
function toArrayBufferIfSupported(dataArray) {
if (typedArraySupport && dataArray.pop) {
return new Uint8Array(dataArray).buffer
}
return dataArray
}
function cryptoOperation(cryptoContext) {
function processResult(result, isProcessCall) {
result = result && toArrayBufferIfSupported(result)
if (isProcessCall) {
promiseQueue.resolve(result)
return
}
return result
}
var promiseQueue = [],
op = baseOperation(processResult)
op.stream = cryptoContext.algorithm.stream
promiseQueue.add = function (label) {
var resolveFunc,
rejectFunc,
promise = new Promise(function (resolve, reject) {
resolveFunc = resolve
rejectFunc = reject
})
promise.label = label
promiseQueue.push({
resolve: resolveFunc,
reject: rejectFunc,
promise: promise,
})
return promise
}
promiseQueue.resolve = function (result) {
var queueItem = promiseQueue.shift()
queueItem.resolve.apply(queueItem.promise, [result])
}
op.process = function (buffer) {
cryptoContext.operationSubType = 'process'
cryptoContext.buffer = utils.toArray(buffer)
workerManager.continueJob(this, utils.clone(cryptoContext))
return promiseQueue.add('process')
}
op.finish = function () {
cryptoContext.operationSubType = 'finish'
cryptoContext.buffer = []
workerManager.continueJob(this, utils.clone(cryptoContext))
return promiseQueue.add('finish')
}
op.abort = function () {
workerManager.abortJob(this)
}
op.algorithm = cryptoContext.algorithm || null
op.key = cryptoContext.keyHandle || null
return op
}
var keys = []
keys.add = function (keyHandle, keyData) {
keys.push({
keyHandle: keyHandle,
keyData: keyData,
})
}
keys.remove = function (keyHandle) {
for (var i = 0; i < keys.length; i += 1) {
if (keys[i].keyHandle === keyHandle) {
keys = keys.splice(i, 1)
return
}
}
}
keys.lookup = function (keyHandle) {
for (var i = 0; i < keys.length; i += 1) {
if (keys[i].keyHandle === keyHandle) {
return keys[i].keyData
}
}
return null
}
var workerManager = (function () {
var maxWorkers = 12
var maxFreeWorkers = 2
var workerPool = []
var jobQueue = []
var jobId = 0
var workerId = 0
var callbackQueue = []
var setFunction =
typeof setImmediate === 'undefined' ? setTimeout : setImmediate
function executeNextCallback() {
callbackQueue.shift()()
}
function queueCallback(callback) {
callbackQueue.push(callback)
setFunction(executeNextCallback, 0)
}
var workerStatus = webWorkerSupport ? 'available' : 'unavailable'
function getFreeWorker() {
purgeWorkerType(!asyncMode)
for (var i = 0; i < workerPool.length; i++) {
if (!workerPool[i].busy) {
return workerPool[i]
}
}
return null
}
function purgeWorkerType(webWorker) {
for (var i = workerPool.length - 1; i >= 0; i -= 1) {
if (workerPool[i].isWebWorker === webWorker) {
workerPool[i].terminate()
workerPool.splice(i, 1)
}
}
}
function freeWorkerCount() {
var freeWorkers = 0
for (var i = 0; i < workerPool.length; i++) {
if (!workerPool[i].busy) {
freeWorkers += 1
}
}
return freeWorkers
}
function addWorkerToPool(worker) {
workerPool.push(worker)
}
function removeWorkerFromPool(worker) {
for (var i = 0; i < workerPool.length; i++) {
if (workerPool[i] === worker) {
worker.terminate()
workerPool.splice(i, 1)
return
}
}
}
function lookupWorkerByOperation(operation) {
for (var i = 0; i < workerPool.length; i++) {
if (workerPool[i].operation === operation) {
return workerPool[i]
}
}
return null
}
function queueJob(operation, data) {
jobQueue.push({
operation: operation,
data: data,
id: jobId++,
})
}
function jobCompleted(worker) {
worker.busy = false
if (asyncMode) {
if (jobQueue.length > 0) {
var job = jobQueue.shift(),
i
continueJob(job.operation, job.data)
if (job.data.operationSubType === 'process') {
for (i = 0; i < jobQueue.length; i++) {
if (job.operation === jobQueue[i].operation) {
continueJob(jobQueue[i].operation, jobQueue[i].data)
}
}
for (i = jobQueue.length - 1; i >= 0; i--) {
if (job.operation === jobQueue[i].operation) {
jobQueue.splice(i, 1)
}
}
}
} else if (freeWorkerCount() > maxFreeWorkers) {
removeWorkerFromPool(worker)
}
}
}
function createNewWorker(operation) {
var worker
if (workerStatus === 'pending') {
throw new Error('Creating new worker while workerstatus=pending')
}
if (workerStatus === 'ready') {
try {
worker = new Worker(scriptUrl)
worker.postMessage({
prngSeed: msrcryptoPseudoRandom.getBytes(48),
})
worker.isWebWorker = true
} catch (ex) {
asyncMode = false
workerStatus = 'failed'
worker.terminate()
worker = syncWorker()
worker.isWebWorker = false
}
} else {
worker = syncWorker()
worker.isWebWorker = false
}
worker.operation = operation
worker.id = workerId++
worker.busy = false
worker.onmessage = function (e) {
if (e.data.initialized === true) {
return
}
var op = worker.operation
e.target ||
(e.target = {
data: worker.data,
})
for (var i = 0; i < jobQueue.length; i++) {
if (jobQueue[i].operation === worker.operation) {
var job = jobQueue[i]
jobQueue.splice(i, 1)
postMessageToWorker(worker, job.data)
return
}
}
if (!(e.data.hasOwnProperty('type') && e.data.type === 'process')) {
jobCompleted(worker)
}
op.dispatchEvent(e)
}
worker.onerror = function (e) {
var op = worker.operation
jobCompleted(worker)
op.dispatchEvent(e)
}
addWorkerToPool(worker)
return worker
}
function useWebWorkers(enable) {
if (workerStatus === 'unavailable') {
utils.consoleLog('web workers not available in this browser.')
return
}
if (enable === true && workerStatus === 'ready') {
return
}
if (enable === false && workerStatus === 'available') {
return
}
if (enable === false && workerStatus === 'ready') {
asyncMode = false
workerStatus = 'available'
utils.consoleLog('web workers disabled.')
return
}
if (workerStatus === 'pending') {
return
}
workerStatus = 'pending'
var worker = new Worker(scriptUrl)
function setWorkerStatus(e) {
var succeeded = !!(e.data && e.data.initialized === true)
worker.removeEventListener('message', setWorkerStatus, false)
worker.removeEventListener('error', setWorkerStatus, false)
worker.terminate()
workerStatus = succeeded ? 'ready' : 'failed'
asyncMode = succeeded
utils.consoleLog(
'web worker initialization ' +
(succeeded
? 'succeeded. Now using web workers.'
: 'failed. running synchronously.' + (e.message || '')),
)
if (jobQueue.length > 0) {
var job = jobQueue.shift()
runJob(job.operation, job.data)
}
return
}
worker.addEventListener('message', setWorkerStatus, false)
worker.addEventListener('error', setWorkerStatus, false)
worker.postMessage({
prngSeed: msrcryptoPseudoRandom.getBytes(48),
})
return
}
function abortJob(cryptoOperationObject) {
var worker = lookupWorkerByOperation(cryptoOperationObject)
if (worker) {
removeWorkerFromPool(worker)
}
}
function runJob(operation, data) {
var worker = null
if (workerStatus === 'pending') {
queueJob(operation, data)
return
}
worker = getFreeWorker()
if (asyncMode && worker === null && workerPool.length >= maxWorkers) {
queueJob(operation, data)
return
}
if (worker === null) {
worker = createNewWorker(operation)
}
if (worker === null) {
queueJob(operation, data)
throw new Error('could not create new worker')
}
worker.operation = operation
worker.busy = true
data.workerid = worker.id
postMessageToWorker(worker, data)
}
function continueJob(operation, data) {
var worker = lookupWorkerByOperation(operation)
if (worker) {
postMessageToWorker(worker, data)
return
}
runJob(operation, data)
}
function postMessageToWorker(worker, data) {
data.workerid = worker.id
if (asyncMode) {
worker.postMessage(data)
} else {
var func = (function (postData) {
return function () {
return worker.postMessage(postData)
}
})(data)
queueCallback(func)
}
return
}
return {
runJob: runJob,
continueJob: continueJob,
abortJob: abortJob,
useWebWorkers: useWebWorkers,
}
})()
function checkOperation(operationType, algorithmName) {
if (!operations.exists(operationType, algorithmName)) {
throw new Error('unsupported algorithm')
}
}
var subtleParameters = [
{
name: 'algorithm',
type: 'Object',
required: true,
},
{
name: 'keyHandle',
type: 'Object',
required: true,
},
{
name: 'buffer',
type: 'Array',
required: false,
},
{
name: 'signature',
type: 'Array',
required: true,
},
{
name: 'format',
type: 'String',
required: true,
},
{
name: 'keyData',
type: 'Object',
required: true,
},
{
name: 'extractable',
type: 'Boolean',
required: false,
},
{
name: 'usages',
type: 'Array',
required: false,
},
{
name: 'derivedKeyType',
type: 'Object',
required: true,
},
{
name: 'length',
type: 'Number',
required: false,
},
{
name: 'extractable',
type: 'Boolean',
required: true,
},
{
name: 'usages',
type: 'Array',
required: true,
},
{
name: 'keyData',
type: 'Array',
required: true,
},
]
var subtleParametersSets = {
encrypt: [0, 1, 2],
decrypt: [0, 1, 2],
sign: [0, 1, 2],
verify: [0, 1, 3, 2],
digest: [0, 2],
generateKey: [0, 6, 7],
importKeyRaw: [4, 12, 0, 10, 11],
importKeyJwk: [4, 5, 0, 10, 11],
exportKey: [0, 4, 1, 6, 7],
deriveKey: [0, 1, 8, 6, 7],
deriveBits: [0, 1, 9],
wrapKey: [1, 1, 0],
unwrapKey: [2, 0, 1, 6, 7],
}
function lookupKeyData(handle) {
var data = keys.lookup(handle)
if (!data) {
throw new Error('key not found')
}
return data
}
function buildParameterCollection(operationName, parameterSet) {
var parameterCollection = {
operationType: operationName,
},
operationParameterSet,
expectedParam,
actualParam,
i
if (
operationName === 'importKey' &&
(parameterSet[0] === 'raw' || parameterSet[0] === 'spki')
) {
operationName = 'importKeyRaw'
}
if (operationName === 'importKey' && parameterSet[0] === 'jwk') {
operationName = 'importKeyJwk'
}
operationParameterSet = subtleParametersSets[operationName]
for (i = 0; i < operationParameterSet.length; i += 1) {
expectedParam = subtleParameters[operationParameterSet[i]]
actualParam = parameterSet[i]
if (actualParam == null) {
if (expectedParam.required) {
throw new Error(expectedParam.name)
} else {
continue
}
}
if (actualParam.subarray) {
actualParam = utils.toArray(actualParam)
}
if (utils.getObjectType(actualParam) === 'ArrayBuffer') {
actualParam = utils.toArray(actualParam)
}
if (
msrcryptoUtilities.getObjectType(actualParam) !== expectedParam.type
) {
throw new Error(expectedParam.name)
}
if (expectedParam.name === 'algorithm') {
actualParam.name = actualParam.name.toUpperCase()
if (actualParam.iv) {
actualParam.iv = utils.toArray(actualParam.iv)
}
if (actualParam.publicExponent) {
actualParam.publicExponent = utils.toArray(
actualParam.publicExponent,
)
}
if (actualParam.salt) {
actualParam.salt = utils.toArray(actualParam.salt)
}
if (actualParam.additionalData) {
actualParam.additionalData = utils.toArray(
actualParam.additionalData,
)
}
if (
actualParam.hash &&
!actualParam.hash.name &&
utils.getObjectType(actualParam.hash) === 'String'
) {
actualParam.hash = {
name: actualParam.hash,
}
}
}
if (parameterCollection.hasOwnProperty(expectedParam.name)) {
parameterCollection[expectedParam.name + '1'] = actualParam
} else {
parameterCollection[expectedParam.name] = actualParam
}
}
return parameterCollection
}
function executeOperation(operationName, parameterSet, keyFunc) {
var pc = buildParameterCollection(operationName, parameterSet)
checkOperation(operationName, pc.algorithm.name)
if (pc.keyHandle) {
pc.keyData = lookupKeyData(pc.keyHandle)
}
if (pc.keyHandle1) {
pc.keyData1 = lookupKeyData(pc.keyHandle1)
}
if (pc.algorithm && pc.algorithm.public) {
pc.additionalKeyData = lookupKeyData(pc.algorithm.public)
}
var op = keyFunc ? keyOperation(pc) : cryptoOperation(pc)
if (
keyFunc ||
pc.buffer ||
operationName === 'deriveBits' ||
operationName === 'wrapKey'
) {
workerManager.runJob(op, pc)
}
if (op.stream) {
return Promise.resolve(streamObject(op))
}
return op.promise
}
var publicMethods = {
encrypt: function (algorithm, keyHandle, buffer) {
return executeOperation('encrypt', arguments, 0)
},
decrypt: function (algorithm, keyHandle, buffer) {
return executeOperation('decrypt', arguments, 0)
},
sign: function (algorithm, keyHandle, buffer) {
return executeOperation('sign', arguments, 0)
},
verify: function (algorithm, keyHandle, signature, buffer) {
return executeOperation('verify', arguments, 0)
},
digest: function (algorithm, buffer) {
return executeOperation('digest', arguments, 0)
},
generateKey: function (algorithm, extractable, keyUsage) {
return executeOperation('generateKey', arguments, 1)
},
deriveKey: function (
algorithm,
baseKey,
derivedKeyType,
extractable,
keyUsage,
) {
var deriveBits = this.deriveBits,
importKey = this.importKey
return new Promise(function (resolve, reject) {
var keyLength
switch (derivedKeyType.name.toUpperCase()) {
case 'AES-CBC':
case 'AES-GCM':
keyLength = derivedKeyType.length
break
case 'HMAC':
keyLength =
derivedKeyType.length ||
{
'SHA-1': 512,
'SHA-224': 512,
'SHA-256': 512,
'SHA-384': 1024,
'SHA-512': 1024,
}[derivedKeyType.hash.name.toUpperCase()]
break
default:
reject(new Error('No Supported'))
return
}
deriveBits(algorithm, baseKey, keyLength)
.then(function (bits) {
return importKey(
'raw',
bits,
derivedKeyType,
extractable,
keyUsage,
)
})
.then(function (key) {
resolve(key)
})
['catch'](function (err) {
reject(err)
})
})
},
deriveBits: function (algorithm, baseKey, length) {
return executeOperation('deriveBits', arguments, 0)
},
importKey: function (
format,
keyData,
algorithm,
extractable,
keyUsage,
) {
return executeOperation('importKey', arguments, 1)
},
exportKey: function (format, keyHandle) {
return executeOperation(
'exportKey',
[keyHandle.algorithm, format, keyHandle],
1,
)
},
wrapKey: function (format, key, wrappingKey, wrappingKeyAlgorithm) {
var encrypt = this.encrypt,
exportKey = this.exportKey
return new Promise(function (resolve, reject) {
if (
key.extractable === false ||
key.usages.indexOf('wrapKey') < 0 ||
wrappingKey.algorithm.name.toUpperCase() !==
wrappingKeyAlgorithm.name
) {
reject(new Error('InvalidAccessError'))
return
}
exportKey(format, key)
.then(function (keyData) {
return encrypt(
wrappingKeyAlgorithm,
wrappingKey,
format === 'jwk'
? utils.stringToBytes(JSON.stringify(keyData, null, 0))
: keyData,
)
})
.then(function (cipherArrayBuffer) {
resolve(cipherArrayBuffer)
})
['catch'](function (err) {
reject(err)
})
})
},
unwrapKey: function (
format,
wrappedKey,
unwrappingKey,
unwrapAlgorithm,
unwrappedKeyAlgorithm,
extractable,
keyUsages,
) {
var decrypt = this.decrypt,
importKey = this.importKey
return new Promise(function (resolve, reject) {
if (
unwrappingKey.usages.indexOf('unwrapKey') < 0 ||
unwrappingKey.algorithm.name.toUpperCase() !==
unwrapAlgorithm.name
) {
reject(new Error('InvalidAccessError'))
return
}
decrypt(unwrapAlgorithm, unwrappingKey, wrappedKey)
.then(function (keyPlain) {
return importKey(
format,
format === 'jwk'
? JSON.parse(utils.bytesToString(keyPlain))
: keyPlain,
unwrappedKeyAlgorithm,
extractable,
keyUsages,
)
})
.then(function (key) {
resolve(key)
})
['catch'](function (err) {
reject(err)
})
})
},
}
var internalMethods = {
useWebWorkers: workerManager.useWebWorkers,
}
return {
publicMethods: publicMethods,
internalMethods: internalMethods,
}
})()
var msrcryptoWrapKey = (function () {
var utils = msrcryptoUtilities
function wrapKey(params) {
var rsaObj = msrcryptoRsa(
params.keyData1,
params.keyHandle1.algorithm.name,
msrcryptoHashFunctions['SHA-1'],
)()
var tagLength = 128
var keyToWrapJwk = msrcryptoJwk.keyToJwkOld(
params.keyHandle,
params.keyData,
)
var jweHeader = {
alg: params.keyHandle1.algorithm.name.toUpperCase(),
enc: 'A128GCM',
}
var encodedJweHeader = utils.toBase64(JSON.stringify(jweHeader), true)
var cmk = msrcryptoPseudoRandom.getBytes(32)
var jweEncryptedKey = rsaObj.encrypt(cmk)
var encodedJweEncryptedKey = utils.toBase64(jweEncryptedKey, true)
var jweIv = msrcryptoPseudoRandom.getBytes(12)
var encodedJweIv = utils.toBase64(jweIv, true)
var additionalData = encodedJweHeader.concat(
'.',
encodedJweEncryptedKey,
'.',
encodedJweIv,
)
var gcm = msrcryptoGcm(msrcryptoBlockCipher.aes(cmk))
gcm.init(jweIv, utils.stringToBytes(additionalData), tagLength)
var ciphertextPlusTag = gcm.encrypt(keyToWrapJwk)
var tag = ciphertextPlusTag.slice(-(tagLength / 8))
var encodedIntegrityValue = utils.toBase64(tag, true)
var encodedCiphertext = utils.toBase64(
ciphertextPlusTag.slice(0, ciphertextPlusTag.length - tag.length),
true,
)
var jwe = {
recipients: [
{
header: encodedJweHeader,
encrypted_key: encodedJweEncryptedKey,
integrity_value: encodedIntegrityValue,
},
],
initialization_vector: encodedJweIv,
ciphertext: encodedCiphertext,
}
return utils.stringToBytes(JSON.stringify(jwe))
}
function unwrapKey(params) {
var b64Tobytes = utils.fromBase64
var keyDataJwk = JSON.parse(
String.fromCharCode.apply(null, params.buffer),
)
var header = utils.fromBase64(keyDataJwk.recipients[0].header)
var encrypted_key = b64Tobytes(keyDataJwk.recipients[0].encrypted_key)
var integrity_value = b64Tobytes(
keyDataJwk.recipients[0].integrity_value,
)
var initialization_vector = b64Tobytes(keyDataJwk.initialization_vector)
var ciphertext = b64Tobytes(keyDataJwk.ciphertext)
var hashFunc = msrcryptoHashFunctions['SHA-1']()
var rsaObj = msrcryptoRsa(
params.keyData,
params.keyHandle.algorithm.name,
hashFunc,
)
var inKey = rsaObj.decrypt(encrypted_key)
var additionalData = keyDataJwk.recipients[0].header.concat(
'.',
keyDataJwk.recipients[0].encrypted_key,
'.',
keyDataJwk.initialization_vector,
)
var gcm = msrcryptoGcm(msrcryptoBlockCipher.aes(inKey))
gcm.init(
initialization_vector,
utils.stringToBytes(additionalData),
128,
)
var result = gcm.decrypt(ciphertext, integrity_value)
var keyObject = msrcryptoJwk.jwkToKey(result, params.algorithm, ['k'])
return {
type: 'keyImport',
keyData: keyObject.k,
keyHandle: {
algorithm: {
name: params.algorithm.name,
},
extractable: params.extractable || keyObject.extractable,
usages: params.usages,
type: 'secret',
},
}
}
return {
wrapKey: wrapKey,
unwrapKey: unwrapKey,
}
})()
if (typeof operations !== 'undefined') {
operations.register('wrapKey', 'AES-GCM', msrcryptoWrapKey.wrapKey)
operations.register('unwrapKey', 'AES-CBC', msrcryptoWrapKey.unwrapKey)
}
var publicMethods = {
subtle: msrcryptoSubtle ? msrcryptoSubtle.publicMethods : null,
getRandomValues: function (array) {
var i
var randomValues = msrcryptoPseudoRandom.getBytes(array.length)
for (i = 0; i < array.length; i += 1) {
array[i] = randomValues[i]
}
return array
},
initPrng: function (entropyData) {
var entropyDataType = Object.prototype.toString.call(entropyData)
if (
entropyDataType !== '[object Array]' &&
entropyDataType !== '[object Uint8Array]'
) {
throw new Error('entropyData must be a Array or Uint8Array')
}
entropyPool && entropyPool.reseed(entropyData)
msrcryptoPseudoRandom.reseed(entropyPool.read(48))
fprngEntropyProvided = true
},
toBase64: function (data, base64Url) {
return msrcryptoUtilities.toBase64(data, base64Url)
},
fromBase64: function (base64String) {
return msrcryptoUtilities.fromBase64(base64String)
},
textToBytes: function (text) {
return msrcryptoUtilities.stringToBytes(text)
},
bytesToText: function (byteArray) {
return msrcryptoUtilities.bytesToString(byteArray)
},
asn1: asn1,
url: scriptUrl,
version: msrCryptoVersion,
useWebWorkers: function (useWebWorkers) {
return msrcryptoSubtle
? msrcryptoSubtle.internalMethods.useWebWorkers(useWebWorkers)
: null
},
}
var entropyPool
entropyPool = entropyPool || new MsrcryptoEntropy(global)
entropyPool.init()
var localEntropy = entropyPool.read(48)
msrcryptoPseudoRandom.init(localEntropy)
return publicMethods
}
return msrCrypto()
})
;(function (root, factory) {
if (typeof Promise !== 'undefined') {
return
}
root.Promise = factory()
})(this, function () {
var Promise = function (executor, id) {
if (!(this instanceof Promise)) {
throw new Error("use 'new' keyword with Promise constructor")
}
var successResult = null,
failReason = null,
thenResolved = [],
thenRejected = [],
rejectThenPromise = [],
resolveThenPromise = []
this.then = function (onCompleted, onRejected) {
var thenFunctionResult
if (successResult) {
thenFunctionResult = onCompleted(successResult.result)
if (thenFunctionResult && thenFunctionResult.then) {
return thenFunctionResult
}
return Promise.resolve(thenFunctionResult)
}
if (failReason) {
thenFunctionResult = onRejected
? onRejected(failReason.result)
: failReason.result
if (thenFunctionResult && thenFunctionResult.then) {
return thenFunctionResult
}
return Promise.resolve(thenFunctionResult)
}
thenResolved.push(onCompleted)
if (onRejected) {
thenRejected.push(onRejected)
}
return new Promise(function (resolve, reject) {
resolveThenPromise.push(resolve)
rejectThenPromise.push(reject)
})
}
this['catch'] = function (onRejected) {
var catchFunctionResult
if (failReason) {
catchFunctionResult = onRejected(failReason.result)
if (catchFunctionResult && catchFunctionResult.then) {
return catchFunctionResult
}
return Promise.resolve(catchFunctionResult)
}
thenRejected.push(onRejected)
return new Promise(function (resolve, reject) {
resolveThenPromise.push(resolve)
rejectThenPromise.push(reject)
})
}
function resolve(param) {
var result, i
for (i = 0; i < thenResolved.length; i += 1) {
result = thenResolved[i](param)
if (result && result.then) {
result.then(resolveThenPromise[i])
if (rejectThenPromise[i]) {
result['catch'](rejectThenPromise[i])
}
} else {
if (resolveThenPromise[i]) {
resolveThenPromise[i](result)
}
}
}
successResult = {
result: param,
}
return
}
function reject(param) {
var reason, i
for (i = 0; i < thenRejected.length; i += 1) {
reason = thenRejected[i](param)
if (reason && reason.then) {
reason.then(resolveThenPromise[i], rejectThenPromise[i])
} else {
if (resolveThenPromise[i]) {
resolveThenPromise[i](reason)
}
}
}
failReason = {
result: param,
}
return
}
executor(resolve, reject)
return
}
Promise.all = function (promiseArray) {
var results = [],
resultCount = 0,
promiseAll
function then(index, resolve) {
return function (result) {
results[index] = result
resultCount += 1
if (resultCount === promiseArray.length) {
resolve(results)
}
}
}
promiseAll = new Promise(function (resolve, reject) {
var i
function r(reason) {
reject(reason)
}
for (i = 0; i < promiseArray.length; i += 1) {
if (promiseArray[i].then) {
promiseArray[i].then(then(i, resolve))
promiseArray[i]['catch'](r)
continue
}
Promise.resolve(promiseArray[i]).then(then(i, resolve))
}
})
return promiseAll
}
Promise.race = function (promiseArray) {
var resolved = false,
promiseRace
function then(resolveFunction) {
return function (result) {
if (!resolved) {
resolved = true
resolveFunction(result)
}
}
}
promiseRace = new Promise(function (resolve, reject) {
for (var i = 0; i < promiseArray.length; i += 1) {
promiseArray[i].then(then(resolve), then(reject))
}
})
return promiseRace
}
Promise.reject = function (rejectReason) {
return new Promise(function (resolve, reject) {
reject(rejectReason)
})
}
Promise.resolve = function (resolveResult) {
return new Promise(function (resolve, reject) {
resolve(resolveResult)
})
}
return Promise
})