ndn-telehash-transport
Version:
telehash transport module for NDN
15,130 lines • 723 kB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
* @license MIT
*/
var base64 = require('base64-js')
var ieee754 = require('ieee754')
exports.Buffer = Buffer
exports.SlowBuffer = Buffer
exports.INSPECT_MAX_BYTES = 50
Buffer.poolSize = 8192
/**
* If `Buffer._useTypedArrays`:
* === true Use Uint8Array implementation (fastest)
* === false Use Object implementation (compatible down to IE6)
*/
Buffer._useTypedArrays = (function () {
// Detect if browser supports Typed Arrays. Supported browsers are IE 10+, Firefox 4+,
// Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. If the browser does not support adding
// properties to `Uint8Array` instances, then that's the same as no `Uint8Array` support
// because we need to be able to add all the node Buffer API methods. This is an issue
// in Firefox 4-29. Now fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=695438
try {
var buf = new ArrayBuffer(0)
var arr = new Uint8Array(buf)
arr.foo = function () { return 42 }
return 42 === arr.foo() &&
typeof arr.subarray === 'function' // Chrome 9-10 lack `subarray`
} catch (e) {
return false
}
})()
/**
* Class: Buffer
* =============
*
* The Buffer constructor returns instances of `Uint8Array` that are augmented
* with function properties for all the node `Buffer` API functions. We use
* `Uint8Array` so that square bracket notation works as expected -- it returns
* a single octet.
*
* By augmenting the instances, we can avoid modifying the `Uint8Array`
* prototype.
*/
function Buffer (subject, encoding, noZero) {
if (!(this instanceof Buffer))
return new Buffer(subject, encoding, noZero)
var type = typeof subject
// Workaround: node's base64 implementation allows for non-padded strings
// while base64-js does not.
if (encoding === 'base64' && type === 'string') {
subject = stringtrim(subject)
while (subject.length % 4 !== 0) {
subject = subject + '='
}
}
// Find the length
var length
if (type === 'number')
length = coerce(subject)
else if (type === 'string')
length = Buffer.byteLength(subject, encoding)
else if (type === 'object')
length = coerce(subject.length) // assume that object is array-like
else
throw new Error('First argument needs to be a number, array or string.')
var buf
if (Buffer._useTypedArrays) {
// Preferred: Return an augmented `Uint8Array` instance for best performance
buf = Buffer._augment(new Uint8Array(length))
} else {
// Fallback: Return THIS instance of Buffer (created by `new`)
buf = this
buf.length = length
buf._isBuffer = true
}
var i
if (Buffer._useTypedArrays && typeof subject.byteLength === 'number') {
// Speed optimization -- use set if we're copying from a typed array
buf._set(subject)
} else if (isArrayish(subject)) {
// Treat array-ish objects as a byte array
for (i = 0; i < length; i++) {
if (Buffer.isBuffer(subject))
buf[i] = subject.readUInt8(i)
else
buf[i] = subject[i]
}
} else if (type === 'string') {
buf.write(subject, 0, encoding)
} else if (type === 'number' && !Buffer._useTypedArrays && !noZero) {
for (i = 0; i < length; i++) {
buf[i] = 0
}
}
return buf
}
// STATIC METHODS
// ==============
Buffer.isEncoding = function (encoding) {
switch (String(encoding).toLowerCase()) {
case 'hex':
case 'utf8':
case 'utf-8':
case 'ascii':
case 'binary':
case 'base64':
case 'raw':
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
return true
default:
return false
}
}
Buffer.isBuffer = function (b) {
return !!(b !== null && b !== undefined && b._isBuffer)
}
Buffer.byteLength = function (str, encoding) {
var ret
str = str + ''
switch (encoding || 'utf8') {
case 'hex':
ret = str.length / 2
break
case 'utf8':
case 'utf-8':
ret = utf8ToBytes(str).length
break
case 'ascii':
case 'binary':
case 'raw':
ret = str.length
break
case 'base64':
ret = base64ToBytes(str).length
break
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
ret = str.length * 2
break
default:
throw new Error('Unknown encoding')
}
return ret
}
Buffer.concat = function (list, totalLength) {
assert(isArray(list), 'Usage: Buffer.concat(list, [totalLength])\n' +
'list should be an Array.')
if (list.length === 0) {
return new Buffer(0)
} else if (list.length === 1) {
return list[0]
}
var i
if (typeof totalLength !== 'number') {
totalLength = 0
for (i = 0; i < list.length; i++) {
totalLength += list[i].length
}
}
var buf = new Buffer(totalLength)
var pos = 0
for (i = 0; i < list.length; i++) {
var item = list[i]
item.copy(buf, pos)
pos += item.length
}
return buf
}
// BUFFER INSTANCE METHODS
// =======================
function _hexWrite (buf, string, offset, length) {
offset = Number(offset) || 0
var remaining = buf.length - offset
if (!length) {
length = remaining
} else {
length = Number(length)
if (length > remaining) {
length = remaining
}
}
// must be an even number of digits
var strLen = string.length
assert(strLen % 2 === 0, 'Invalid hex string')
if (length > strLen / 2) {
length = strLen / 2
}
for (var i = 0; i < length; i++) {
var byte = parseInt(string.substr(i * 2, 2), 16)
assert(!isNaN(byte), 'Invalid hex string')
buf[offset + i] = byte
}
Buffer._charsWritten = i * 2
return i
}
function _utf8Write (buf, string, offset, length) {
var charsWritten = Buffer._charsWritten =
blitBuffer(utf8ToBytes(string), buf, offset, length)
return charsWritten
}
function _asciiWrite (buf, string, offset, length) {
var charsWritten = Buffer._charsWritten =
blitBuffer(asciiToBytes(string), buf, offset, length)
return charsWritten
}
function _binaryWrite (buf, string, offset, length) {
return _asciiWrite(buf, string, offset, length)
}
function _base64Write (buf, string, offset, length) {
var charsWritten = Buffer._charsWritten =
blitBuffer(base64ToBytes(string), buf, offset, length)
return charsWritten
}
function _utf16leWrite (buf, string, offset, length) {
var charsWritten = Buffer._charsWritten =
blitBuffer(utf16leToBytes(string), buf, offset, length)
return charsWritten
}
Buffer.prototype.write = function (string, offset, length, encoding) {
// Support both (string, offset, length, encoding)
// and the legacy (string, encoding, offset, length)
if (isFinite(offset)) {
if (!isFinite(length)) {
encoding = length
length = undefined
}
} else { // legacy
var swap = encoding
encoding = offset
offset = length
length = swap
}
offset = Number(offset) || 0
var remaining = this.length - offset
if (!length) {
length = remaining
} else {
length = Number(length)
if (length > remaining) {
length = remaining
}
}
encoding = String(encoding || 'utf8').toLowerCase()
var ret
switch (encoding) {
case 'hex':
ret = _hexWrite(this, string, offset, length)
break
case 'utf8':
case 'utf-8':
ret = _utf8Write(this, string, offset, length)
break
case 'ascii':
ret = _asciiWrite(this, string, offset, length)
break
case 'binary':
ret = _binaryWrite(this, string, offset, length)
break
case 'base64':
ret = _base64Write(this, string, offset, length)
break
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
ret = _utf16leWrite(this, string, offset, length)
break
default:
throw new Error('Unknown encoding')
}
return ret
}
Buffer.prototype.toString = function (encoding, start, end) {
var self = this
encoding = String(encoding || 'utf8').toLowerCase()
start = Number(start) || 0
end = (end !== undefined)
? Number(end)
: end = self.length
// Fastpath empty strings
if (end === start)
return ''
var ret
switch (encoding) {
case 'hex':
ret = _hexSlice(self, start, end)
break
case 'utf8':
case 'utf-8':
ret = _utf8Slice(self, start, end)
break
case 'ascii':
ret = _asciiSlice(self, start, end)
break
case 'binary':
ret = _binarySlice(self, start, end)
break
case 'base64':
ret = _base64Slice(self, start, end)
break
case 'ucs2':
case 'ucs-2':
case 'utf16le':
case 'utf-16le':
ret = _utf16leSlice(self, start, end)
break
default:
throw new Error('Unknown encoding')
}
return ret
}
Buffer.prototype.toJSON = function () {
return {
type: 'Buffer',
data: Array.prototype.slice.call(this._arr || this, 0)
}
}
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
Buffer.prototype.copy = function (target, target_start, start, end) {
var source = this
if (!start) start = 0
if (!end && end !== 0) end = this.length
if (!target_start) target_start = 0
// Copy 0 bytes; we're done
if (end === start) return
if (target.length === 0 || source.length === 0) return
// Fatal error conditions
assert(end >= start, 'sourceEnd < sourceStart')
assert(target_start >= 0 && target_start < target.length,
'targetStart out of bounds')
assert(start >= 0 && start < source.length, 'sourceStart out of bounds')
assert(end >= 0 && end <= source.length, 'sourceEnd out of bounds')
// Are we oob?
if (end > this.length)
end = this.length
if (target.length - target_start < end - start)
end = target.length - target_start + start
var len = end - start
if (len < 100 || !Buffer._useTypedArrays) {
for (var i = 0; i < len; i++)
target[i + target_start] = this[i + start]
} else {
target._set(this.subarray(start, start + len), target_start)
}
}
function _base64Slice (buf, start, end) {
if (start === 0 && end === buf.length) {
return base64.fromByteArray(buf)
} else {
return base64.fromByteArray(buf.slice(start, end))
}
}
function _utf8Slice (buf, start, end) {
var res = ''
var tmp = ''
end = Math.min(buf.length, end)
for (var i = start; i < end; i++) {
if (buf[i] <= 0x7F) {
res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i])
tmp = ''
} else {
tmp += '%' + buf[i].toString(16)
}
}
return res + decodeUtf8Char(tmp)
}
function _asciiSlice (buf, start, end) {
var ret = ''
end = Math.min(buf.length, end)
for (var i = start; i < end; i++)
ret += String.fromCharCode(buf[i])
return ret
}
function _binarySlice (buf, start, end) {
return _asciiSlice(buf, start, end)
}
function _hexSlice (buf, start, end) {
var len = buf.length
if (!start || start < 0) start = 0
if (!end || end < 0 || end > len) end = len
var out = ''
for (var i = start; i < end; i++) {
out += toHex(buf[i])
}
return out
}
function _utf16leSlice (buf, start, end) {
var bytes = buf.slice(start, end)
var res = ''
for (var i = 0; i < bytes.length; i += 2) {
res += String.fromCharCode(bytes[i] + bytes[i+1] * 256)
}
return res
}
Buffer.prototype.slice = function (start, end) {
var len = this.length
start = clamp(start, len, 0)
end = clamp(end, len, len)
if (Buffer._useTypedArrays) {
return Buffer._augment(this.subarray(start, end))
} else {
var sliceLen = end - start
var newBuf = new Buffer(sliceLen, undefined, true)
for (var i = 0; i < sliceLen; i++) {
newBuf[i] = this[i + start]
}
return newBuf
}
}
// `get` will be removed in Node 0.13+
Buffer.prototype.get = function (offset) {
console.log('.get() is deprecated. Access using array indexes instead.')
return this.readUInt8(offset)
}
// `set` will be removed in Node 0.13+
Buffer.prototype.set = function (v, offset) {
console.log('.set() is deprecated. Access using array indexes instead.')
return this.writeUInt8(v, offset)
}
Buffer.prototype.readUInt8 = function (offset, noAssert) {
if (!noAssert) {
assert(offset !== undefined && offset !== null, 'missing offset')
assert(offset < this.length, 'Trying to read beyond buffer length')
}
if (offset >= this.length)
return
return this[offset]
}
function _readUInt16 (buf, offset, littleEndian, noAssert) {
if (!noAssert) {
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
assert(offset !== undefined && offset !== null, 'missing offset')
assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')
}
var len = buf.length
if (offset >= len)
return
var val
if (littleEndian) {
val = buf[offset]
if (offset + 1 < len)
val |= buf[offset + 1] << 8
} else {
val = buf[offset] << 8
if (offset + 1 < len)
val |= buf[offset + 1]
}
return val
}
Buffer.prototype.readUInt16LE = function (offset, noAssert) {
return _readUInt16(this, offset, true, noAssert)
}
Buffer.prototype.readUInt16BE = function (offset, noAssert) {
return _readUInt16(this, offset, false, noAssert)
}
function _readUInt32 (buf, offset, littleEndian, noAssert) {
if (!noAssert) {
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
assert(offset !== undefined && offset !== null, 'missing offset')
assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')
}
var len = buf.length
if (offset >= len)
return
var val
if (littleEndian) {
if (offset + 2 < len)
val = buf[offset + 2] << 16
if (offset + 1 < len)
val |= buf[offset + 1] << 8
val |= buf[offset]
if (offset + 3 < len)
val = val + (buf[offset + 3] << 24 >>> 0)
} else {
if (offset + 1 < len)
val = buf[offset + 1] << 16
if (offset + 2 < len)
val |= buf[offset + 2] << 8
if (offset + 3 < len)
val |= buf[offset + 3]
val = val + (buf[offset] << 24 >>> 0)
}
return val
}
Buffer.prototype.readUInt32LE = function (offset, noAssert) {
return _readUInt32(this, offset, true, noAssert)
}
Buffer.prototype.readUInt32BE = function (offset, noAssert) {
return _readUInt32(this, offset, false, noAssert)
}
Buffer.prototype.readInt8 = function (offset, noAssert) {
if (!noAssert) {
assert(offset !== undefined && offset !== null,
'missing offset')
assert(offset < this.length, 'Trying to read beyond buffer length')
}
if (offset >= this.length)
return
var neg = this[offset] & 0x80
if (neg)
return (0xff - this[offset] + 1) * -1
else
return this[offset]
}
function _readInt16 (buf, offset, littleEndian, noAssert) {
if (!noAssert) {
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
assert(offset !== undefined && offset !== null, 'missing offset')
assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')
}
var len = buf.length
if (offset >= len)
return
var val = _readUInt16(buf, offset, littleEndian, true)
var neg = val & 0x8000
if (neg)
return (0xffff - val + 1) * -1
else
return val
}
Buffer.prototype.readInt16LE = function (offset, noAssert) {
return _readInt16(this, offset, true, noAssert)
}
Buffer.prototype.readInt16BE = function (offset, noAssert) {
return _readInt16(this, offset, false, noAssert)
}
function _readInt32 (buf, offset, littleEndian, noAssert) {
if (!noAssert) {
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
assert(offset !== undefined && offset !== null, 'missing offset')
assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')
}
var len = buf.length
if (offset >= len)
return
var val = _readUInt32(buf, offset, littleEndian, true)
var neg = val & 0x80000000
if (neg)
return (0xffffffff - val + 1) * -1
else
return val
}
Buffer.prototype.readInt32LE = function (offset, noAssert) {
return _readInt32(this, offset, true, noAssert)
}
Buffer.prototype.readInt32BE = function (offset, noAssert) {
return _readInt32(this, offset, false, noAssert)
}
function _readFloat (buf, offset, littleEndian, noAssert) {
if (!noAssert) {
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')
}
return ieee754.read(buf, offset, littleEndian, 23, 4)
}
Buffer.prototype.readFloatLE = function (offset, noAssert) {
return _readFloat(this, offset, true, noAssert)
}
Buffer.prototype.readFloatBE = function (offset, noAssert) {
return _readFloat(this, offset, false, noAssert)
}
function _readDouble (buf, offset, littleEndian, noAssert) {
if (!noAssert) {
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
assert(offset + 7 < buf.length, 'Trying to read beyond buffer length')
}
return ieee754.read(buf, offset, littleEndian, 52, 8)
}
Buffer.prototype.readDoubleLE = function (offset, noAssert) {
return _readDouble(this, offset, true, noAssert)
}
Buffer.prototype.readDoubleBE = function (offset, noAssert) {
return _readDouble(this, offset, false, noAssert)
}
Buffer.prototype.writeUInt8 = function (value, offset, noAssert) {
if (!noAssert) {
assert(value !== undefined && value !== null, 'missing value')
assert(offset !== undefined && offset !== null, 'missing offset')
assert(offset < this.length, 'trying to write beyond buffer length')
verifuint(value, 0xff)
}
if (offset >= this.length) return
this[offset] = value
}
function _writeUInt16 (buf, value, offset, littleEndian, noAssert) {
if (!noAssert) {
assert(value !== undefined && value !== null, 'missing value')
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
assert(offset !== undefined && offset !== null, 'missing offset')
assert(offset + 1 < buf.length, 'trying to write beyond buffer length')
verifuint(value, 0xffff)
}
var len = buf.length
if (offset >= len)
return
for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) {
buf[offset + i] =
(value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
(littleEndian ? i : 1 - i) * 8
}
}
Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) {
_writeUInt16(this, value, offset, true, noAssert)
}
Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) {
_writeUInt16(this, value, offset, false, noAssert)
}
function _writeUInt32 (buf, value, offset, littleEndian, noAssert) {
if (!noAssert) {
assert(value !== undefined && value !== null, 'missing value')
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
assert(offset !== undefined && offset !== null, 'missing offset')
assert(offset + 3 < buf.length, 'trying to write beyond buffer length')
verifuint(value, 0xffffffff)
}
var len = buf.length
if (offset >= len)
return
for (var i = 0, j = Math.min(len - offset, 4); i < j; i++) {
buf[offset + i] =
(value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
}
}
Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) {
_writeUInt32(this, value, offset, true, noAssert)
}
Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) {
_writeUInt32(this, value, offset, false, noAssert)
}
Buffer.prototype.writeInt8 = function (value, offset, noAssert) {
if (!noAssert) {
assert(value !== undefined && value !== null, 'missing value')
assert(offset !== undefined && offset !== null, 'missing offset')
assert(offset < this.length, 'Trying to write beyond buffer length')
verifsint(value, 0x7f, -0x80)
}
if (offset >= this.length)
return
if (value >= 0)
this.writeUInt8(value, offset, noAssert)
else
this.writeUInt8(0xff + value + 1, offset, noAssert)
}
function _writeInt16 (buf, value, offset, littleEndian, noAssert) {
if (!noAssert) {
assert(value !== undefined && value !== null, 'missing value')
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
assert(offset !== undefined && offset !== null, 'missing offset')
assert(offset + 1 < buf.length, 'Trying to write beyond buffer length')
verifsint(value, 0x7fff, -0x8000)
}
var len = buf.length
if (offset >= len)
return
if (value >= 0)
_writeUInt16(buf, value, offset, littleEndian, noAssert)
else
_writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert)
}
Buffer.prototype.writeInt16LE = function (value, offset, noAssert) {
_writeInt16(this, value, offset, true, noAssert)
}
Buffer.prototype.writeInt16BE = function (value, offset, noAssert) {
_writeInt16(this, value, offset, false, noAssert)
}
function _writeInt32 (buf, value, offset, littleEndian, noAssert) {
if (!noAssert) {
assert(value !== undefined && value !== null, 'missing value')
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
assert(offset !== undefined && offset !== null, 'missing offset')
assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')
verifsint(value, 0x7fffffff, -0x80000000)
}
var len = buf.length
if (offset >= len)
return
if (value >= 0)
_writeUInt32(buf, value, offset, littleEndian, noAssert)
else
_writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert)
}
Buffer.prototype.writeInt32LE = function (value, offset, noAssert) {
_writeInt32(this, value, offset, true, noAssert)
}
Buffer.prototype.writeInt32BE = function (value, offset, noAssert) {
_writeInt32(this, value, offset, false, noAssert)
}
function _writeFloat (buf, value, offset, littleEndian, noAssert) {
if (!noAssert) {
assert(value !== undefined && value !== null, 'missing value')
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
assert(offset !== undefined && offset !== null, 'missing offset')
assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')
verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38)
}
var len = buf.length
if (offset >= len)
return
ieee754.write(buf, value, offset, littleEndian, 23, 4)
}
Buffer.prototype.writeFloatLE = function (value, offset, noAssert) {
_writeFloat(this, value, offset, true, noAssert)
}
Buffer.prototype.writeFloatBE = function (value, offset, noAssert) {
_writeFloat(this, value, offset, false, noAssert)
}
function _writeDouble (buf, value, offset, littleEndian, noAssert) {
if (!noAssert) {
assert(value !== undefined && value !== null, 'missing value')
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
assert(offset !== undefined && offset !== null, 'missing offset')
assert(offset + 7 < buf.length,
'Trying to write beyond buffer length')
verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308)
}
var len = buf.length
if (offset >= len)
return
ieee754.write(buf, value, offset, littleEndian, 52, 8)
}
Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) {
_writeDouble(this, value, offset, true, noAssert)
}
Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) {
_writeDouble(this, value, offset, false, noAssert)
}
// fill(value, start=0, end=buffer.length)
Buffer.prototype.fill = function (value, start, end) {
if (!value) value = 0
if (!start) start = 0
if (!end) end = this.length
if (typeof value === 'string') {
value = value.charCodeAt(0)
}
assert(typeof value === 'number' && !isNaN(value), 'value is not a number')
assert(end >= start, 'end < start')
// Fill 0 bytes; we're done
if (end === start) return
if (this.length === 0) return
assert(start >= 0 && start < this.length, 'start out of bounds')
assert(end >= 0 && end <= this.length, 'end out of bounds')
for (var i = start; i < end; i++) {
this[i] = value
}
}
Buffer.prototype.inspect = function () {
var out = []
var len = this.length
for (var i = 0; i < len; i++) {
out[i] = toHex(this[i])
if (i === exports.INSPECT_MAX_BYTES) {
out[i + 1] = '...'
break
}
}
return '<Buffer ' + out.join(' ') + '>'
}
/**
* Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
* Added in Node 0.12. Only available in browsers that support ArrayBuffer.
*/
Buffer.prototype.toArrayBuffer = function () {
if (typeof Uint8Array !== 'undefined') {
if (Buffer._useTypedArrays) {
return (new Buffer(this)).buffer
} else {
var buf = new Uint8Array(this.length)
for (var i = 0, len = buf.length; i < len; i += 1)
buf[i] = this[i]
return buf.buffer
}
} else {
throw new Error('Buffer.toArrayBuffer not supported in this browser')
}
}
// HELPER FUNCTIONS
// ================
function stringtrim (str) {
if (str.trim) return str.trim()
return str.replace(/^\s+|\s+$/g, '')
}
var BP = Buffer.prototype
/**
* Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
*/
Buffer._augment = function (arr) {
arr._isBuffer = true
// save reference to original Uint8Array get/set methods before overwriting
arr._get = arr.get
arr._set = arr.set
// deprecated, will be removed in node 0.13+
arr.get = BP.get
arr.set = BP.set
arr.write = BP.write
arr.toString = BP.toString
arr.toLocaleString = BP.toString
arr.toJSON = BP.toJSON
arr.copy = BP.copy
arr.slice = BP.slice
arr.readUInt8 = BP.readUInt8
arr.readUInt16LE = BP.readUInt16LE
arr.readUInt16BE = BP.readUInt16BE
arr.readUInt32LE = BP.readUInt32LE
arr.readUInt32BE = BP.readUInt32BE
arr.readInt8 = BP.readInt8
arr.readInt16LE = BP.readInt16LE
arr.readInt16BE = BP.readInt16BE
arr.readInt32LE = BP.readInt32LE
arr.readInt32BE = BP.readInt32BE
arr.readFloatLE = BP.readFloatLE
arr.readFloatBE = BP.readFloatBE
arr.readDoubleLE = BP.readDoubleLE
arr.readDoubleBE = BP.readDoubleBE
arr.writeUInt8 = BP.writeUInt8
arr.writeUInt16LE = BP.writeUInt16LE
arr.writeUInt16BE = BP.writeUInt16BE
arr.writeUInt32LE = BP.writeUInt32LE
arr.writeUInt32BE = BP.writeUInt32BE
arr.writeInt8 = BP.writeInt8
arr.writeInt16LE = BP.writeInt16LE
arr.writeInt16BE = BP.writeInt16BE
arr.writeInt32LE = BP.writeInt32LE
arr.writeInt32BE = BP.writeInt32BE
arr.writeFloatLE = BP.writeFloatLE
arr.writeFloatBE = BP.writeFloatBE
arr.writeDoubleLE = BP.writeDoubleLE
arr.writeDoubleBE = BP.writeDoubleBE
arr.fill = BP.fill
arr.inspect = BP.inspect
arr.toArrayBuffer = BP.toArrayBuffer
return arr
}
// slice(start, end)
function clamp (index, len, defaultValue) {
if (typeof index !== 'number') return defaultValue
index = ~~index; // Coerce to integer.
if (index >= len) return len
if (index >= 0) return index
index += len
if (index >= 0) return index
return 0
}
function coerce (length) {
// Coerce length to a number (possibly NaN), round up
// in case it's fractional (e.g. 123.456) then do a
// double negate to coerce a NaN to 0. Easy, right?
length = ~~Math.ceil(+length)
return length < 0 ? 0 : length
}
function isArray (subject) {
return (Array.isArray || function (subject) {
return Object.prototype.toString.call(subject) === '[object Array]'
})(subject)
}
function isArrayish (subject) {
return isArray(subject) || Buffer.isBuffer(subject) ||
subject && typeof subject === 'object' &&
typeof subject.length === 'number'
}
function toHex (n) {
if (n < 16) return '0' + n.toString(16)
return n.toString(16)
}
function utf8ToBytes (str) {
var byteArray = []
for (var i = 0; i < str.length; i++) {
var b = str.charCodeAt(i)
if (b <= 0x7F)
byteArray.push(str.charCodeAt(i))
else {
var start = i
if (b >= 0xD800 && b <= 0xDFFF) i++
var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%')
for (var j = 0; j < h.length; j++)
byteArray.push(parseInt(h[j], 16))
}
}
return byteArray
}
function asciiToBytes (str) {
var byteArray = []
for (var i = 0; i < str.length; i++) {
// Node's code seems to be doing this and not & 0x7F..
byteArray.push(str.charCodeAt(i) & 0xFF)
}
return byteArray
}
function utf16leToBytes (str) {
var c, hi, lo
var byteArray = []
for (var i = 0; i < str.length; i++) {
c = str.charCodeAt(i)
hi = c >> 8
lo = c % 256
byteArray.push(lo)
byteArray.push(hi)
}
return byteArray
}
function base64ToBytes (str) {
return base64.toByteArray(str)
}
function blitBuffer (src, dst, offset, length) {
var pos
for (var i = 0; i < length; i++) {
if ((i + offset >= dst.length) || (i >= src.length))
break
dst[i + offset] = src[i]
}
return i
}
function decodeUtf8Char (str) {
try {
return decodeURIComponent(str)
} catch (err) {
return String.fromCharCode(0xFFFD) // UTF 8 invalid char
}
}
/*
* We have to make sure that the value is a valid integer. This means that it
* is non-negative. It has no fractional component and that it does not
* exceed the maximum allowed value.
*/
function verifuint (value, max) {
assert(typeof value === 'number', 'cannot write a non-number as a number')
assert(value >= 0, 'specified a negative value for writing an unsigned value')
assert(value <= max, 'value is larger than maximum value for type')
assert(Math.floor(value) === value, 'value has a fractional component')
}
function verifsint (value, max, min) {
assert(typeof value === 'number', 'cannot write a non-number as a number')
assert(value <= max, 'value larger than maximum allowed value')
assert(value >= min, 'value smaller than minimum allowed value')
assert(Math.floor(value) === value, 'value has a fractional component')
}
function verifIEEE754 (value, max, min) {
assert(typeof value === 'number', 'cannot write a non-number as a number')
assert(value <= max, 'value larger than maximum allowed value')
assert(value >= min, 'value smaller than minimum allowed value')
}
function assert (test, message) {
if (!test) throw new Error(message || 'Failed assertion')
}
},{"base64-js":2,"ieee754":3}],2:[function(require,module,exports){
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
;(function (exports) {
'use strict';
var Arr = (typeof Uint8Array !== 'undefined')
? Uint8Array
: Array
var ZERO = '0'.charCodeAt(0)
var PLUS = '+'.charCodeAt(0)
var SLASH = '/'.charCodeAt(0)
var NUMBER = '0'.charCodeAt(0)
var LOWER = 'a'.charCodeAt(0)
var UPPER = 'A'.charCodeAt(0)
function decode (elt) {
var code = elt.charCodeAt(0)
if (code === PLUS)
return 62 // '+'
if (code === SLASH)
return 63 // '/'
if (code < NUMBER)
return -1 //no match
if (code < NUMBER + 10)
return code - NUMBER + 26 + 26
if (code < UPPER + 26)
return code - UPPER
if (code < LOWER + 26)
return code - LOWER + 26
}
function b64ToByteArray (b64) {
var i, j, l, tmp, placeHolders, arr
if (b64.length % 4 > 0) {
throw new Error('Invalid string. Length must be a multiple of 4')
}
// the number of equal signs (place holders)
// if there are two placeholders, than the two characters before it
// represent one byte
// if there is only one, then the three characters before it represent 2 bytes
// this is just a cheap hack to not do indexOf twice
var len = b64.length
placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
// base64 is 4/3 + up to two characters of the original data
arr = new Arr(b64.length * 3 / 4 - placeHolders)
// if there are placeholders, only get up to the last complete 4 chars
l = placeHolders > 0 ? b64.length - 4 : b64.length
var L = 0
function push (v) {
arr[L++] = v
}
for (i = 0, j = 0; i < l; i += 4, j += 3) {
tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
push((tmp & 0xFF0000) >> 16)
push((tmp & 0xFF00) >> 8)
push(tmp & 0xFF)
}
if (placeHolders === 2) {
tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
push(tmp & 0xFF)
} else if (placeHolders === 1) {
tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
push((tmp >> 8) & 0xFF)
push(tmp & 0xFF)
}
return arr
}
function uint8ToBase64 (uint8) {
var i,
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
output = "",
temp, length
function encode (num) {
return lookup.charAt(num)
}
function tripletToBase64 (num) {
return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
}
// go through the array every three bytes, we'll deal with trailing stuff later
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
output += tripletToBase64(temp)
}
// pad the end with zeros, but make sure to not forget the extra bytes
switch (extraBytes) {
case 1:
temp = uint8[uint8.length - 1]
output += encode(temp >> 2)
output += encode((temp << 4) & 0x3F)
output += '=='
break
case 2:
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
output += encode(temp >> 10)
output += encode((temp >> 4) & 0x3F)
output += encode((temp << 2) & 0x3F)
output += '='
break
}
return output
}
module.exports.toByteArray = b64ToByteArray
module.exports.fromByteArray = uint8ToBase64
}())
},{}],3:[function(require,module,exports){
exports.read = function(buffer, offset, isLE, mLen, nBytes) {
var e, m,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
nBits = -7,
i = isLE ? (nBytes - 1) : 0,
d = isLE ? -1 : 1,
s = buffer[offset + i];
i += d;
e = s & ((1 << (-nBits)) - 1);
s >>= (-nBits);
nBits += eLen;
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
m = e & ((1 << (-nBits)) - 1);
e >>= (-nBits);
nBits += mLen;
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
if (e === 0) {
e = 1 - eBias;
} else if (e === eMax) {
return m ? NaN : ((s ? -1 : 1) * Infinity);
} else {
m = m + Math.pow(2, mLen);
e = e - eBias;
}
return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
};
exports.write = function(buffer, value, offset, isLE, mLen, nBytes) {
var e, m, c,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
i = isLE ? 0 : (nBytes - 1),
d = isLE ? 1 : -1,
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
value = Math.abs(value);
if (isNaN(value) || value === Infinity) {
m = isNaN(value) ? 1 : 0;
e = eMax;
} else {
e = Math.floor(Math.log(value) / Math.LN2);
if (value * (c = Math.pow(2, -e)) < 1) {
e--;
c *= 2;
}
if (e + eBias >= 1) {
value += rt / c;
} else {
value += rt * Math.pow(2, 1 - eBias);
}
if (value * c >= 2) {
e++;
c /= 2;
}
if (e + eBias >= eMax) {
m = 0;
e = eMax;
} else if (e + eBias >= 1) {
m = (value * c - 1) * Math.pow(2, mLen);
e = e + eBias;
} else {
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
e = 0;
}
}
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
e = (e << mLen) | m;
eLen += mLen;
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
buffer[offset + i - d] |= s * 128;
};
},{}],4:[function(require,module,exports){
var Buffer = require('buffer').Buffer;
var intSize = 4;
var zeroBuffer = new Buffer(intSize); zeroBuffer.fill(0);
var chrsz = 8;
function toArray(buf, bigEndian) {
if ((buf.length % intSize) !== 0) {
var len = buf.length + (intSize - (buf.length % intSize));
buf = Buffer.concat([buf, zeroBuffer], len);
}
var arr = [];
var fn = bigEndian ? buf.readInt32BE : buf.readInt32LE;
for (var i = 0; i < buf.length; i += intSize) {
arr.push(fn.call(buf, i));
}
return arr;
}
function toBuffer(arr, size, bigEndian) {
var buf = new Buffer(size);
var fn = bigEndian ? buf.writeInt32BE : buf.writeInt32LE;
for (var i = 0; i < arr.length; i++) {
fn.call(buf, arr[i], i * 4, true);
}
return buf;
}
function hash(buf, fn, hashSize, bigEndian) {
if (!Buffer.isBuffer(buf)) buf = new Buffer(buf);
var arr = fn(toArray(buf, bigEndian), buf.length * chrsz);
return toBuffer(arr, hashSize, bigEndian);
}
module.exports = { hash: hash };
},{"buffer":1}],5:[function(require,module,exports){
var Buffer = require('buffer').Buffer
var sha = require('./sha')
var sha256 = require('./sha256')
var rng = require('./rng')
var md5 = require('./md5')
var algorithms = {
sha1: sha,
sha256: sha256,
md5: md5
}
var blocksize = 64
var zeroBuffer = new Buffer(blocksize); zeroBuffer.fill(0)
function hmac(fn, key, data) {
if(!Buffer.isBuffer(key)) key = new Buffer(key)
if(!Buffer.isBuffer(data)) data = new Buffer(data)
if(key.length > blocksize) {
key = fn(key)
} else if(key.length < blocksize) {
key = Buffer.concat([key, zeroBuffer], blocksize)
}
var ipad = new Buffer(blocksize), opad = new Buffer(blocksize)
for(var i = 0; i < blocksize; i++) {
ipad[i] = key[i] ^ 0x36
opad[i] = key[i] ^ 0x5C
}
var hash = fn(Buffer.concat([ipad, data]))
return fn(Buffer.concat([opad, hash]))
}
function hash(alg, key) {
alg = alg || 'sha1'
var fn = algorithms[alg]
var bufs = []
var length = 0
if(!fn) error('algorithm:', alg, 'is not yet supported')
return {
update: function (data) {
if(!Buffer.isBuffer(data)) data = new Buffer(data)
bufs.push(data)
length += data.length
return this
},
digest: function (enc) {
var buf = Buffer.concat(bufs)
var r = key ? hmac(fn, key, buf) : fn(buf)
bufs = null
return enc ? r.toString(enc) : r
}
}
}
function error () {
var m = [].slice.call(arguments).join(' ')
throw new Error([
m,
'we accept pull requests',
'http://github.com/dominictarr/crypto-browserify'
].join('\n'))
}
exports.createHash = function (alg) { return hash(alg) }
exports.createHmac = function (alg, key) { return hash(alg, key) }
exports.randomBytes = function(size, callback) {
if (callback && callback.call) {
try {
callback.call(this, undefined, new Buffer(rng(size)))
} catch (err) { callback(err) }
} else {
return new Buffer(rng(size))
}
}
function each(a, f) {
for(var i in a)
f(a[i], i)
}
// the least I can do is make error messages for the rest of the node.js/crypto api.
each(['createCredentials'
, 'createCipher'
, 'createCipheriv'
, 'createDecipher'
, 'createDecipheriv'
, 'createSign'
, 'createVerify'
, 'createDiffieHellman'
, 'pbkdf2'], function (name) {
exports[name] = function () {
error('sorry,', name, 'is not implemented yet')
}
})
},{"./md5":6,"./rng":7,"./sha":8,"./sha256":9,"buffer":1}],6:[function(require,module,exports){
/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*/
var helpers = require('./helpers');
/*
* Perform a simple self-test to see if the VM is working
*/
function md5_vm_test()
{
return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
}
/*
* Calculate the MD5 of an array of little-endian words, and a bit length
*/
function core_md5(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return Array(a, b, c, d);
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
function md5_cmn(q, a, b, x, s, t)
{
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function bit_rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
module.exports = function md5(buf) {
return helpers.hash(buf, core_md5, 16);
};
},{"./helpers":4}],7:[function(require,module,exports){
// Original code adapted from Robert Kieffer.
// details at https://github.com/broofa/node-uuid
(function() {
var _global = this;
var mathRNG, whatwgRNG;
// NOTE: Math.random() does not guarantee "cryptographic quality"
mathRNG = function(size) {
var bytes = new Array(size);
var r;
for (var i = 0, r; i < size; i++) {
if ((i & 0x03) == 0) r = Math.random() * 0x100000000;
bytes[i] = r >>> ((i & 0x03) << 3) & 0xff;
}
return bytes;
}
if (_global.crypto && crypto.getRandomValues) {
whatwgRNG = function(size) {
var bytes = new Uint8Array(size);
crypto.getRandomValues(bytes);
return bytes;
}
}
module.exports = whatwgRNG || mathRNG;
}())
},{}],8:[function(require,module,exports){
/*
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for details.
*/
var helpers = require('./helpers');
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_sha1(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w = Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for(var j = 0; j < 80; j++)
{
if(j < 16) w[j] = x[i + j];
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d)
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t)
{
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
module.exports = function sha1(buf) {
return helpers.hash(buf, core_sha1, 20, true);
};
},{"./helpers":4}],9:[function(require,module,exports){
/**
* A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
* in FIPS 180-2
* Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
*
*/
var helpers = require('./helpers');
var safe_add = function(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
};
var S = function(X, n) {
return (X >>> n) | (X << (32 - n));
};
var R = function(X, n) {
return (X >>> n);
};
var Ch = function(x, y, z) {
return ((x & y) ^ ((~x) & z));
};
var Maj = function(x, y, z) {
return ((x & y) ^ (x & z) ^ (y & z));
};
var Sigma0256 = function(x) {
return (S(x, 2) ^ S(x, 13) ^ S(x, 22));
};
var Sigma1256 = function(x) {
return (S(x, 6) ^ S(x, 11) ^ S(x, 25));
};
var Gamma0256 = function(x) {
return (S(x, 7) ^ S(x, 18) ^ R(x, 3));
};
var Gamma1256 = function(x) {
return (S(x, 17) ^ S(x, 19) ^ R(x, 10));
};
var core_sha256 = function(m, l) {
var K = new Array(0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85,0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2);
var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
var W = new Array(64);
var a, b, c, d, e, f, g, h, i, j;
var T1, T2;
/* append padding */
m[l >> 5] |= 0x80 << (24 - l % 32);
m[((l + 64 >> 9) << 4) + 15] = l;
for (var i = 0; i < m.length; i += 16) {
a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3]; e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7];
for (var j = 0; j < 64; j++) {
if (j < 16) {
W[j] = m[j + i];
} else {
W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
}
T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
T2 = safe_add(Sigma0256(a), Maj(a, b, c));
h = g; g = f; f = e; e = safe_add(d, T1); d = c; c = b; b = a; a = safe_add(T1, T2);
}
HASH[0] = safe_add(a, HASH[0]); HASH[1] = safe_add(b, HASH[1]); HASH[2] = safe_add(c, HASH[2]); HASH[3] = safe_add(d, HASH[3]);
HASH[4] = safe_add(e, HASH[4]); HASH[5] = safe_add(f, HASH[5]); HASH[6] = safe_add(g, HASH[6]); HASH[7] = safe_add(h, HASH[7]);
}
return HASH;
};
module.exports = function sha256(buf) {
return helpers.hash(buf, core_sha256, 32, true);
};
},{"./helpers":4}],10:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
process.nextTick = (function () {
var canSetImmediate = typeof window !== 'undefined'
&& window.setImmediate;
var canPost = typeof window !== 'undefined'
&& window.postMessage && window.addEventListener
;
if (canSetImmediate) {
return function (f) { return window.setImmediate(f) };
}
if (canPost) {
var queue = [];
window.addEventListener('message', function (ev) {
var source = ev.source;
if ((source === window || source === null) && ev.data === 'process-tick') {
ev.stopPropagation();
if (queue.length > 0) {
var fn = queue.shift();
fn();
}
}
}, true);
return function nextTick(fn) {
queue.push(fn);
window.postMessage('process-tick', '*');
};
}
return function nextTick(fn) {
setTimeout(fn, 0);
};
})();
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.binding = function (name) {
throw new Error('process.binding is not supported');
}
// TODO(shtylman)
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
},{}],11:[function(require,module,exports){
var self
var ndn = require("ndn-lib");
var ElementReader = ndn.ElementReader;
var ndnbuf = ndn.customBuffer;
var Name = ndn.Name
var Data = ndn.Data
var telehash = {}
telehash.transport = function (hashname, channel) {
this.hashname = hashname
var faceSelf = this
if (channel) {
this.channel = channel
}
};
telehash.start = function(appname, listenCallback) {
function assigner (selfie){
self = selfie
listenCallback(self)
}
require("./lib/node/init.js")(appname, assigner, "testbspassword")
}
/**
* Connect to the host and port in face. This replaces a previous connection and sets connectedHost
* and connectedPort. Once connected, call onopenCallback().
* Listen on the port to read an entire binary XML encoded element and call
* face.onReceivedElement(element).
*/
telehash.transport.prototype.connect = function(face, onopenCallback)
{
this.elementReader = new ElementReader(face);
var faceSelf= this;
face.transport = this
//console.log("call to connec!!!!!!!!!!!!!!!!!!!!!!")
function listener (end, packet, chan, cb) {
//console.log("got packet!", chan, packet)
if (packet.js == "ndn"){
var ev = packet.body
console.log('RecvHandle called on telehash face', ev, typeof ev);
try {
// Find the end of the binary XML element and call face.onReceivedElement.
faceSelf.elementReader.onReceivedData(ev);
} catch (ex) {
console.log("NDN.ws.onmessage exception: " + ex);
return;
}
// garbage collect arraybuffer
//var ms = new MessageChannel()
}
cb(true)
}
if (!face.transport.channel || face.transport.channel.ended){
//console.log("channel not defined, begin listening")
self.start(face.transport.hashname, "ndn", {js:"incoming"}, function(err, packet, chan, callb){
//console.log("defined channel", chan, packet)
listener(err, packet, chan, callb)
chan.callback = listener
face.transport.channel = chan
face.transport.channel.callback = listener
callb(true)
onopenCallback()
})
} else {
face.transport.channel.callback = listener
//console.log("channel defined, callingback", face.transport.channel.callback)
onopenCallback()
}
};
/**
* Send the Uint8Array data.
*/
telehash.transport.prototype.send = function(data)
{
console.log(!this.channel, !this.channel.ended)
if ((!this.channel == false) && !this.channel.ended) {
this.channel.send({js:"ndn", body: data})
}
else
console.log('telehash connection is not established.');
};
module.exports = telehash;
},{"./lib/node/init.js":13,"ndn-lib":23}],12:[function(require,module,exports){
(function (process){
(function(){var e,t,n;(function(r){function d(e,t){return h.call(e,t)}function v(e,t){var n,r,i,s,o,u,a,f,c,h,p,v=t&&t.split("/"),m=l.map,g=/\.js$/,y=m&&m["*"]||{};if(e&&e.charAt(0)===".")if(t){v=v.slice(0,v.length-1),e=e.split("/"),o=e.length-1,l.pkgs&&d(l.pkgs,v[0])&&g.test(e[o])&&(e[o]=e[o].replace(g,"")),e=v.concat(e);for(c=0;c<e.length;c+=1){p=e[c];if(p===".")e.splice(c,1),c-=1;else if(p===".."){if(c===1&&(e[2]===".."||e[0]===".."))break;c>0&&(e.splice(c-1,2),c-=2)}}e=e.join("/")}else e.indexOf("./")===0&&(e=e.substring(2));if((v||y)&&m){n=e.split("/");for(c=n.length;c>0;c-=1){r=n.slice(0,c).join("/");if(v)for(h=v.length;h>0;h-=1){i=m[v.slice(0,h).join("/")];if(i){i=i[r];if(i){s=i,u=c;break}}}if(s)break;!a&&y&&y[r]&&(a=y[r],f=c)}!s&&a&&(s=a,u=f),s&&(n.splice(0,u,s),e=n.join("/"))}return e}function m(e,t){return function(){return s.apply(r,p.call(arguments,0).concat([e,t]))}}function g(e){return function(t){return v(t,e)}}function y(e){return function(t){a[e]=t}}function b(e){if(d(f,e)){var t=f[e];delete f[e],c[e]=!0,i.apply(r,t)}if(!d(a,e)&&!d(c,e))throw new Error("No "+e);return a[e]}function w(e){var t,n=e?e.indexOf("!"):-1;return n>-1&&(t=e.substring(0,n),e=e.substring(n+1,e.length)),[t,e]}function E(e){return function(){return l&&l.config&&l.config[e]||{}}}var i,s,o,u,a={},f={},l={},c={},h=Object.prototype.hasOwnProperty,p=[].slice;o=function(e,t){var n,r=w(e),i=r[0];return e=r[1],i&&(i=v(i,t),n=b(i)),i?n&&n.normalize?e=n.normalize(e,g(t)):e=v(e,t):(e=v(e,t),r=w(e),i=r[0],e=r[1],i&&(n=b(i))),{f:i?i+"!"+e:e,n:e,pr:i,p:n}},u={require:function(e){return m(e)},exports:function(e){var t=a[e];return typeof t!="undefined"?t:a[e]={}},module:function(e){return{id:e,uri:"",exports:a[e],config:E(e)}}},i=function(e,t,n,i){var s,l,h,p,v,g=[],w=typeof n,E;i=i||e;if(w==="undefined"||w==="function"){t=!t.length&&n.length?["require","exports","module"]:t;for(v=0;v<t.length;v+=1){p=o(t[v],i),l=p.f;if(l==="require")g[v]=u.require(e);else if(l==="exports")g[v]=u.exports(e),E=!0;else if(l==="module")s=g[v]=u.module(e);else if(d(a,l)||d(f,l)||d(c,l))g[v]=b(l);else{if(!p.p)throw new Error(e+" missing "+l);p.p.load(p.n,m(i,!0),y(l),{}),g[v]=a[l]}}h=n?n.apply(a[e],g):undefined;if(e)if(s&&s.exports!==r&&s.exports!==a[e])a[e]=s.exports;else if(h!==r||!E)a[e]=h}else e&&(a[e]=n)},e=t=s=function(e,t,n,a,f){var c,h;if(typeof e=="string")return u[e]?u[e](t):b(o(e,t).f);if(!e.splice){l=e,l.deps&&s(l.deps,l.callback),h=l.packages;if(l.packages){l.pkgs={};for(c=0;c<h.length;c++)l.pkgs[h[c].name||h[c]]=!0}if(!t)return;t.splice?(e=t,t=n,n=null):e=r}return t=t||function(){},typeof n=="function"&&(n=a,a=f),a?i(r,e,t,n):setTimeout(function(){i(r,e,t,n)},4),s},s.config=function(e){return s(e)},e._defined=a,n=function(e,t,n){t.splice||(n=t,t=[]),!d(a,e)&&!d(f,e)&&(f[e]=[e,t,n])},n.amd={jQuery:!0}})(),n("node_modules/almond/almond",function(){}),function(){function e(e){var t=e.util=e.util||{};typeof process=="undefined"||!process.nextTick?typeof setImmediate=="function"?(t.setImmediate=setImmediate,t.nextTick=function(e){return setImmediate(e)}):(t.setImmediate=function(e){setTimeout(e,0)},t.nextTick=t.setImmediate):(t.nextTick=process.nextTick,typeof setImmediate=="function"?t.setImmediate=setImmediate:t.setImmediate=t.nextTick),t.isArray=Array.isArray||function(e){return Object.prototype.toString.call(e)==="[object Array]"},t.isArrayBuffer=function(e){return typeof ArrayBuffer!="undefined"&&e instanceof ArrayBuffer};var n=[];typeof Int8Array!="undefined"&&n.push(Int8Array),typeof Uint8Array!="undefined"&&n.push(Uint8Array),typeof Uint8ClampedArray!="undefined"&&n.push(Uint8ClampedArray),typeof Int16Array!="undefined"&&n.push(Int16Array),typeof Uint16Array!="undefined"&&n.push(Uint16Array),typeof Int32Array!="undefined"&&n.push(Int32Array),typeof Uint32Array!="undefined"&&n.push(Uint32Array),typeof Float32Array!="undefined"&&n.push(Float32Array),typeof Float64Array!="undefined"&&n.push(Float64Array),t.isArrayBufferView=function(e){for(var t=0;t<n.length;++t)if(e instanceof n[t])return!0;return!1},t.ByteBuffer=function(e){this.data="",this.read=0;if(typeof e=="string")this.data=e;else if(t.isArrayBuffer(e)||t.isArrayBufferView(e)){var n=new Uint8Array(e);try{this.data=String.fromCharCode.apply(null,n)}catch(r){for(var i=0;i<n.length;++i)this.putByte(n[i])}}},t.ByteBuffer.prototype.length=function(){return this.data.length-this.read},t.ByteBuffer.prototype.isEmpty=function(){return this.length()<=0},t.ByteBuffer.prototype.putByte=function(e){return this.data+=String.fromCharCode(e),this},t.ByteBuffer.prototype.fillWithByte=function(e,t){e=String.fromCharCode(e);var n=this.data;while(t>0)t&1&&(n+=e),t>>>=1,t>0&&(e+=e);return this.data=n,this},t.ByteBuffer.prototype.putBytes=function(e){return this.data+=e,this},t.ByteBuffer.prototype.putString=function(e){return this.data+=t.encodeUtf8(e),this},t.ByteBuffer.prototype.putInt16=function(e){return this.data+=String.fromCharCode(e>>8&255)+String.fromCharCode(e&255),this},t.ByteBuffer.prototype.putInt24=function(e){return this.data+=String.fromCharCode(e>>16&255)+String.fromCharCode(e>>8&255)+String.fromCharCode(e&255),this},t.ByteBuffer.prototype.putInt32=function(e){return this.data+=String.fromCharCode(e>>24&255)+String.fromCharCode(e>>16&255)+String.fromCharCode(e>>8&255)+String.fromCharCode(e&255),this},t.ByteBuffer.prototype.putInt16Le=function(e){return this.data+=String.fromCharCode(e&255)+String.fromCharCode(e>>8&255),this},t.ByteBuffer.prototype.putInt24Le=function(e){return this.data+=String.fromCharCode(e&255)+String.fromCharCode(e>>8&255)+String.fromCharCode(e>>16&255),this},t.ByteBuffer.prototype.putInt32Le=function(e){return this.data+=String.fromCharCode(e&255)+String.fromCharCode(e>>8&255)+String.fromCharCode(e>>16&255)+String.fromCharCode(e>>24&255),this},t.ByteBuffer.prototype.putInt=function(e,t){do t-=8,this.data+=String.fromCharCode(e>>t&255);while(t>0);return this},t.ByteBuffer.prototype.putSignedInt=function(e,t){return e<0&&(e+=2<<t-1),this.putInt(e,t)},t.ByteBuffer.prototype.putBuffer=function(e){return this.data+=e.getBytes(),this},t.ByteBuffer.prototype.getByte=function(){return this.data.charCodeAt(this.read++)},t.ByteBuffer.prototype.getInt16=function(){var e=this.data.charCodeAt(this.read)<<8^this.data.charCodeAt(this.read+1);return this.read+=2,e},t.ByteBuffer.prototype.getInt24=function(){var e=this.data.charCodeAt(this.read)<<16^this.data.charCodeAt(this.read+1)<<8^this.data.charCodeAt(this.read+2);return this.read+=3,e},t.ByteBuffer.prototype.getInt32=function(){var e=this.data.charCodeAt(this.read)<<24^this.data.charCodeAt(this.read+1)<<16^this.data.charCodeAt(this.read+2)<<8^this.data.charCodeAt(this.read+3);return this.read+=4,e},t.ByteBuffer.prototype.getInt16Le=function(){var e=this.data.charCodeAt(this.read)^this.data.charCodeAt(this.read+1)<<8;return this.read+=2,e},t.ByteBuffer.prototype.getInt24Le=function(){var e=this.data.charCodeAt(this.read)^this.data.charCodeAt(this.read+1)<<8^this.data.charCodeAt(this.read+2)<<16;return this.read+=3,e},t.ByteBuffer.prototype.getInt32Le=function(){var e=this.data.charCodeAt(this.read)^this.data.charCodeAt(this.read+1)<<8^this.data.charCodeAt(this.read+2)<<16^this.data.charCodeAt(this.read+3)<<24;return this.read+=4,e},t.ByteBuffer.prototype.getInt=function(e){var t=0;do t=(t<<8)+this.data.charCodeAt(this.read++),e-=8;while(e>0);return t},t.ByteBuffer.prototype.getSignedInt=function(e){var t=this.getInt(e),n=2<<e-2;return t>=n&&(t-=n<<1),t},t.ByteBuffer.prototype.getBytes=function(e){var t;return e?(e=Math.min(this.length(),e),t=this.data.slice(this.read,this.read+e),this.read+=e):e===0?t="":(t=this.read===0?this.data:this.data.slice(this.read),this.clear()),t},t.ByteBuffer.prototype.bytes=function(e){return typeof e=="undefined"?this.data.slice(this.read):this.data.slice(this.read,this.read+e)},t.ByteBuffer.prototype.at=function(e){return this.data.charCodeAt(this.read+e)},t.ByteBuffer.prototype.setAt=function(e,t){return this.data=this.data.substr(0,this.read+e)+String.fromCharCode(t)+this.data.substr(this.read+e+1),this},t.ByteBuffer.prototype.last=function(){return this.data.charCodeAt(this.data.length-1)},t.ByteBuffer.prototype.copy=function(){var e=t.createBuffer(this.data);return e.read=this.read,e},t.ByteBuffer.prototype.compact=function(){return this.read>0&&(this.data=this.data.slice(this.read),this.read=0),this},t.ByteBuffer.prototype.clear=function(){return this.data="",this.read=0,this},t.ByteBuffer.prototype.truncate=function(e){var t=Math.max(0,this.length()-e);return this.data=this.data.substr(this.read,t),this.read=0,this},t.ByteBuffer.prototype.toHex=function(){var e="";for(var t=this.read;t<this.data.length;++t){var n=this.data.charCodeAt(t);n<16&&(e+="0"),e+=n.toString(16)}return e},t.ByteBuffer.prototype.toString=function(){return t.decodeUtf8(this.bytes())},t.createBuffer=function(e,n){return n=n||"raw",e!==undefined&&n==="utf8"&&(e=t.encodeUtf8(e)),new t.ByteBuffer(e)},t.fillString=function(e,t){var n="";while(t>0)t&1&&(n+=e),t>>>=1,t>0&&(e+=e);return n},t.xorBytes=function(e,t,n){var r="",i="",s="",o=0,u=0;for(;n>0;--n,++o)i=e.charCodeAt(o)^t.charCodeAt(o),u>=10&&(r+=s,s="",u=0),s+=String.fromCharCode(i),++u;return r+=s,r},t.hexToBytes=function(e){var t="",n=0;e.length&!0&&(n=1,t+=String.fromCharCode(parseInt(e[0],16)));for(;n<e.length;n+=2)t+=String.fromCharCode(parseInt(e.substr(n,2),16));return t},t.bytesToHex=function(e){return t.createBuffer(e).toHex()},t.int32ToBytes=function(e){return String.fromCharCode(e>>24&255)+String.fromCharCode(e>>16&255)+String.fromCharCode(e>>8&255)+String.fromCharCode(e&255)};var r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",i=[62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,64,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51];t.encode64=function(e,t){var n="",i="",s,o,u,a=0;while(a<e.length)s=e.charCodeAt(a++),o=e.charCodeAt(a++),u=e.charCodeAt(a++),n+=r.charAt(s>>2),n+=r.charAt((s&3)<<4|o>>4),isNaN(o)?n+="==":(n+=r.charAt((o&15)<<2|u>>6),n+=isNaN(u)?"=":r.charAt(u&63)),t&&n.length>t&&(i+=n.substr(0,t)+"\r\n",n=n.substr(t));return i+=n,i},t.decode64=function(e){e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");var t="",n,r,s,o,u=0;while(u<e.length)n=i[e.charCodeAt(u++)-43],r=i[e.charCodeAt(u++)-43],s=i[e.charCodeAt(u++)-43],o=i[e.charCodeAt(u++)-43],t+=String.fromCharCode(n<<2|r>>4),s!==64&&(t+=String.fromCharCode((r&15)<<4|s>>2),o!==64&&(t+=String.fromCharCode((s&3)<<6|o)));return t},t.encodeUtf8=function(e){return unescape(encodeURIComponent(e))},t.decodeUtf8=function(e){return decodeURIComponent(escape(e))},t.deflate=function(e,n,r){n=t.decode64(e.deflate(t.encode64(n)).rval);if(r){var i=2,s=n.charCodeAt(1);s&32&&(i=6),n=n.substring(i,n.length-4)}return n},t.inflate=function(e,n,r){var i=e.inflate(t.encode64(n)).rval;return i===null?null:t.decode64(i)};var s=function(e,n,r){if(!e)throw{message:"WebStorage not available."};var i;r===null?i=e.removeItem(n):(r=t.encode64(JSON.stringify(r)),i=e.setItem(n,r));if(typeof i!="undefined"&&i.rval!==!0)throw i.error},o=function(e,n){if(!e)throw{message:"WebStorage not available."};var r=e.getItem(n);if(e.init)if(r.rval===null){if(r.error)throw r.error;r=null}else r=r.rval;return r!==null&&(r=JSON.parse(t.decode64(r))),r},u=function(e,t,n,r){var i=o(e,t);i===null&&(i={}),i[n]=r,s(e,t,i)},a=function(e,t,n){var r=o(e,t);return r!==null&&(r=n in r?r[n]:null),r},f=function(e,t,n){var r=o(e,t);if(r!==null&&n in r){delete r[n];var i=!0;for(var u in r){i=!1;break}i&&(r=null),s(e,t,r)}},l=function(e,t){s(e,t,null)},c=function(e,t,n){var r=null;typeof n=="undefined"&&(n=["web","flash"]);var i,s=!1,o=null;for(var u in n){i=n[u];try{if(i==="flash"||i==="both"){if(t[0]===null)throw{message:"Flash local storage not available."};r=e.apply(this,t),s=i==="flash"}if(i==="web"||i==="both")t[0]=localStorage,r=e.apply(this,t),s=!0}catch(a){o=a}if(s)break}if(!s)throw o;return r};t.setItem=function(e,t,n,r,i){c(u,arguments,i)},t.getItem=function(e,t,n,r){return c(a,arguments,r)},t.removeItem=function(e,t,n,r){c(f,arguments,r)},t.clearItems=function(e,t,n){c(l,arguments,n)},t.parseUrl=function(e){var t=/^(https?):\/\/([^:&^\/]*):?(\d*)(.*)$/g;t.lastIndex=0;var n=t.exec(e),r=n===null?null:{full:e,scheme:n[1],host:n[2],port:n[3],path:n[4]};return r&&(r.fullHost=r.host,r.port?r.port!==80&&r.scheme==="http"?r.fullHost+=":"+r.port:r.port!==443&&r.scheme==="https"&&(r.fullHost+=":"+r.port):r.scheme==="http"?r.port=80:r.scheme==="https"&&(r.port=443),r.full=r.scheme+"://"+r.fullHost),r};var h=null;t.getQueryVariables=function(e){var t=function(e){var t={},n=e.split("&");for(var r=0;r<n.length;r++){var i=n[r].indexOf("="),s,o;i>0?(s=n[r].substring(0,i),o=n[r].substring(i+1)):(s=n[r],o=null),s in t||(t[s]=[]),!(s in Object.prototype)&&o!==null&&t[s].push(unescape(o))}return t},n;return typeof e=="undefined"?(h===null&&(typeof window=="undefined"?h={}:h=t(window.location.search.substring(1))),n=h):n=t(e),n},t.parseFragment=function(e){var n=e,r="",i=e.indexOf("?");i>0&&(n=e.substring(0,i),r=e.substring(i+1));var s=n.split("/");s.length>0&&s[0]===""&&s.shift();var o=r===""?{}:t.getQueryVariables(r);return{pathString:n,queryString:r,path:s,query:o}},t.makeRequest=function(e){var n=t.parseFragment(e),r={path:n.pathString,query:n.queryString,getPath:function(e){return typeof e=="undefined"?n.path:n.path[e]},getQuery:function(e,t){var r;return typeof e=="undefined"?r=n.query:(r=n.query[e],r&&typeof t!="undefined"&&(r=r[t])),r},getQueryLast:function(e,t){var n,i=r.getQuery(e);return i?n=i[i.length-1]:n=t,n}};return r},t.makeLink=function(e,t,n){e=jQuery.isArray(e)?e.join("/"):e;var r=jQuery.param(t||{});return n=n||"",e+(r.length>0?"?"+r:"")+(n.length>0?"#"+n:"")},t.setPath=function(e,t,n){if(typeof e=="object"&&e!==null){var r=0,i=t.length;while(r<i){var s=t[r++];if(r==i)e[s]=n;else{var o=s in e;if(!o||o&&typeof e[s]!="object"||o&&e[s]===null)e[s]={};e=e[s]}}}},t.getPath=function(e,t,n){var r=0,i=t.length,s=!0;while(s&&r<i&&typeof e=="object"&&e!==null){var o=t[r++];s=o in e,s&&(e=e[o])}return s?e:n},t.deletePath=function(e,t){if(typeof e=="object"&&e!==null){var n=0,r=t.length;while(n<r){var i=t[n++];if(n==r)delete e[i];else{if(!(i in e&&typeof e[i]=="object"&&e[i]!==null))break;e=e[i]}}}},t.isEmpty=function(e){for(var t in e)if(e.hasOwnProperty(t))return!1;return!0},t.format=function(e){var t=/%./g,n,r,i=0,s=[],o=0;while(n=t.exec(e)){r=e.substring(o,t.lastIndex-2),r.length>0&&s.push(r),o=t.lastIndex;var u=n[0][1];switch(u){case"s":case"o":i<arguments.length?s.push(arguments[i++ +1]):s.push("<?>");break;case"%":s.push("%");break;default:s.push("<%"+u+"?>")}}return s.push(e.substring(o)),s.join("")},t.formatNumber=function(e,t,n,r){var i=e,s=isNaN(t=Math.abs(t))?2:t,o=n===undefined?",":n,u=r===undefined?".":r,a=i<0?"-":"",f=parseInt(i=Math.abs(+i||0).toFixed(s),10)+"",l=f.length>3?f.length%3:0;return a+(l?f.substr(0,l)+u:"")+f.substr(l).replace(/(\d{3})(?=\d)/g,"$1"+u)+(s?o+Math.abs(i-f).toFixed(s).slice(2):"")},t.formatSize=function(e){return e>=1073741824?e=t.formatNumber(e/1073741824,2,".","")+" GiB":e>=1048576?e=t.formatNumber(e/1048576,2,".","")+" MiB":e>=1024?e=t.formatNumber(e/1024,0)+" KiB":e=t.formatNumber(e,0)+" bytes",e},t.bytesFromIP=function(e){return e.indexOf(".")!==-1?t.bytesFromIPv4(e):e.indexOf(":")!==-1?t.bytesFromIPv6(e):null},t.bytesFromIPv4=function(e){e=e.split(".");if(e.length!==4)return null;var n=t.createBuffer();for(var r=0;r<e.length;++r){var i=parseInt(e[r],10);if(isNaN(i))return null;n.putByte(i)}return n.getBytes()},t.bytesFromIPv6=function(e){var n=0;e=e.split(":").filter(function(e){return e.length===0&&++n,!0});var r=(8-e.length+n)*2,i=t.createBuffer();for(var s=0;s<8;++s){if(!e[s]||e[s].length===0){i.fillWithByte(0,r),r=0;continue}var o=t.hexToBytes(e[s]);o.length<2&&i.putByte(0),i.putBytes(o)}return i.getBytes()},t.bytesToIP=function(e){return e.length===4?t.bytesToIPv4(e):e.length===16?t.bytesToIPv6(e):null},t.bytesToIPv4=function(e){if(e.length!==4)return null;var t=[];for(var n=0;n<e.length;++n)t.push(e.charCodeAt(n));return t.join(".")},t.bytesToIPv6=function(e){if(e.length!==16)return null;var n=[],r=[],i=0;for(var s=0;s<e.length;s+=2){var o=t.bytesToHex(e[s]+e[s+1]);while(o[0]==="0"&&o!=="0")o=o.substr(1);if(o==="0"){var u=r[r.length-1],a=n.length;!u||a!==u.end+1?r.push({start:a,end:a}):(u.end=a,u.end-u.start>r[i].end-r[i].start&&(i=r.length-1))}n.push(o)}if(r.length>0){var f=r[i];f.end-f.start>0&&(n.splice(f.start,f.end-f.start+1,""),f.start===0&&n.unshift(""),f.end===7&&n.push(""))}return n.join(":")}}var r="util";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/util",["require","module"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){var t=!1,n=4,r,i,s,o,u,a=function(){t=!0,s=[0,1,2,4,8,16,32,64,128,27,54];var e=new Array(256);for(var n=0;n<128;++n)e[n]=n<<1,e[n+128]=n+128<<1^283;r=new Array(256),i=new Array(256),o=new Array(4),u=new Array(4);for(var n=0;n<4;++n)o[n]=new Array(256),u[n]=new Array(256);var a=0,f=0,l,c,h,p,d,v,m;for(var n=0;n<256;++n){p=f^f<<1^f<<2^f<<3^f<<4,p=p>>8^p&255^99,r[a]=p,i[p]=a,d=e[p],l=e[a],c=e[l],h=e[c],v=d<<24^p<<16^p<<8^(p^d),m=(l^c^h)<<24^(a^h)<<16^(a^c^h)<<8^(a^l^h);for(var g=0;g<4;++g)o[g][a]=v,u[g][p]=m,v=v<<24|v>>>8,m=m<<24|m>>>8;a===0?a=f=1:(a=l^e[e[e[l^h]]],f^=e[e[f]])}},f=function(e,t){var i=e.slice(0),o,a=1,f=i.length,l=f+6+1,c=n*l;for(var h=f;h<c;++h)o=i[h-1],h%f===0?(o=r[o>>>16&255]<<24^r[o>>>8&255]<<16^r[o&255]<<8^r[o>>>24]^s[a]<<24,a++):f>6&&h%f===4&&(o=r[o>>>24]<<24^r[o>>>16&255]<<16^r[o>>>8&255]<<8^r[o&255]),i[h]=i[h-f]^o;if(t){var p,d=u[0],v=u[1],m=u[2],g=u[3],y=i.slice(0),c=i.length;for(var h=0,b=c-n;h<c;h+=n,b-=n)if(h===0||h===c-n)y[h]=i[b],y[h+1]=i[b+3],y[h+2]=i[b+2],y[h+3]=i[b+1];else for(var w=0;w<n;++w)p=i[b+w],y[h+(3&-w)]=d[r[p>>>24]]^v[r[p>>>16&255]]^m[r[p>>>8&255]]^g[r[p&255]];i=y}return i},l=function(e,t,n,s){var a=e.length/4-1,f,l,c,h,p;s?(f=u[0],l=u[1],c=u[2],h=u[3],p=i):(f=o[0],l=o[1],c=o[2],h=o[3],p=r);var d,v,m,g,y,b,w;d=t[0]^e[0],v=t[s?3:1]^e[1],m=t[2]^e[2],g=t[s?1:3]^e[3];var E=3;for(var S=1;S<a;++S)y=f[d>>>24]^l[v>>>16&255]^c[m>>>8&255]^h[g&255]^e[++E],b=f[v>>>24]^l[m>>>16&255]^c[g>>>8&255]^h[d&255]^e[++E],w=f[m>>>24]^l[g>>>16&255]^c[d>>>8&255]^h[v&255]^e[++E],g=f[g>>>24]^l[d>>>16&255]^c[v>>>8&255]^h[m&255]^e[++E],d=y,v=b,m=w;n[0]=p[d>>>24]<<24^p[v>>>16&255]<<16^p[m>>>8&255]<<8^p[g&255]^e[++E],n[s?3:1]=p[v>>>24]<<24^p[m>>>16&255]<<16^p[g>>>8&255]<<8^p[d&255]^e[++E],n[2]=p[m>>>24]<<24^p[g>>>16&255]<<16^p[d>>>8&255]<<8^p[v&255]^e[++E],n[s?1:3]=p[g>>>24]<<24^p[d>>>16&255]<<16^p[v>>>8&255]<<8^p[m&255]^e[++E]},c=function(r,i,s,o,u){function C(){if(o)for(var e=0;e<n;++e)E[e]=b.getInt32();else for(var e=0;e<n;++e)E[e]=x[e]^b.getInt32();l(g,E,S,o);if(o){for(var e=0;e<n;++e)w.putInt32(x[e]^S[e]);x=E.slice(0)}else{for(var e=0;e<n;++e)w.putInt32(S[e]);x=S}}function k(){l(g,E,S,!1);for(var e=0;e<n;++e)E[e]=b.getInt32();for(var e=0;e<n;++e){var t=E[e]^S[e];o||(E[e]=t),w.putInt32(t)}}function L(){l(g,E,S,!1);for(var e=0;e<n;++e)E[e]=b.getInt32();for(var e=0;e<n;++e)w.putInt32(E[e]^S[e]),E[e]=S[e]}function A(){l(g,E,S,!1);for(var e=n-1;e>=0;--e){if(E[e]!==4294967295){++E[e];break}E[e]=0}for(var e=0;e<n;++e)w.putInt32(b.getInt32()^S[e])}var c=null;t||a(),u=(u||"CBC").toUpperCase();if(typeof r!="string"||r.length!==16&&r.length!==24&&r.length!==32){if(e.util.isArray(r)&&(r.length===16||r.length===24||r.length===32)){var h=r,r=e.util.createBuffer();for(var p=0;p<h.length;++p)r.putByte(h[p])}}else r=e.util.createBuffer(r);if(!e.util.isArray(r)){var h=r;r=[];var d=h.length();if(d===16||d===24||d===32){d>>>=2;for(var p=0;p<d;++p)r.push(h.getInt32())}}if(!e.util.isArray(r)||r.length!==4&&r.length!==6&&r.length!==8)return c;var v=["CFB","OFB","CTR"].indexOf(u)!==-1,m=u==="CBC",g=f(r,o&&!v),y=n<<2,b,w,E,S,x,T,N;c={output:null};if(u==="CBC")N=C;else if(u==="CFB")N=k;else if(u==="OFB")N=L;else{if(u!=="CTR")throw{message:'Unsupported block cipher mode of operation: "'+u+'"'};N=A}return c.update=function(e){T||b.putBuffer(e);while(b.length()>=y||b.length()>0&&T)N()},c.finish=function(e){var t=!0,r=b.length()%y;if(!o)if(e)t=e(y,b,o);else if(m){var i=b.length()===y?y:y-b.length();b.fillWithByte(i,i)}t&&(T=!0,c.update());if(o){m&&(t=r===0);if(t)if(e)t=e(y,w,o);else if(m){var s=w.length(),u=w.at(s-1);u>n<<2?t=!1:w.truncate(u)}}return!m&&!e&&r>0&&w.truncate(y-r),t},c.start=function(t,r){t===null&&(t=x.slice(0));if(typeof t=="string"&&t.length===16)t=e.util.createBuffer(t);else if(e.util.isArray(t)&&t.length===16){var i=t,t=e.util.createBuffer();for(var s=0;s<16;++s)t.putByte(i[s])}if(!e.util.isArray(t)){var i=t;t=new Array(4),t[0]=i.getInt32(),t[1]=i.getInt32(),t[2]=i.getInt32(),t[3]=i.getInt32()}b=e.util.createBuffer(),w=r||e.util.createBuffer(),x=t.slice(0),E=new Array(n),S=new Array(n),T=!1,c.output=w;if(["CFB","OFB","CTR"].indexOf(u)!==-1){for(var s=0;s<n;++s)E[s]=x[s];x=null}},i!==null&&c.start(i,s),c};e.aes=e.aes||{},e.aes.startEncrypting=function(e,t,n,r){return c(e,t,n,!1,r)},e.aes.createEncryptionCipher=function(e,t){return c(e,null,null,!1,t)},e.aes.startDecrypting=function(e,t,n,r){return c(e,t,n,!0,r)},e.aes.createDecryptionCipher=function(e,t){return c(e,null,null,!0,t)},e.aes._expandKey=function(e,n){return t||a(),f(e,n)},e.aes._updateBlock=l}var r="aes";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/aes",["require","module","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){e.pki=e.pki||{};var t=e.pki.oids=e.oids=e.oids||{};t["1.2.840.113549.1.1.1"]="rsaEncryption",t.rsaEncryption="1.2.840.113549.1.1.1",t["1.2.840.113549.1.1.4"]="md5WithRSAEncryption",t.md5WithRSAEncryption="1.2.840.113549.1.1.4",t["1.2.840.113549.1.1.5"]="sha1WithRSAEncryption",t.sha1WithRSAEncryption="1.2.840.113549.1.1.5",t["1.2.840.113549.1.1.7"]="RSAES-OAEP",t["RSAES-OAEP"]="1.2.840.113549.1.1.7",t["1.2.840.113549.1.1.8"]="mgf1",t.mgf1="1.2.840.113549.1.1.8",t["1.2.840.113549.1.1.9"]="pSpecified",t.pSpecified="1.2.840.113549.1.1.9",t["1.2.840.113549.1.1.10"]="RSASSA-PSS",t["RSASSA-PSS"]="1.2.840.113549.1.1.10",t["1.2.840.113549.1.1.11"]="sha256WithRSAEncryption",t.sha256WithRSAEncryption="1.2.840.113549.1.1.11",t["1.2.840.113549.1.1.12"]="sha384WithRSAEncryption",t.sha384WithRSAEncryption="1.2.840.113549.1.1.12",t["1.2.840.113549.1.1.13"]="sha512WithRSAEncryption",t.sha512WithRSAEncryption="1.2.840.113549.1.1.13",t["1.3.14.3.2.7"]="desCBC",t.desCBC="1.3.14.3.2.7",t["1.3.14.3.2.26"]="sha1",t.sha1="1.3.14.3.2.26",t["2.16.840.1.101.3.4.2.1"]="sha256",t.sha256="2.16.840.1.101.3.4.2.1",t["2.16.840.1.101.3.4.2.2"]="sha384",t.sha384="2.16.840.1.101.3.4.2.2",t["2.16.840.1.101.3.4.2.3"]="sha512",t.sha512="2.16.840.1.101.3.4.2.3",t["1.2.840.113549.2.5"]="md5",t.md5="1.2.840.113549.2.5",t["1.2.840.113549.1.7.1"]="data",t.data="1.2.840.113549.1.7.1",t["1.2.840.113549.1.7.2"]="signedData",t.signedData="1.2.840.113549.1.7.2",t["1.2.840.113549.1.7.3"]="envelopedData",t.envelopedData="1.2.840.113549.1.7.3",t["1.2.840.113549.1.7.4"]="signedAndEnvelopedData",t.signedAndEnvelopedData="1.2.840.113549.1.7.4",t["1.2.840.113549.1.7.5"]="digestedData",t.digestedData="1.2.840.113549.1.7.5",t["1.2.840.113549.1.7.6"]="encryptedData",t.encryptedData="1.2.840.113549.1.7.6",t["1.2.840.113549.1.9.1"]="emailAddress",t.emailAddress="1.2.840.113549.1.9.1",t["1.2.840.113549.1.9.2"]="unstructuredName",t.unstructuredName="1.2.840.113549.1.9.2",t["1.2.840.113549.1.9.3"]="contentType",t.contentType="1.2.840.113549.1.9.3",t["1.2.840.113549.1.9.4"]="messageDigest",t.messageDigest="1.2.840.113549.1.9.4",t["1.2.840.113549.1.9.5"]="signingTime",t.signingTime="1.2.840.113549.1.9.5",t["1.2.840.113549.1.9.6"]="counterSignature",t.counterSignature="1.2.840.113549.1.9.6",t["1.2.840.113549.1.9.7"]="challengePassword",t.challengePassword="1.2.840.113549.1.9.7",t["1.2.840.113549.1.9.8"]="unstructuredAddress",t.unstructuredAddress="1.2.840.113549.1.9.8",t["1.2.840.113549.1.9.20"]="friendlyName",t.friendlyName="1.2.840.113549.1.9.20",t["1.2.840.113549.1.9.21"]="localKeyId",t.localKeyId="1.2.840.113549.1.9.21",t["1.2.840.113549.1.9.22.1"]="x509Certificate",t.x509Certificate="1.2.840.113549.1.9.22.1",t["1.2.840.113549.1.12.10.1.1"]="keyBag",t.keyBag="1.2.840.113549.1.12.10.1.1",t["1.2.840.113549.1.12.10.1.2"]="pkcs8ShroudedKeyBag",t.pkcs8ShroudedKeyBag="1.2.840.113549.1.12.10.1.2",t["1.2.840.113549.1.12.10.1.3"]="certBag",t.certBag="1.2.840.113549.1.12.10.1.3",t["1.2.840.113549.1.12.10.1.4"]="crlBag",t.crlBag="1.2.840.113549.1.12.10.1.4",t["1.2.840.113549.1.12.10.1.5"]="secretBag",t.secretBag="1.2.840.113549.1.12.10.1.5",t["1.2.840.113549.1.12.10.1.6"]="safeContentsBag",t.safeContentsBag="1.2.840.113549.1.12.10.1.6",t["1.2.840.113549.1.5.13"]="pkcs5PBES2",t.pkcs5PBES2="1.2.840.113549.1.5.13",t["1.2.840.113549.1.5.12"]="pkcs5PBKDF2",t.pkcs5PBKDF2="1.2.840.113549.1.5.12",t["1.2.840.113549.1.12.1.1"]="pbeWithSHAAnd128BitRC4",t.pbeWithSHAAnd128BitRC4="1.2.840.113549.1.12.1.1",t["1.2.840.113549.1.12.1.2"]="pbeWithSHAAnd40BitRC4",t.pbeWithSHAAnd40BitRC4="1.2.840.113549.1.12.1.2",t["1.2.840.113549.1.12.1.3"]="pbeWithSHAAnd3-KeyTripleDES-CBC",t["pbeWithSHAAnd3-KeyTripleDES-CBC"]="1.2.840.113549.1.12.1.3",t["1.2.840.113549.1.12.1.4"]="pbeWithSHAAnd2-KeyTripleDES-CBC",t["pbeWithSHAAnd2-KeyTripleDES-CBC"]="1.2.840.113549.1.12.1.4",t["1.2.840.113549.1.12.1.5"]="pbeWithSHAAnd128BitRC2-CBC",t["pbeWithSHAAnd128BitRC2-CBC"]="1.2.840.113549.1.12.1.5",t["1.2.840.113549.1.12.1.6"]="pbewithSHAAnd40BitRC2-CBC",t["pbewithSHAAnd40BitRC2-CBC"]="1.2.840.113549.1.12.1.6",t["1.2.840.113549.3.7"]="des-EDE3-CBC",t["des-EDE3-CBC"]="1.2.840.113549.3.7",t["2.16.840.1.101.3.4.1.2"]="aes128-CBC",t["aes128-CBC"]="2.16.840.1.101.3.4.1.2",t["2.16.840.1.101.3.4.1.22"]="aes192-CBC",t["aes192-CBC"]="2.16.840.1.101.3.4.1.22",t["2.16.840.1.101.3.4.1.42"]="aes256-CBC",t["aes256-CBC"]="2.16.840.1.101.3.4.1.42",t["2.5.4.3"]="commonName",t.commonName="2.5.4.3",t["2.5.4.5"]="serialName",t.serialName="2.5.4.5",t["2.5.4.6"]="countryName",t.countryName="2.5.4.6",t["2.5.4.7"]="localityName",t.localityName="2.5.4.7",t["2.5.4.8"]="stateOrProvinceName",t.stateOrProvinceName="2.5.4.8",t["2.5.4.10"]="organizationName",t.organizationName="2.5.4.10",t["2.5.4.11"]="organizationalUnitName",t.organizationalUnitName="2.5.4.11",t["2.16.840.1.113730.1.1"]="nsCertType",t.nsCertType="2.16.840.1.113730.1.1",t["2.5.29.1"]="authorityKeyIdentifier",t["2.5.29.2"]="keyAttributes",t["2.5.29.3"]="certificatePolicies",t["2.5.29.4"]="keyUsageRestriction",t["2.5.29.5"]="policyMapping",t["2.5.29.6"]="subtreesConstraint",t["2.5.29.7"]="subjectAltName",t["2.5.29.8"]="issuerAltName",t["2.5.29.9"]="subjectDirectoryAttributes",t["2.5.29.10"]="basicConstraints",t["2.5.29.11"]="nameConstraints",t["2.5.29.12"]="policyConstraints",t["2.5.29.13"]="basicConstraints",t["2.5.29.14"]="subjectKeyIdentifier",t.subjectKeyIdentifier="2.5.29.14",t["2.5.29.15"]="keyUsage",t.keyUsage="2.5.29.15",t["2.5.29.16"]="privateKeyUsagePeriod",t["2.5.29.17"]="subjectAltName",t.subjectAltName="2.5.29.17",t["2.5.29.18"]="issuerAltName",t.issuerAltName="2.5.29.18",t["2.5.29.19"]="basicConstraints",t.basicConstraints="2.5.29.19",t["2.5.29.20"]="cRLNumber",t["2.5.29.21"]="cRLReason",t["2.5.29.22"]="expirationDate",t["2.5.29.23"]="instructionCode",t["2.5.29.24"]="invalidityDate",t["2.5.29.25"]="cRLDistributionPoints",t["2.5.29.26"]="issuingDistributionPoint",t["2.5.29.27"]="deltaCRLIndicator",t["2.5.29.28"]="issuingDistributionPoint",t["2.5.29.29"]="certificateIssuer",t["2.5.29.30"]="nameConstraints",t["2.5.29.31"]="cRLDistributionPoints",t["2.5.29.32"]="certificatePolicies",t["2.5.29.33"]="policyMappings",t["2.5.29.34"]="policyConstraints",t["2.5.29.35"]="authorityKeyIdentifier",t["2.5.29.36"]="policyConstraints",t["2.5.29.37"]="extKeyUsage",t.extKeyUsage="2.5.29.37",t["2.5.29.46"]="freshestCRL",t["2.5.29.54"]="inhibitAnyPolicy",t["1.3.6.1.5.5.7.3.1"]="serverAuth",t.serverAuth="1.3.6.1.5.5.7.3.1",t["1.3.6.1.5.5.7.3.2"]="clientAuth",t.clientAuth="1.3.6.1.5.5.7.3.2",t["1.3.6.1.5.5.7.3.3"]="codeSigning",t.codeSigning="1.3.6.1.5.5.7.3.3",t["1.3.6.1.5.5.7.3.4"]="emailProtection",t.emailProtection="1.3.6.1.5.5.7.3.4",t["1.3.6.1.5.5.7.3.8"]="timeStamping",t.timeStamping="1.3.6.1.5.5.7.3.8"}var r="oids";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/oids",["require","module"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){var t=e.asn1=e.asn1||{};t.Class={UNIVERSAL:0,APPLICATION:64,CONTEXT_SPECIFIC:128,PRIVATE:192},t.Type={NONE:0,BOOLEAN:1,INTEGER:2,BITSTRING:3,OCTETSTRING:4,NULL:5,OID:6,ODESC:7,EXTERNAL:8,REAL:9,ENUMERATED:10,EMBEDDED:11,UTF8:12,ROID:13,SEQUENCE:16,SET:17,PRINTABLESTRING:19,IA5STRING:22,UTCTIME:23,GENERALIZEDTIME:24,BMPSTRING:30},t.create=function(t,n,r,i){if(e.util.isArray(i)){var s=[];for(var o=0;o<i.length;++o)i[o]!==undefined&&s.push(i[o]);i=s}return{tagClass:t,type:n,constructed:r,composed:r||e.util.isArray(i),value:i}};var n=function(e){var t=e.getByte();if(t===128)return undefined;var n,r=t&128;return r?n=e.getInt((t&127)<<3):n=t,n};t.fromDer=function(r,i){i===undefined&&(i=!0),typeof r=="string"&&(r=e.util.createBuffer(r));if(r.length()<2)throw{message:"Too few bytes to parse DER.",bytes:r.length()};var s=r.getByte(),o=s&192,u=s&31,a=n(r);if(r.length()<a){if(i)throw{message:"Too few bytes to read ASN.1 value.",detail:r.length()+" < "+a};a=r.length()}var f,l=(s&32)===32,c=l;if(!c&&o===t.Class.UNIVERSAL&&u===t.Type.BITSTRING&&a>1){var h=r.read,p=r.getByte();if(p===0){s=r.getByte();var d=s&192;if(d===t.Class.UNIVERSAL||d===t.Class.CONTEXT_SPECIFIC)try{var v=n(r);c=v===a-(r.read-h),c&&(++h,--a)}catch(m){}}r.read=h}if(c){f=[];if(a===undefined)for(;;){if(r.bytes(2)===String.fromCharCode(0,0)){r.getBytes(2);break}f.push(t.fromDer(r,i))}else{var g=r.length();while(a>0)f.push(t.fromDer(r,i)),a-=g-r.length(),g=r.length()}}else{if(a===undefined){if(i)throw{message:"Non-constructed ASN.1 object of indefinite length."};a=r.length()}if(u===t.Type.BMPSTRING){f="";for(var y=0;y<a;y+=2)f+=String.fromCharCode(r.getInt16())}else f=r.getBytes(a)}return t.create(o,u,l,f)},t.toDer=function(n){var r=e.util.createBuffer(),i=n.tagClass|n.type,s=e.util.createBuffer();if(n.composed){n.constructed?i|=32:s.putByte(0);for(var o=0;o<n.value.length;++o)n.value[o]!==undefined&&s.putBuffer(t.toDer(n.value[o]))}else if(n.type===t.Type.BMPSTRING)for(var o=0;o<n.value.length;++o)s.putInt16(n.value.charCodeAt(o));else s.putBytes(n.value);r.putByte(i);if(s.length()<=127)r.putByte(s.length()&127);else{var u=s.length(),a="";do a+=String.fromCharCode(u&255),u>>>=8;while(u>0);r.putByte(a.length|128);for(var o=a.length-1;o>=0;--o)r.putByte(a.charCodeAt(o))}return r.putBuffer(s),r},t.oidToDer=function(t){var n=t.split("."),r=e.util.createBuffer();r.putByte(40*parseInt(n[0],10)+parseInt(n[1],10));var i,s,o,u;for(var a=2;a<n.length;++a){i=!0,s=[],o=parseInt(n[a],10);do u=o&127,o>>>=7,i||(u|=128),s.push(u),i=!1;while(o>0);for(var f=s.length-1;f>=0;--f)r.putByte(s[f])}return r},t.derToOid=function(t){var n;typeof t=="string"&&(t=e.util.createBuffer(t));var r=t.getByte();n=Math.floor(r/40)+"."+r%40;var i=0;while(t.length()>0)r=t.getByte(),i<<=7,r&128?i+=r&127:(n+="."+(i+r),i=0);return n},t.utcTimeToDate=function(e){var t=new Date,n=parseInt(e.substr(0,2),10);n=n>=50?1900+n:2e3+n;var r=parseInt(e.substr(2,2),10)-1,i=parseInt(e.substr(4,2),10),s=parseInt(e.substr(6,2),10),o=parseInt(e.substr(8,2),10),u=0;if(e.length>11){var a=e.charAt(10),f=10;a!=="+"&&a!=="-"&&(u=parseInt(e.substr(10,2),10),f+=2)}t.setUTCFullYear(n,r,i),t.setUTCHours(s,o,u,0);if(f){a=e.charAt(f);if(a==="+"||a==="-"){var l=parseInt(e.substr(f+1,2),10),c=parseInt(e.substr(f+4,2),10),h=l*60+c;h*=6e4,a==="+"?t.setTime(+t-h):t.setTime(+t+h)}}return t},t.generalizedTimeToDate=function(e){var t=new Date,n=parseInt(e.substr(0,4),10),r=parseInt(e.substr(4,2),10)-1,i=parseInt(e.substr(6,2),10),s=parseInt(e.substr(8,2),10),o=parseInt(e.substr(10,2),10),u=parseInt(e.substr(12,2),10),a=0,f=0,l=!1;e.charAt(e.length-1)==="Z"&&(l=!0);var c=e.length-5,h=e.charAt(c);if(h==="+"||h==="-"){var p=parseInt(e.substr(c+1,2),10),d=parseInt(e.substr(c+4,2),10);f=p*60+d,f*=6e4,h==="+"&&(f*=-1),l=!0}return e.charAt(14)==="."&&(a=parseFloat(e.substr(14),10)*1e3),l?(t.setUTCFullYear(n,r,i),t.setUTCHours(s,o,u,a),t.setTime(+t+f)):(t.setFullYear(n,r,i),t.setHours(s,o,u,a)),t},t.dateToUtcTime=function(e){var t="",n=[];n.push((""+e.getUTCFullYear()).substr(2)),n.push(""+(e.getUTCMonth()+1)),n.push(""+e.getUTCDate()),n.push(""+e.getUTCHours()),n.push(""+e.getUTCMinutes()),n.push(""+e.getUTCSeconds());for(var r=0;r<n.length;++r)n[r].length<2&&(t+="0"),t+=n[r];return t+="Z",t},t.integerToDer=function(t){var n=e.util.createBuffer();if(t>=-128&&t<128)return n.putSignedInt(t,8);if(t>=-32768&&t<32768)return n.putSignedInt(t,16);if(t>=-8388608&&t<8388608)return n.putSignedInt(t,24);if(t>=-2147483648&&t<2147483648)return n.putSignedInt(t,32);throw{message:"Integer too large; max is 32-bits.",integer:t}},t.derToInteger=function(t){typeof t=="string"&&(t=e.util.createBuffer(t));var n=t.length()*8;if(n>32)throw{message:"Integer too large; max is 32-bits."};return t.getSignedInt(n)},t.validate=function(n,r,i,s){var o=!1;if(n.tagClass!==r.tagClass&&typeof r.tagClass!="undefined"||n.type!==r.type&&typeof r.type!="undefined")s&&(n.tagClass!==r.tagClass&&s.push("["+r.name+"] "+'Expected tag class "'+r.tagClass+'", got "'+n.tagClass+'"'),n.type!==r.type&&s.push("["+r.name+"] "+'Expected type "'+r.type+'", got "'+n.type+'"'));else if(n.constructed===r.constructed||typeof r.constructed=="undefined"){o=!0;if(r.value&&e.util.isArray(r.value)){var u=0;for(var a=0;o&&a<r.value.length;++a)o=r.value[a].optional||!1,n.value[u]&&(o=t.validate(n.value[u],r.value[a],i,s),o?++u:r.value[a].optional&&(o=!0)),!o&&s&&s.push("["+r.name+"] "+'Tag class "'+r.tagClass+'", type "'+r.type+'" expected value length "'+r.value.length+'", got "'+n.value.length+'"')}o&&i&&(r.capture&&(i[r.capture]=n.value),r.captureAsn1&&(i[r.captureAsn1]=n))}else s&&s.push("["+r.name+"] "+'Expected constructed "'+r.constructed+'", got "'+n.constructed+'"');return o};var r=/[^\\u0000-\\u00ff]/;t.prettyPrint=function(n,i,s){var o="";i=i||0,s=s||2,i>0&&(o+="\n");var u="";for(var a=0;a<i*s;++a)u+=" ";o+=u+"Tag: ";switch(n.tagClass){case t.Class.UNIVERSAL:o+="Universal:";break;case t.Class.APPLICATION:o+="Application:";break;case t.Class.CONTEXT_SPECIFIC:o+="Context-Specific:";break;case t.Class.PRIVATE:o+="Private:"}if(n.tagClass===t.Class.UNIVERSAL){o+=n.type;switch(n.type){case t.Type.NONE:o+=" (None)";break;case t.Type.BOOLEAN:o+=" (Boolean)";break;case t.Type.BITSTRING:o+=" (Bit string)";break;case t.Type.INTEGER:o+=" (Integer)";break;case t.Type.OCTETSTRING:o+=" (Octet string)";break;case t.Type.NULL:o+=" (Null)";break;case t.Type.OID:o+=" (Object Identifier)";break;case t.Type.ODESC:o+=" (Object Descriptor)";break;case t.Type.EXTERNAL:o+=" (External or Instance of)";break;case t.Type.REAL:o+=" (Real)";break;case t.Type.ENUMERATED:o+=" (Enumerated)";break;case t.Type.EMBEDDED:o+=" (Embedded PDV)";break;case t.Type.UTF8:o+=" (UTF8)";break;case t.Type.ROID:o+=" (Relative Object Identifier)";break;case t.Type.SEQUENCE:o+=" (Sequence)";break;case t.Type.SET:o+=" (Set)";break;case t.Type.PRINTABLESTRING:o+=" (Printable String)";break;case t.Type.IA5String:o+=" (IA5String (ASCII))";break;case t.Type.UTCTIME:o+=" (UTC time)";break;case t.Type.GENERALIZEDTIME:o+=" (Generalized time)";break;case t.Type.BMPSTRING:o+=" (BMP String)"}}else o+=n.type;o+="\n",o+=u+"Constructed: "+n.constructed+"\n";if(n.composed){var f=0,l="";for(var a=0;a<n.value.length;++a)n.value[a]!==undefined&&(f+=1,l+=t.prettyPrint(n.value[a],i+1,s),a+1<n.value.length&&(l+=","));o+=u+"Sub values: "+f+l}else{o+=u+"Value: ";if(n.type===t.Type.OID){var c=t.derToOid(n.value);o+=c,e.pki&&e.pki.oids&&c in e.pki.oids&&(o+=" ("+e.pki.oids[c]+")")}if(n.type===t.Type.INTEGER)try{o+=t.derToInteger(n.value)}catch(h){o+="0x"+e.util.bytesToHex(n.value)}else r.test(n.value)?o+="0x"+e.util.createBuffer(n.value,"utf8").toHex():n.value.length===0?o+="[null]":o+=n.value}return o}}var r="asn1";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/asn1",["require","module","./util","./oids"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){var t=e.md5=e.md5||{};e.md=e.md||{},e.md.algorithms=e.md.algorithms||{},e.md.md5=e.md.algorithms.md5=t;var n=null,r=null,i=null,s=null,o=!1,u=function(){n=String.fromCharCode(128),n+=e.util.fillString(String.fromCharCode(0),64),r=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9],i=[7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21],s=new Array(64);for(var t=0;t<64;++t)s[t]=Math.floor(Math.abs(Math.sin(t+1))*4294967296);o=!0},a=function(e,t,n){var o,u,a,f,l,c,h,p,d=n.length();while(d>=64){u=e.h0,a=e.h1,f=e.h2,l=e.h3;for(p=0;p<16;++p)t[p]=n.getInt32Le(),c=l^a&(f^l),o=u+c+s[p]+t[p],h=i[p],u=l,l=f,f=a,a+=o<<h|o>>>32-h;for(;p<32;++p)c=f^l&(a^f),o=u+c+s[p]+t[r[p]],h=i[p],u=l,l=f,f=a,a+=o<<h|o>>>32-h;for(;p<48;++p)c=a^f^l,o=u+c+s[p]+t[r[p]],h=i[p],u=l,l=f,f=a,a+=o<<h|o>>>32-h;for(;p<64;++p)c=f^(a|~l),o=u+c+s[p]+t[r[p]],h=i[p],u=l,l=f,f=a,a+=o<<h|o>>>32-h;e.h0=e.h0+u&4294967295,e.h1=e.h1+a&4294967295,e.h2=e.h2+f&4294967295,e.h3=e.h3+l&4294967295,d-=64}};t.create=function(){o||u();var t=null,r=e.util.createBuffer(),i=new Array(16),s={algorithm:"md5",blockLength:64,digestLength:16,messageLength:0};return s.start=function(){return s.messageLength=0,r=e.util.createBuffer(),t={h0:1732584193,h1:4023233417,h2:2562383102,h3:271733878},s},s.start(),s.update=function(n,o){return o==="utf8"&&(n=e.util.encodeUtf8(n)),s.messageLength+=n.length,r.putBytes(n),a(t,i,r),(r.read>2048||r.length()===0)&&r.compact(),s},s.digest=function(){var o=s.messageLength,u=e.util.createBuffer();u.putBytes(r.bytes()),u.putBytes(n.substr(0,64-(o+8)%64)),u.putInt32Le(o<<3&4294967295),u.putInt32Le(o>>>29&255);var f={h0:t.h0,h1:t.h1,h2:t.h2,h3:t.h3};a(f,i,u);var l=e.util.createBuffer();return l.putInt32Le(f.h0),l.putInt32Le(f.h1),l.putInt32Le(f.h2),l.putInt32Le(f.h3),l},s}}var r="md5";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/md5",["require","module","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){var t=e.sha1=e.sha1||{};e.md=e.md||{},e.md.algorithms=e.md.algorithms||{},e.md.sha1=e.md.algorithms.sha1=t;var n=null,r=!1,i=function(){n=String.fromCharCode(128),n+=e.util.fillString(String.fromCharCode(0),64),r=!0},s=function(e,t,n){var r,i,s,o,u,a,f,l,c=n.length();while(c>=64){i=e.h0,s=e.h1,o=e.h2,u=e.h3,a=e.h4;for(l=0;l<16;++l)r=n.getInt32(),t[l]=r,f=u^s&(o^u),r=(i<<5|i>>>27)+f+a+1518500249+r,a=u,u=o,o=s<<30|s>>>2,s=i,i=r;for(;l<20;++l)r=t[l-3]^t[l-8]^t[l-14]^t[l-16],r=r<<1|r>>>31,t[l]=r,f=u^s&(o^u),r=(i<<5|i>>>27)+f+a+1518500249+r,a=u,u=o,o=s<<30|s>>>2,s=i,i=r;for(;l<32;++l)r=t[l-3]^t[l-8]^t[l-14]^t[l-16],r=r<<1|r>>>31,t[l]=r,f=s^o^u,r=(i<<5|i>>>27)+f+a+1859775393+r,a=u,u=o,o=s<<30|s>>>2,s=i,i=r;for(;l<40;++l)r=t[l-6]^t[l-16]^t[l-28]^t[l-32],r=r<<2|r>>>30,t[l]=r,f=s^o^u,r=(i<<5|i>>>27)+f+a+1859775393+r,a=u,u=o,o=s<<30|s>>>2,s=i,i=r;for(;l<60;++l)r=t[l-6]^t[l-16]^t[l-28]^t[l-32],r=r<<2|r>>>30,t[l]=r,f=s&o|u&(s^o),r=(i<<5|i>>>27)+f+a+2400959708+r,a=u,u=o,o=s<<30|s>>>2,s=i,i=r;for(;l<80;++l)r=t[l-6]^t[l-16]^t[l-28]^t[l-32],r=r<<2|r>>>30,t[l]=r,f=s^o^u,r=(i<<5|i>>>27)+f+a+3395469782+r,a=u,u=o,o=s<<30|s>>>2,s=i,i=r;e.h0+=i,e.h1+=s,e.h2+=o,e.h3+=u,e.h4+=a,c-=64}};t.create=function(){r||i();var t=null,o=e.util.createBuffer(),u=new Array(80),a={algorithm:"sha1",blockLength:64,digestLength:20,messageLength:0};return a.start=function(){return a.messageLength=0,o=e.util.createBuffer(),t={h0:1732584193,h1:4023233417,h2:2562383102,h3:271733878,h4:3285377520},a},a.start(),a.update=function(n,r){return r==="utf8"&&(n=e.util.encodeUtf8(n)),a.messageLength+=n.length,o.putBytes(n),s(t,u,o),(o.read>2048||o.length()===0)&&o.compact(),a},a.digest=function(){var r=a.messageLength,i=e.util.createBuffer();i.putBytes(o.bytes()),i.putBytes(n.substr(0,64-(r+8)%64)),i.putInt32(r>>>29&255),i.putInt32(r<<3&4294967295);var f={h0:t.h0,h1:t.h1,h2:t.h2,h3:t.h3,h4:t.h4};s(f,u,i);var l=e.util.createBuffer();return l.putInt32(f.h0),l.putInt32(f.h1),l.putInt32(f.h2),l.putInt32(f.h3),l.putInt32(f.h4),l},a}}var r="sha1";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/sha1",["require","module","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){var t=e.sha256=e.sha256||{};e.md=e.md||{},e.md.algorithms=e.md.algorithms||{},e.md.sha256=e.md.algorithms.sha256=t;var n=null,r=!1,i=null,s=function(){n=String.fromCharCode(128),n+=e.util.fillString(String.fromCharCode(0),64),i=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],r=!0},o=function(e,t,n){var r,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b=n.length();while(b>=64){for(l=0;l<16;++l)t[l]=n.getInt32();for(;l<64;++l)r=t[l-2],r=(r>>>17|r<<15)^(r>>>19|r<<13)^r>>>10,s=t[l-15],s=(s>>>7|s<<25)^(s>>>18|s<<14)^s>>>3,t[l]=r+t[l-7]+s+t[l-16]&4294967295;c=e.h0,h=e.h1,p=e.h2,d=e.h3,v=e.h4,m=e.h5,g=e.h6,y=e.h7;for(l=0;l<64;++l)u=(v>>>6|v<<26)^(v>>>11|v<<21)^(v>>>25|v<<7),a=g^v&(m^g),o=(c>>>2|c<<30)^(c>>>13|c<<19)^(c>>>22|c<<10),f=c&h|p&(c^h),r=y+u+a+i[l]+t[l],s=o+f,y=g,g=m,m=v,v=d+r&4294967295,d=p,p=h,h=c,c=r+s&4294967295;e.h0=e.h0+c&4294967295,e.h1=e.h1+h&4294967295,e.h2=e.h2+p&4294967295,e.h3=e.h3+d&4294967295,e.h4=e.h4+v&4294967295,e.h5=e.h5+m&4294967295,e.h6=e.h6+g&4294967295,e.h7=e.h7+y&4294967295,b-=64}};t.create=function(){r||s();var t=null,i=e.util.createBuffer(),u=new Array(64),a={algorithm:"sha256",blockLength:64,digestLength:32,messageLength:0};return a.start=function(){return a.messageLength=0,i=e.util.createBuffer(),t={h0:1779033703,h1:3144134277,h2:1013904242,h3:2773480762,h4:1359893119,h5:2600822924,h6:528734635,h7:1541459225},a},a.start(),a.update=function(n,r){return r==="utf8"&&(n=e.util.encodeUtf8(n)),a.messageLength+=n.length,i.putBytes(n),o(t,u,i),(i.read>2048||i.length()===0)&&i.compact(),a},a.digest=function(){var r=a.messageLength,s=e.util.createBuffer();s.putBytes(i.bytes()),s.putBytes(n.substr(0,64-(r+8)%64)),s.putInt32(r>>>29&255),s.putInt32(r<<3&4294967295);var f={h0:t.h0,h1:t.h1,h2:t.h2,h3:t.h3,h4:t.h4,h5:t.h5,h6:t.h6,h7:t.h7};o(f,u,s);var l=e.util.createBuffer();return l.putInt32(f.h0),l.putInt32(f.h1),l.putInt32(f.h2),l.putInt32(f.h3),l.putInt32(f.h4),l.putInt32(f.h5),l.putInt32(f.h6),l.putInt32(f.h7),l},a}}var r="sha256";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/sha256",["require","module","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){e.md=e.md||{},e.md.algorithms={md5:e.md5,sha1:e.sha1,sha256:e.sha256},e.md.md5=e.md5,e.md.sha1=e.sha1,e.md.sha256=e.sha256}var r="md";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/md",["require","module","./md5","./sha1","./sha256"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){var t=e.hmac=e.hmac||{};t.create=function(){var t=null,n=null,r=null,i=null,s={};return s.start=function(s,o){if(s!==null)if(typeof s=="string"){s=s.toLowerCase();if(!(s in e.md.algorithms))throw'Unknown hash algorithm "'+s+'"';n=e.md.algorithms[s].create()}else n=s;if(o===null)o=t;else{if(typeof o=="string")o=e.util.createBuffer(o);else if(e.util.isArray(o)){var u=o;o=e.util.createBuffer();for(var a=0;a<u.length;++a)o.putByte(u[a])}var f=o.length();f>n.blockLength&&(n.start(),n.update(o.bytes()),o=n.digest()),r=e.util.createBuffer(),i=e.util.createBuffer(),f=o.length();for(var a=0;a<f;++a){var u=o.at(a);r.putByte(54^u),i.putByte(92^u)}if(f<n.blockLength){var u=n.blockLength-f;for(var a=0;a<u;++a)r.putByte(54),i.putByte(92)}t=o,r=r.bytes(),i=i.bytes()}n.start(),n.update(r)},s.update=function(e){n.update(e)},s.getMac=function(){var e=n.digest().bytes();return n.start(),n.update(i),n.update(e),n.digest()},s.digest=s.getMac,s}}var r="hmac";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/hmac",["require","module","./md","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){function n(e){var t=e.name+": ",n=[];for(var r=0;r<e.values.length;++r)n.push(e.values[r].replace(/^(\S+\r\n)/,function(e,t){return" "+t}));t+=n.join(",")+"\r\n";var i=0,s=-1;for(var r=0;r<t.length;++r,++i)if(i>65&&s!==-1){var o=t[s];o===","?(++s,t=t.substr(0,s)+"\r\n "+t.substr(s)):t=t.substr(0,s)+"\r\n"+o+t.substr(s+1),i=r-s-1,s=-1,++r}else if(t[r]===" "||t[r]===" "||t[r]===",")s=r;return t}function r(e){return e.replace(/^\s+/,"")}var t=e.pem=e.pem||{};t.encode=function(t,r){r=r||{};var i="-----BEGIN "+t.type+"-----\r\n",s;t.procType&&(s={name:"Proc-Type",values:[String(t.procType.version),t.procType.type]},i+=n(s)),t.contentDomain&&(s={name:"Content-Domain",values:[t.contentDomain]},i+=n(s)),t.dekInfo&&(s={name:"DEK-Info",values:[t.dekInfo.algorithm]},t.dekInfo.parameters&&s.values.push(t.dekInfo.parameters),i+=n(s));if(t.headers)for(var o=0;o<t.headers.length;++o)i+=n(t.headers[o]);return t.procType&&(i+="\r\n"),i+=e.util.encode64(t.body,r.maxline||64)+"\r\n",i+="-----END "+t.type+"-----\r\n",i},t.decode=function(t){var n=[],i=/\s*-----BEGIN ([A-Z0-9- ]+)-----\r?\n?([\x21-\x7e\s]+?(?:\r?\n\r?\n))?([:A-Za-z0-9+\/=\s]+?)-----END \1-----/g,s=/([\x21-\x7e]+):\s*([\x21-\x7e\s^:]+)/,o=/\r?\n/,u;for(;;){u=i.exec(t);if(!u)break;var a={type:u[1],procType:null,contentDomain:null,dekInfo:null,headers:[],body:e.util.decode64(u[3])};n.push(a);if(!u[2])continue;var f=u[2].split(o),l=0;while(u&&l<f.length){var c=f[l].replace(/\s+$/,"");for(var h=l+1;h<f.length;++h){var p=f[h];if(!/\s/.test(p[0]))break;c+=p,l=h}u=c.match(s);if(u){var d={name:u[1],values:[]},v=u[2].split(",");for(var m=0;m<v.length;++m)d.values.push(r(v[m]));if(!a.procType){if(d.name!=="Proc-Type")throw{message:'Invalid PEM formatted message. The first encapsulated header must be "Proc-Type".'};if(d.values.length!==2)throw{message:'Invalid PEM formatted message. The "Proc-Type" header must have two subfields.'};a.procType={version:v[0],type:v[1]}}else if(!a.contentDomain&&d.name==="Content-Domain")a.contentDomain=v[0]||"";else if(!a.dekInfo&&d.name==="DEK-Info"){if(d.values.length===0)throw{message:'Invalid PEM formatted message. The "DEK-Info" header must have at least one subfield.'};a.dekInfo={algorithm:v[0],parameters:v[1]||null}}else a.headers.push(d)}++l}if(a.procType==="ENCRYPTED"&&!a.dekInfo)throw{message:'Invalid PEM formatted message. The "DEK-Info" header must be present if "Proc-Type" is "ENCRYPTED".'}}if(n.length===0)throw{message:"Invalid PEM formatted message."};return n}}var r="pem";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/pem",["require","module","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){function f(e){var t=[0,4,536870912,536870916,65536,65540,536936448,536936452,512,516,536871424,536871428,66048,66052,536936960,536936964],n=[0,1,1048576,1048577,67108864,67108865,68157440,68157441,256,257,1048832,1048833,67109120,67109121,68157696,68157697],r=[0,8,2048,2056,16777216,16777224,16779264,16779272,0,8,2048,2056,16777216,16777224,16779264,16779272],i=[0,2097152,134217728,136314880,8192,2105344,134225920,136323072,131072,2228224,134348800,136445952,139264,2236416,134356992,136454144],s=[0,262144,16,262160,0,262144,16,262160,4096,266240,4112,266256,4096,266240,4112,266256],o=[0,1024,32,1056,0,1024,32,1056,33554432,33555456,33554464,33555488,33554432,33555456,33554464,33555488],u=[0,268435456,524288,268959744,2,268435458,524290,268959746,0,268435456,524288,268959744,2,268435458,524290,268959746],a=[0,65536,2048,67584,536870912,536936448,536872960,536938496,131072,196608,133120,198656,537001984,537067520,537004032,537069568],f=[0,262144,0,262144,2,262146,2,262146,33554432,33816576,33554432,33816576,33554434,33816578,33554434,33816578],l=[0,268435456,8,268435464,0,268435456,8,268435464,1024,268436480,1032,268436488,1024,268436480,1032,268436488],c=[0,32,0,32,1048576,1048608,1048576,1048608,8192,8224,8192,8224,1056768,1056800,1056768,1056800],h=[0,16777216,512,16777728,2097152,18874368,2097664,18874880,67108864,83886080,67109376,83886592,69206016,85983232,69206528,85983744],p=[0,4096,134217728,134221824,524288,528384,134742016,134746112,16,4112,134217744,134221840,524304,528400,134742032,134746128],d=[0,4,256,260,0,4,256,260,1,5,257,261,1,5,257,261],v=e.length()>8?3:1,m=[],g=[0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0],y=0,b;for(var w=0;w<v;w++){var E=e.getInt32(),S=e.getInt32();b=(E>>>4^S)&252645135,S^=b,E^=b<<4,b=(S>>>-16^E)&65535,E^=b,S^=b<<-16,b=(E>>>2^S)&858993459,S^=b,E^=b<<2,b=(S>>>-16^E)&65535,E^=b,S^=b<<-16,b=(E>>>1^S)&1431655765,S^=b,E^=b<<1,b=(S>>>8^E)&16711935,E^=b,S^=b<<8,b=(E>>>1^S)&1431655765,S^=b,E^=b<<1,b=E<<8|S>>>20&240,E=S<<24|S<<8&16711680|S>>>8&65280|S>>>24&240,S=b;for(var x=0;x<g.length;x++){g[x]?(E=E<<2|E>>>26,S=S<<2|S>>>26):(E=E<<1|E>>>27,S=S<<1|S>>>27),E&=-15,S&=-15;var T=t[E>>>28]|n[E>>>24&15]|r[E>>>20&15]|i[E>>>16&15]|s[E>>>12&15]|o[E>>>8&15]|u[E>>>4&15],N=a[S>>>28]|f[S>>>24&15]|l[S>>>20&15]|c[S>>>16&15]|h[S>>>12&15]|p[S>>>8&15]|d[S>>>4&15];b=(N>>>16^T)&65535,m[y++]=T^b,m[y++]=N^b<<16}}return m}var t=[16843776,0,65536,16843780,16842756,66564,4,65536,1024,16843776,16843780,1024,16778244,16842756,16777216,4,1028,16778240,16778240,66560,66560,16842752,16842752,16778244,65540,16777220,16777220,65540,0,1028,66564,16777216,65536,16843780,4,16842752,16843776,16777216,16777216,1024,16842756,65536,66560,16777220,1024,4,16778244,66564,16843780,65540,16842752,16778244,16777220,1028,66564,16843776,1028,16778240,16778240,0,65540,66560,0,16842756],n=[-2146402272,-2147450880,32768,1081376,1048576,32,-2146435040,-2147450848,-2147483616,-2146402272,-2146402304,-2147483648,-2147450880,1048576,32,-2146435040,1081344,1048608,-2147450848,0,-2147483648,32768,1081376,-2146435072,1048608,-2147483616,0,1081344,32800,-2146402304,-2146435072,32800,0,1081376,-2146435040,1048576,-2147450848,-2146435072,-2146402304,32768,-2146435072,-2147450880,32,-2146402272,1081376,32,32768,-2147483648,32800,-2146402304,1048576,-2147483616,1048608,-2147450848,-2147483616,1048608,1081344,0,-2147450880,32800,-2147483648,-2146435040,-2146402272,1081344],r=[520,134349312,0,134348808,134218240,0,131592,134218240,131080,134217736,134217736,131072,134349320,131080,134348800,520,134217728,8,134349312,512,131584,134348800,134348808,131592,134218248,131584,131072,134218248,8,134349320,512,134217728,134349312,134217728,131080,520,131072,134349312,134218240,0,512,131080,134349320,134218240,134217736,512,0,134348808,134218248,131072,134217728,134349320,8,131592,131584,134217736,134348800,134218248,520,134348800,131592,8,134348808,131584],i=[8396801,8321,8321,128,8396928,8388737,8388609,8193,0,8396800,8396800,8396929,129,0,8388736,8388609,1,8192,8388608,8396801,128,8388608,8193,8320,8388737,1,8320,8388736,8192,8396928,8396929,129,8388736,8388609,8396800,8396929,129,0,0,8396800,8320,8388736,8388737,1,8396801,8321,8321,128,8396929,129,1,8192,8388609,8193,8396928,8388737,8193,8320,8388608,8396801,128,8388608,8192,8396928],s=[256,34078976,34078720,1107296512,524288,256,1073741824,34078720,1074266368,524288,33554688,1074266368,1107296512,1107820544,524544,1073741824,33554432,1074266112,1074266112,0,1073742080,1107820800,1107820800,33554688,1107820544,1073742080,0,1107296256,34078976,33554432,1107296256,524544,524288,1107296512,256,33554432,1073741824,34078720,1107296512,1074266368,33554688,1073741824,1107820544,34078976,1074266368,256,33554432,1107820544,1107820800,524544,1107296256,1107820800,34078720,0,1074266112,1107296256,524544,33554688,1073742080,524288,0,1074266112,34078976,1073742080],o=[536870928,541065216,16384,541081616,541065216,16,541081616,4194304,536887296,4210704,4194304,536870928,4194320,536887296,536870912,16400,0,4194320,536887312,16384,4210688,536887312,16,541065232,541065232,0,4210704,541081600,16400,4210688,541081600,536870912,536887296,16,541065232,4210688,541081616,4194304,16400,536870928,4194304,536887296,536870912,16400,536870928,541081616,4210688,541065216,4210704,541081600,0,541065232,16,16384,541065216,4210704,16384,4194320,536887312,0,541081600,536870912,4194320,536887312],u=[2097152,69206018,67110914,0,2048,67110914,2099202,69208064,69208066,2097152,0,67108866,2,67108864,69206018,2050,67110912,2099202,2097154,67110912,67108866,69206016,69208064,2097154,69206016,2048,2050,69208066,2099200,2,67108864,2099200,67108864,2099200,2097152,67110914,67110914,69206018,69206018,2,2097154,67108864,67110912,2097152,69208064,2050,2099202,69208064,2050,67108866,69208066,69206016,2099200,0,2,69208066,0,2099202,69206016,2048,67108866,67110912,2048,2097154],a=[268439616,4096,262144,268701760,268435456,268439616,64,268435456,262208,268697600,268701760,266240,268701696,266304,4096,64,268697600,268435520,268439552,4160,266240,262208,268697664,268701696,4160,0,0,268697664,268435520,268439552,266304,262144,266304,262144,268701696,4096,64,268697664,4096,266304,268439552,64,268435520,268697600,268697664,268435456,262144,268439616,0,268701760,262208,268435520,268697600,268439552,268439616,0,268701760,266240,266240,4160,4160,262208,268435456,268701696],l=function(l,c){typeof l=="string"&&(l.length===8||l.length===24)&&(l=e.util.createBuffer(l));var h=f(l),p=1,d=0,v=0,m=0,g=0,y=!1,b=null,w=null,E=h.length===32?3:9,S;E===3?S=c?[0,32,2]:[30,-2,-2]:S=c?[0,32,2,62,30,-2,64,96,2]:[94,62,-2,32,64,2,30,-2,-2];var x=null;return x={start:function(t,n){t?(typeof t=="string"&&t.length===8&&(t=e.util.createBuffer(t)),p=1,d=t.getInt32(),m=t.getInt32()):p=0,y=!1,b=e.util.createBuffer(),w=n||e.util.createBuffer(),x.output=w},update:function(e){y||b.putBuffer(e);while(b.length()>=8){var f,l=b.getInt32(),x=b.getInt32();p===1&&(c?(l^=d,x^=m):(v=d,g=m,d=l,m=x)),f=(l>>>4^x)&252645135,x^=f,l^=f<<4,f=(l>>>16^x)&65535,x^=f,l^=f<<16,f=(x>>>2^l)&858993459,l^=f,x^=f<<2,f=(x>>>8^l)&16711935,l^=f,x^=f<<8,f=(l>>>1^x)&1431655765,x^=f,l^=f<<1,l=l<<1|l>>>31,x=x<<1|x>>>31;for(var T=0;T<E;T+=3){var N=S[T+1],C=S[T+2];for(var k=S[T];k!=N;k+=C){var L=x^h[k],A=(x>>>4|x<<28)^h[k+1];f=l,l=x,x=f^(n[L>>>24&63]|i[L>>>16&63]|o[L>>>8&63]|a[L&63]|t[A>>>24&63]|r[A>>>16&63]|s[A>>>8&63]|u[A&63])}f=l,l=x,x=f}l=l>>>1|l<<31,x=x>>>1|x<<31,f=(l>>>1^x)&1431655765,x^=f,l^=f<<1,f=(x>>>8^l)&16711935,l^=f,x^=f<<8,f=(x>>>2^l)&858993459,l^=f,x^=f<<2,f=(l>>>16^x)&65535,x^=f,l^=f<<16,f=(l>>>4^x)&252645135,x^=f,l^=f<<4,p===1&&(c?(d=l,m=x):(l^=v,x^=g)),w.putInt32(l),w.putInt32(x)}},finish:function(e){var t=!0;if(c)if(e)t=e(8,b,!c);else{var n=b.length()===8?8:8-b.length();b.fillWithByte(n,n)}t&&(y=!0,x.update());if(!c){t=b.length()===0;if(t)if(e)t=e(8,w,!c);else{var r=w.length(),i=w.at(r-1);i>r?t=!1:w.truncate(i)}}return t}},x};e.des=e.des||{},e.des.startEncrypting=function(e,t,n){var r=l(e,!0);return r.start(t,n),r},e.des.createEncryptionCipher=function(e){return l(e,!0)},e.des.startDecrypting=function(e,t,n){var r=l(e,!1);return r.start(t,n),r},e.des.createDecryptionCipher=function(e){return l(e,!1)}}var r="des";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/des",["require","module","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){var t=e.pkcs5=e.pkcs5||{};e.pbkdf2=t.pbkdf2=function(t,n,r,i,s){if(typeof s=="undefined"||s===null)s=e.md.sha1.create();var o=s.digestLength;if(i>4294967295*o)throw{message:"Derived key is too long."};var u=Math.ceil(i/o),a=i-(u-1)*o,f=e.hmac.create();f.start(s,t);var l="",c,h,p;for(var d=1;d<=u;++d){f.start(null,null),f.update(n),f.update(e.util.int32ToBytes(d)),c=p=f.digest().getBytes();for(var v=2;v<=r;++v)f.start(null,null),f.update(p),h=f.digest().getBytes(),c=e.util.xorBytes(c,h,o),p=h;l+=d<u?c:c.substr(0,a)}return l}}var r="pbkdf2";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/pbkdf2",["require","module","./hmac","./md","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){var n=typeof process!="undefined"&&process.versions&&process.versions.node,r=null;!e.disableNativeCode&&n&&(r=t("crypto"));var i=e.prng=e.prng||{};i.create=function(t){function u(e){if(n.pools[0].messageLength>=32)return f(),e();var t=32-n.pools[0].messageLength<<5;n.seedFile(t,function(t,r){if(t)return e(t);n.collect(r),f(),e()})}function a(){if(n.pools[0].messageLength>=32)return f();var e=32-n.pools[0].messageLength<<5;n.collect(n.seedFileSync(e)),f()}function f(){var t=e.md.sha1.create();t.update(n.pools[0].digest().getBytes()),n.pools[0].start();var r=1;for(var i=1;i<32;++i)r=r===31?2147483648:r<<2,r%n.reseeds===0&&(t.update(n.pools[i].digest().getBytes()),n.pools[i].start());var s=t.digest().getBytes();t.start(),t.update(s);var o=t.digest().getBytes();n.key=n.plugin.formatKey(s),n.seed=n.plugin.formatSeed(o),++n.reseeds,n.generated=0,n.time=+(new Date)}function l(t){var n=null;if(typeof window!="undefined"){var r=window.crypto||window.msCrypto;r&&r.getRandomValues&&(n=function(e){return r.getRandomValues(e)})}var i=e.util.createBuffer();if(n)while(i.length()<t){var s=Math.max(1,Math.min(t-i.length(),65536)/4),o=new Uint32Array(Math.floor(s));try{n(o);for(var u=0;u<o.length;++u)i.putInt32(o[u])}catch(a){if(!(typeof QuotaExceededError!="undefined"&&a instanceof QuotaExceededError))throw a}}if(i.length()<t){var f,l,c,h=Math.floor(Math.random()*65536);while(i.length()<t){l=16807*(h&65535),f=16807*(h>>16),l+=(f&32767)<<16,l+=f>>15,l=(l&2147483647)+(l>>31),h=l&4294967295;for(var u=0;u<3;++u)c=h>>>(u<<3),c^=Math.floor(Math.random()*256),i.putByte(String.fromCharCode(c&255))}}return i.getBytes(t)}var n={plugin:t,key:null,seed:null,time:null,reseeds:0,generated:0},i=t.md,s=new Array(32);for(var o=0;o<32;++o)s[o]=i.create();return n.pools=s,n.pool=0,n.generate=function(t,r){function l(c){if(c)return r(c);if(f.length()>=t)return r(null,f.getBytes(t));if(n.generated>=1048576){var h=+(new Date);if(n.time===null||h-n.time>100)n.key=null}if(n.key===null)return u(l);var p=i(n.key,n.seed);n.generated+=p.length,f.putBytes(p),n.key=o(i(n.key,s(n.seed))),n.seed=a(i(n.key,n.seed)),e.util.setImmediate(l)}if(!r)return n.generateSync(t);var i=n.plugin.cipher,s=n.plugin.increment,o=n.plugin.formatKey,a=n.plugin.formatSeed,f=e.util.createBuffer();l()},n.generateSync=function(t){var r=n.plugin.cipher,i=n.plugin.increment,s=n.plugin.formatKey,o=n.plugin.formatSeed,u=e.util.createBuffer();while(u.length()<t){if(n.generated>=1048576){var f=+(new Date);if(n.time===null||f-n.time>100)n.key=null}n.key===null&&a();var l=r(n.key,n.seed);n.generated+=l.length,u.putBytes(l),n.key=s(r(n.key,i(n.seed))),n.seed=o(r(n.key,n.seed))}return u.getBytes(t)},r?(n.seedFile=function(e,t){r.randomBytes(e,function(e,n){if(e)return t(e);t(null,n.toString())})},n.seedFileSync=function(e){return r.randomBytes(e).toString()}):(n.seedFile=function(e,t){try{t(null,l(e))}catch(n){t(n)}},n.seedFileSync=l),n.collect=function(e){var t=e.length;for(var r=0;r<t;++r)n.pools[n.pool].update(e.substr(r,1)),n.pool=n.pool===31?0:n.pool+1},n.collectInt=function(e,t){var r="";for(var i=0;i<t;i+=8)r+=String.fromCharCode(e>>i&255);n.collect(r)},n.registerWorker=function(e){if(e===self)n.seedFile=function(e,t){function n(e){var r=e.data;r.forge&&r.forge.prng&&(self.removeEventListener("message",n),t(r.forge.prng.err,r.forge.prng.bytes))}self.addEventListener("message",n),self.postMessage({forge:{prng:{needed:e}}})};else{function t(t){var r=t.data;r.forge&&r.forge.prng&&n.seedFile(r.forge.prng.needed,function(t,n){e.postMessage({forge:{prng:{err:t,bytes:n}}})})}e.addEventListener("message",t)}},n}}var r="prng";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/prng",["require","module","./md","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){if(e.random&&e.random.getBytes)return;(function(t){var n={},r=new Array(4),i=e.util.createBuffer();n.formatKey=function(t){var n=e.util.createBuffer(t);return t=new Array(4),t[0]=n.getInt32(),t[1]=n.getInt32(),t[2]=n.getInt32(),t[3]=n.getInt32(),e.aes._expandKey(t,!1)},n.formatSeed=function(t){var n=e.util.createBuffer(t);return t=new Array(4),t[0]=n.getInt32(),t[1]=n.getInt32(),t[2]=n.getInt32(),t[3]=n.getInt32(),t},n.cipher=function(t,n){return e.aes._updateBlock(t,n,r,!1),i.putInt32(r[0]),i.putInt32(r[1]),i.putInt32(r[2]),i.putInt32(r[3]),i.getBytes()},n.increment=function(e){return++e[3],e},n.md=e.md.sha1;var s=e.prng.create(n),o=typeof process!="undefined"&&process.versions&&process.versions.node,u=null;if(typeof window!="undefined"){var a=window.crypto||window.msCrypto;a&&a.getRandomValues&&(u=function(e){return a.getRandomValues(e)})}if(e.disableNativeCode||!o&&!u){typeof window=="undefined"||window.document===undefined,s.collectInt(+(new Date),32);if(typeof navigator!="undefined"){var f="";for(var l in navigator)try{typeof navigator[l]=="string"&&(f+=navigator[l])}catch(c){}s.collect(f),f=null}t&&(t().mousemove(function(e){s.collectInt(e.clientX,16),s.collectInt(e.clientY,16)}),t().keypress(function(e){s.collectInt(e.charCode,8)}))}if(!e.random)e.random=s;else for(var l in s)e.random[l]=s[l];e.random.getBytes=function(t,n){return e.random.generate(t,n)},e.random.getBytesSync=function(t){return e.random.generate(t)}})(typeof jQuery!="undefined"?jQuery:null)}var r="random";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/random",["require","module","./aes","./md","./prng","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){var t=[217,120,249,196,25,221,181,237,40,233,253,121,74,160,216,157,198,126,55,131,43,118,83,142,98,76,100,136,68,139,251,162,23,154,89,245,135,179,79,19,97,69,109,141,9,129,125,50,189,143,64,235,134,183,123,11,240,149,33,34,92,107,78,130,84,214,101,147,206,96,178,28,115,86,192,20,167,140,241,220,18,117,202,31,59,190,228,209,66,61,212,48,163,60,182,38,111,191,14,218,70,105,7,87,39,242,29,155,188,148,67,3,248,17,199,246,144,239,62,231,6,195,213,47,200,102,30,215,8,232,234,222,128,82,238,247,132,170,114,172,53,77,106,42,150,26,210,113,90,21,73,116,75,159,208,94,4,24,164,236,194,224,65,110,15,81,203,204,36,145,175,80,161,244,112,57,153,124,58,133,35,184,180,122,252,2,54,91,37,85,151,49,45,93,250,152,227,138,146,174,5,223,41,16,103,108,186,201,211,0,230,207,225,158,168,44,99,22,1,63,88,226,137,169,13,56,52,27,171,51,255,176,187,72,12,95,185,177,205,46,197,243,219,71,229,165,156,119,10,166,32,104,254,127,193,173],n=[1,2,3,5],r=function(e,t){return e<<t&65535|(e&65535)>>16-t},i=function(e,t){return(e&65535)>>t|e<<16-t&65535};e.rc2=e.rc2||{},e.rc2.expandKey=function(n,r){typeof n=="string"&&(n=e.util.createBuffer(n)),r=r||128;var i=n,s=n.length(),o=r,u=Math.ceil(o/8),a=255>>(o&7),f;for(f=s;f<128;f++)i.putByte(t[i.at(f-1)+i.at(f-s)&255]);i.setAt(128-u,t[i.at(128-u)&a]);for(f=127-u;f>=0;f--)i.setAt(f,t[i.at(f+1)^i.at(f+u)]);return i};var s=function(t,s,o){var u=!1,a=null,f=null,l=null,c,h,p,d,v=[];t=e.rc2.expandKey(t,s);for(p=0;p<64;p++)v.push(t.getInt16Le());o?(c=function(e){for(p=0;p<4;p++)e[p]+=v[d]+(e[(p+3)%4]&e[(p+2)%4])+(~e[(p+3)%4]&e[(p+1)%4]),e[p]=r(e[p],n[p]),d++},h=function(e){for(p=0;p<4;p++)e[p]+=v[e[(p+3)%4]&63]}):(c=function(e){for(p=3;p>=0;p--)e[p]=i(e[p],n[p]),e[p]-=v[d]+(e[(p+3)%4]&e[(p+2)%4])+(~e[(p+3)%4]&e[(p+1)%4]),d--},h=function(e){for(p=3;p>=0;p--)e[p]-=v[e[(p+3)%4]&63]});var m=function(e){var t=[];for(p=0;p<4;p++){var n=a.getInt16Le();l!==null&&(o?n^=l.getInt16Le():l.putInt16Le(n)),t.push(n&65535)}d=o?0:63;for(var r=0;r<e.length;r++)for(var i=0;i<e[r][0];i++)e[r][1](t);for(p=0;p<4;p++)l!==null&&(o?l.putInt16Le(t[p]):t[p]^=l.getInt16Le()),f.putInt16Le(t[p])},g=null;return g={start:function(t,n){t&&typeof t=="string"&&(t=e.util.createBuffer(t)),u=!1,a=e.util.createBuffer(),f=n||new e.util.createBuffer,l=t,g.output=f},update:function(e){u||a.putBuffer(e);while(a.length()>=8)m([[5,c],[1,h],[6,c],[1,h],[5,c]])},finish:function(e){var t=!0;if(o)if(e)t=e(8,a,!o);else{var n=a.length()===8?8:8-a.length();a.fillWithByte(n,n)}t&&(u=!0,g.update());if(!o){t=a.length()===0;if(t)if(e)t=e(8,f,!o);else{var r=f.length(),i=f.at(r-1);i>r?t=!1:f.truncate(i)}}return t}},g};e.rc2.startEncrypting=function(t,n,r){var i=e.rc2.createEncryptionCipher(t,128);return i.start(n,r),i},e.rc2.createEncryptionCipher=function(e,t){return s(e,t,!0)},e.rc2.startDecrypting=function(t,n,r){var i=e.rc2.createDecryptionCipher(t,128);return i.start(n,r),i},e.rc2.createDecryptionCipher=function(e,t){return s(e,t,!1)}}var r="rc2";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/rc2",["require","module","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){function i(e,t,n){this.data=[],e!=null&&("number"==typeof e?this.fromNumber(e,t,n):t==null&&"string"!=typeof e?this.fromString(e,256):this.fromString(e,t))}function s(){return new i(null)}function o(e,t,n,r,i,s){while(--s>=0){var o=t*this.data[e++]+n.data[r]+i;i=Math.floor(o/67108864),n.data[r++]=o&67108863}return i}function u(e,t,n,r,i,s){var o=t&32767,u=t>>15;while(--s>=0){var a=this.data[e]&32767,f=this.data[e++]>>15,l=u*a+f*o;a=o*a+((l&32767)<<15)+n.data[r]+(i&1073741823),i=(a>>>30)+(l>>>15)+u*f+(i>>>30),n.data[r++]=a&1073741823}return i}function a(e,t,n,r,i,s){var o=t&16383,u=t>>14;while(--s>=0){var a=this.data[e]&16383,f=this.data[e++]>>14,l=u*a+f*o;a=o*a+((l&16383)<<14)+n.data[r]+i,i=(a>>28)+(l>>14)+u*f,n.data[r++]=a&268435455}return i}function d(e){return l.charAt(e)}function v(e,t){var n=c[e.charCodeAt(t)];return n==null?-1:n}function m(e){for(var t=this.t-1;t>=0;--t)e.data[t]=this.data[t];e.t=this.t,e.s=this.s}function g(e){this.t=1,this.s=e<0?-1:0,e>0?this.data[0]=e:e<-1?this.data[0]=e+this.DV:this.t=0}function y(e){var t=s();return t.fromInt(e),t}function b(e,t){var n;if(t==16)n=4;else if(t==8)n=3;else if(t==256)n=8;else if(t==2)n=1;else if(t==32)n=5;else{if(t!=4){this.fromRadix(e,t);return}n=2}this.t=0,this.s=0;var r=e.length,s=!1,o=0;while(--r>=0){var u=n==8?e[r]&255:v(e,r);if(u<0){e.charAt(r)=="-"&&(s=!0);continue}s=!1,o==0?this.data[this.t++]=u:o+n>this.DB?(this.data[this.t-1]|=(u&(1<<this.DB-o)-1)<<o,this.data[this.t++]=u>>this.DB-o):this.data[this.t-1]|=u<<o,o+=n,o>=this.DB&&(o-=this.DB)}n==8&&(e[0]&128)!=0&&(this.s=-1,o>0&&(this.data[this.t-1]|=(1<<this.DB-o)-1<<o)),this.clamp(),s&&i.ZERO.subTo(this,this)}function w(){var e=this.s&this.DM;while(this.t>0&&this.data[this.t-1]==e)--this.t}function E(e){if(this.s<0)return"-"+this.negate().toString(e);var t;if(e==16)t=4;else if(e==8)t=3;else if(e==2)t=1;else if(e==32)t=5;else{if(e!=4)return this.toRadix(e);t=2}var n=(1<<t)-1,r,i=!1,s="",o=this.t,u=this.DB-o*this.DB%t;if(o-->0){u<this.DB&&(r=this.data[o]>>u)>0&&(i=!0,s=d(r));while(o>=0)u<t?(r=(this.data[o]&(1<<u)-1)<<t-u,r|=this.data[--o]>>(u+=this.DB-t)):(r=this.data[o]>>(u-=t)&n,u<=0&&(u+=this.DB,--o)),r>0&&(i=!0),i&&(s+=d(r))}return i?s:"0"}function S(){var e=s();return i.ZERO.subTo(this,e),e}function x(){return this.s<0?this.negate():this}function T(e){var t=this.s-e.s;if(t!=0)return t;var n=this.t;t=n-e.t;if(t!=0)return this.s<0?-t:t;while(--n>=0)if((t=this.data[n]-e.data[n])!=0)return t;return 0}function N(e){var t=1,n;return(n=e>>>16)!=0&&(e=n,t+=16),(n=e>>8)!=0&&(e=n,t+=8),(n=e>>4)!=0&&(e=n,t+=4),(n=e>>2)!=0&&(e=n,t+=2),(n=e>>1)!=0&&(e=n,t+=1),t}function C(){return this.t<=0?0:this.DB*(this.t-1)+N(this.data[this.t-1]^this.s&this.DM)}function k(e,t){var n;for(n=this.t-1;n>=0;--n)t.data[n+e]=this.data[n];for(n=e-1;n>=0;--n)t.data[n]=0;t.t=this.t+e,t.s=this.s}function L(e,t){for(var n=e;n<this.t;++n)t.data[n-e]=this.data[n];t.t=Math.max(this.t-e,0),t.s=this.s}function A(e,t){var n=e%this.DB,r=this.DB-n,i=(1<<r)-1,s=Math.floor(e/this.DB),o=this.s<<n&this.DM,u;for(u=this.t-1;u>=0;--u)t.data[u+s+1]=this.data[u]>>r|o,o=(this.data[u]&i)<<n;for(u=s-1;u>=0;--u)t.data[u]=0;t.data[s]=o,t.t=this.t+s+1,t.s=this.s,t.clamp()}function O(e,t){t.s=this.s;var n=Math.floor(e/this.DB);if(n>=this.t){t.t=0;return}var r=e%this.DB,i=this.DB-r,s=(1<<r)-1;t.data[0]=this.data[n]>>r;for(var o=n+1;o<this.t;++o)t.data[o-n-1]|=(this.data[o]&s)<<i,t.data[o-n]=this.data[o]>>r;r>0&&(t.data[this.t-n-1]|=(this.s&s)<<i),t.t=this.t-n,t.clamp()}function M(e,t){var n=0,r=0,i=Math.min(e.t,this.t);while(n<i)r+=this.data[n]-e.data[n],t.data[n++]=r&this.DM,r>>=this.DB;if(e.t<this.t){r-=e.s;while(n<this.t)r+=this.data[n],t.data[n++]=r&this.DM,r>>=this.DB;r+=this.s}else{r+=this.s;while(n<e.t)r-=e.data[n],t.data[n++]=r&this.DM,r>>=this.DB;r-=e.s}t.s=r<0?-1:0,r<-1?t.data[n++]=this.DV+r:r>0&&(t.data[n++]=r),t.t=n,t.clamp()}function _(e,t){var n=this.abs(),r=e.abs(),s=n.t;t.t=s+r.t;while(--s>=0)t.data[s]=0;for(s=0;s<r.t;++s)t.data[s+n.t]=n.am(0,r.data[s],t,s,0,n.t);t.s=0,t.clamp(),this.s!=e.s&&i.ZERO.subTo(t,t)}function D(e){var t=this.abs(),n=e.t=2*t.t;while(--n>=0)e.data[n]=0;for(n=0;n<t.t-1;++n){var r=t.am(n,t.data[n],e,2*n,0,1);(e.data[n+t.t]+=t.am(n+1,2*t.data[n],e,2*n+1,r,t.t-n-1))>=t.DV&&(e.data[n+t.t]-=t.DV,e.data[n+t.t+1]=1)}e.t>0&&(e.data[e.t-1]+=t.am(n,t.data[n],e,2*n,0,1)),e.s=0,e.clamp()}function P(e,t,n){var r=e.abs();if(r.t<=0)return;var o=this.abs();if(o.t<r.t){t!=null&&t.fromInt(0),n!=null&&this.copyTo(n);return}n==null&&(n=s());var u=s(),a=this.s,f=e.s,l=this.DB-N(r.data[r.t-1]);l>0?(r.lShiftTo(l,u),o.lShiftTo(l,n)):(r.copyTo(u),o.copyTo(n));var c=u.t,h=u.data[c-1];if(h==0)return;var p=h*(1<<this.F1)+(c>1?u.data[c-2]>>this.F2:0),d=this.FV/p,v=(1<<this.F1)/p,m=1<<this.F2,g=n.t,y=g-c,b=t==null?s():t;u.dlShiftTo(y,b),n.compareTo(b)>=0&&(n.data[n.t++]=1,n.subTo(b,n)),i.ONE.dlShiftTo(c,b),b.subTo(u,u);while(u.t<c)u.data[u.t++]=0;while(--y>=0){var w=n.data[--g]==h?this.DM:Math.floor(n.data[g]*d+(n.data[g-1]+m)*v);if((n.data[g]+=u.am(0,w,n,y,0,c))<w){u.dlShiftTo(y,b),n.subTo(b,n);while(n.data[g]<--w)n.subTo(b,n)}}t!=null&&(n.drShiftTo(c,t),a!=f&&i.ZERO.subTo(t,t)),n.t=c,n.clamp(),l>0&&n.rShiftTo(l,n),a<0&&i.ZERO.subTo(n,n)}function H(e){var t=s();return this.abs().divRemTo(e,null,t),this.s<0&&t.compareTo(i.ZERO)>0&&e.subTo(t,t),t}function B(e){this.m=e}function j(e){return e.s<0||e.compareTo(this.m)>=0?e.mod(this.m):e}function F(e){return e}function I(e){e.divRemTo(this.m,null,e)}function q(e,t,n){e.multiplyTo(t,n),this.reduce(n)}function R(e,t){e.squareTo(t),this.reduce(t)}function U(){if(this.t<1)return 0;var e=this.data[0];if((e&1)==0)return 0;var t=e&3;return t=t*(2-(e&15)*t)&15,t=t*(2-(e&255)*t)&255,t=t*(2-((e&65535)*t&65535))&65535,t=t*(2-e*t%this.DV)%this.DV,t>0?this.DV-t:-t}function z(e){this.m=e,this.mp=e.invDigit(),this.mpl=this.mp&32767,this.mph=this.mp>>15,this.um=(1<<e.DB-15)-1,this.mt2=2*e.t}function W(e){var t=s();return e.abs().dlShiftTo(this.m.t,t),t.divRemTo(this.m,null,t),e.s<0&&t.compareTo(i.ZERO)>0&&this.m.subTo(t,t),t}function X(e){var t=s();return e.copyTo(t),this.reduce(t),t}function V(e){while(e.t<=this.mt2)e.data[e.t++]=0;for(var t=0;t<this.m.t;++t){var n=e.data[t]&32767,r=n*this.mpl+((n*this.mph+(e.data[t]>>15)*this.mpl&this.um)<<15)&e.DM;n=t+this.m.t,e.data[n]+=this.m.am(0,r,e,t,0,this.m.t);while(e.data[n]>=e.DV)e.data[n]-=e.DV,e.data[++n]++}e.clamp(),e.drShiftTo(this.m.t,e),e.compareTo(this.m)>=0&&e.subTo(this.m,e)}function $(e,t){e.squareTo(t),this.reduce(t)}function J(e,t,n){e.multiplyTo(t,n),this.reduce(n)}function K(){return(this.t>0?this.data[0]&1:this.s)==0}function Q(e,t){if(e>4294967295||e<1)return i.ONE;var n=s(),r=s(),o=t.convert(this),u=N(e)-1;o.copyTo(n);while(--u>=0){t.sqrTo(n,r);if((e&1<<u)>0)t.mulTo(r,o,n);else{var a=n;n=r,r=a}}return t.revert(n)}function G(e,t){var n;return e<256||t.isEven()?n=new B(t):n=new z(t),this.exp(e,n)}function Y(){var e=s();return this.copyTo(e),e}function Z(){if(this.s<0){if(this.t==1)return this.data[0]-this.DV;if(this.t==0)return-1}else{if(this.t==1)return this.data[0];if(this.t==0)return 0}return(this.data[1]&(1<<32-this.DB)-1)<<this.DB|this.data[0]}function et(){return this.t==0?this.s:this.data[0]<<24>>24}function tt(){return this.t==0?this.s:this.data[0]<<16>>16}function nt(e){return Math.floor(Math.LN2*this.DB/Math.log(e))}function rt(){return this.s<0?-1:this.t<=0||this.t==1&&this.data[0]<=0?0:1}function it(e){e==null&&(e=10);if(this.signum()==0||e<2||e>36)return"0";var t=this.chunkSize(e),n=Math.pow(e,t),r=y(n),i=s(),o=s(),u="";this.divRemTo(r,i,o);while(i.signum()>0)u=(n+o.intValue()).toString(e).substr(1)+u,i.divRemTo(r,i,o);return o.intValue().toString(e)+u}function st(e,t){this.fromInt(0),t==null&&(t=10);var n=this.chunkSize(t),r=Math.pow(t,n),s=!1,o=0,u=0;for(var a=0;a<e.length;++a){var f=v(e,a);if(f<0){e.charAt(a)=="-"&&this.signum()==0&&(s=!0);continue}u=t*u+f,++o>=n&&(this.dMultiply(r),this.dAddOffset(u,0),o=0,u=0)}o>0&&(this.dMultiply(Math.pow(t,o)),this.dAddOffset(u,0)),s&&i.ZERO.subTo(this,this)}function ot(e,t,n){if("number"==typeof t)if(e<2)this.fromInt(1);else{this.fromNumber(e,n),this.testBit(e-1)||this.bitwiseTo(i.ONE.shiftLeft(e-1),dt,this),this.isEven()&&this.dAddOffset(1,0);while(!this.isProbablePrime(t))this.dAddOffset(2,0),this.bitLength()>e&&this.subTo(i.ONE.shiftLeft(e-1),this)}else{var r=new Array,s=e&7;r.length=(e>>3)+1,t.nextBytes(r),s>0?r[0]&=(1<<s)-1:r[0]=0,this.fromString(r,256)}}function ut(){var e=this.t,t=new Array;t[0]=this.s;var n=this.DB-e*this.DB%8,r,i=0;if(e-->0){n<this.DB&&(r=this.data[e]>>n)!=(this.s&this.DM)>>n&&(t[i++]=r|this.s<<this.DB-n);while(e>=0){n<8?(r=(this.data[e]&(1<<n)-1)<<8-n,r|=this.data[--e]>>(n+=this.DB-8)):(r=this.data[e]>>(n-=8)&255,n<=0&&(n+=this.DB,--e)),(r&128)!=0&&(r|=-256),i==0&&(this.s&128)!=(r&128)&&++i;if(i>0||r!=this.s)t[i++]=r}}return t}function at(e){return this.compareTo(e)==0}function ft(e){return this.compareTo(e)<0?this:e}function lt(e){return this.compareTo(e)>0?this:e}function ct(e,t,n){var r,i,s=Math.min(e.t,this.t);for(r=0;r<s;++r)n.data[r]=t(this.data[r],e.data[r]);if(e.t<this.t){i=e.s&this.DM;for(r=s;r<this.t;++r)n.data[r]=t(this.data[r],i);n.t=this.t}else{i=this.s&this.DM;for(r=s;r<e.t;++r)n.data[r]=t(i,e.data[r]);n.t=e.t}n.s=t(this.s,e.s),n.clamp()}function ht(e,t){return e&t}function pt(e){var t=s();return this.bitwiseTo(e,ht,t),t}function dt(e,t){return e|t}function vt(e){var t=s();return this.bitwiseTo(e,dt,t),t}function mt(e,t){return e^t}function gt(e){var t=s();return this.bitwiseTo(e,mt,t),t}function yt(e,t){return e&~t}function bt(e){var t=s();return this.bitwiseTo(e,yt,t),t}function wt(){var e=s();for(var t=0;t<this.t;++t)e.data[t]=this.DM&~this.data[t];return e.t=this.t,e.s=~this.s,e}function Et(e){var t=s();return e<0?this.rShiftTo(-e,t):this.lShiftTo(e,t),t}function St(e){var t=s();return e<0?this.lShiftTo(-e,t):this.rShiftTo(e,t),t}function xt(e){if(e==0)return-1;var t=0;return(e&65535)==0&&(e>>=16,t+=16),(e&255)==0&&(e>>=8,t+=8),(e&15)==0&&(e>>=4,t+=4),(e&3)==0&&(e>>=2,t+=2),(e&1)==0&&++t,t}function Tt(){for(var e=0;e<this.t;++e)if(this.data[e]!=0)return e*this.DB+xt(this.data[e]);return this.s<0?this.t*this.DB:-1}function Nt(e){var t=0;while(e!=0)e&=e-1,++t;return t}function Ct(){var e=0,t=this.s&this.DM;for(var n=0;n<this.t;++n)e+=Nt(this.data[n]^t);return e}function kt(e){var t=Math.floor(e/this.DB);return t>=this.t?this.s!=0:(this.data[t]&1<<e%this.DB)!=0}function Lt(e,t){var n=i.ONE.shiftLeft(e);return this.bitwiseTo(n,t,n),n}function At(e){return this.changeBit(e,dt)}function Ot(e){return this.changeBit(e,yt)}function Mt(e){return this.changeBit(e,mt)}function _t(e,t){var n=0,r=0,i=Math.min(e.t,this.t);while(n<i)r+=this.data[n]+e.data[n],t.data[n++]=r&this.DM,r>>=this.DB;if(e.t<this.t){r+=e.s;while(n<this.t)r+=this.data[n],t.data[n++]=r&this.DM,r>>=this.DB;r+=this.s}else{r+=this.s;while(n<e.t)r+=e.data[n],t.data[n++]=r&this.DM,r>>=this.DB;r+=e.s}t.s=r<0?-1:0,r>0?t.data[n++]=r:r<-1&&(t.data[n++]=this.DV+r),t.t=n,t.clamp()}function Dt(e){var t=s();return this.addTo(e,t),t}function Pt(e){var t=s();return this.subTo(e,t),t}function Ht(e){var t=s();return this.multiplyTo(e,t),t}function Bt(e){var t=s();return this.divRemTo(e,t,null),t}function jt(e){var t=s();return this.divRemTo(e,null,t),t}function Ft(e){var t=s(),n=s();return this.divRemTo(e,t,n),new Array(t,n)}function It(e){this.data[this.t]=this.am(0,e-1,this,0,0,this.t),++this.t,this.clamp()}function qt(e,t){if(e==0)return;while(this.t<=t)this.data[this.t++]=0;this.data[t]+=e;while(this.data[t]>=this.DV)this.data[t]-=this.DV,++t>=this.t&&(this.data[this.t++]=0),++this.data[t]}function Rt(){}function Ut(e){return e}function zt(e,t,n){e.multiplyTo(t,n)}function Wt(e,t){e.squareTo(t)}function Xt(e){return this.exp(e,new Rt)}function Vt(e,t,n){var r=Math.min(this.t+e.t,t);n.s=0,n.t=r;while(r>0)n.data[--r]=0;var i;for(i=n.t-this.t;r<i;++r)n.data[r+this.t]=this.am(0,e.data[r],n,r,0,this.t);for(i=Math.min(e.t,t);r<i;++r)this.am(0,e.data[r],n,r,0,t-r);n.clamp()}function $t(e,t,n){--t;var r=n.t=this.t+e.t-t;n.s=0;while(--r>=0)n.data[r]=0;for(r=Math.max(t-this.t,0);r<e.t;++r)n.data[this.t+r-t]=this.am(t-r,e.data[r],n,0,0,this.t+r-t);n.clamp(),n.drShiftTo(1,n)}function Jt(e){this.r2=s(),this.q3=s(),i.ONE.dlShiftTo(2*e.t,this.r2),this.mu=this.r2.divide(e),this.m=e}function Kt(e){if(e.s<0||e.t>2*this.m.t)return e.mod(this.m);if(e.compareTo(this.m)<0)return e;var t=s();return e.copyTo(t),this.reduce(t),t}function Qt(e){return e}function Gt(e){e.drShiftTo(this.m.t-1,this.r2),e.t>this.m.t+1&&(e.t=this.m.t+1,e.clamp()),this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3),this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);while(e.compareTo(this.r2)<0)e.dAddOffset(1,this.m.t+1);e.subTo(this.r2,e);while(e.compareTo(this.m)>=0)e.subTo(this.m,e)}function Yt(e,t){e.squareTo(t),this.reduce(t)}function Zt(e,t,n){e.multiplyTo(t,n),this.reduce(n)}function en(e,t){var n=e.bitLength(),r,i=y(1),o;if(n<=0)return i;n<18?r=1:n<48?r=3:n<144?r=4:n<768?r=5:r=6,n<8?o=new B(t):t.isEven()?o=new Jt(t):o=new z(t);var u=new Array,a=3,f=r-1,l=(1<<r)-1;u[1]=o.convert(this);if(r>1){var c=s();o.sqrTo(u[1],c);while(a<=l)u[a]=s(),o.mulTo(c,u[a-2],u[a]),a+=2}var h=e.t-1,p,d=!0,v=s(),m;n=N(e.data[h])-1;while(h>=0){n>=f?p=e.data[h]>>n-f&l:(p=(e.data[h]&(1<<n+1)-1)<<f-n,h>0&&(p|=e.data[h-1]>>this.DB+n-f)),a=r;while((p&1)==0)p>>=1,--a;(n-=a)<0&&(n+=this.DB,--h);if(d)u[p].copyTo(i),d=!1;else{while(a>1)o.sqrTo(i,v),o.sqrTo(v,i),a-=2;a>0?o.sqrTo(i,v):(m=i,i=v,v=m),o.mulTo(v,u[p],i)}while(h>=0&&(e.data[h]&1<<n)==0)o.sqrTo(i,v),m=i,i=v,v=m,--n<0&&(n=this.DB-1,--h)}return o.revert(i)}function tn(e){var t=this.s<0?this.negate():this.clone(),n=e.s<0?e.negate():e.clone();if(t.compareTo(n)<0){var r=t;t=n,n=r}var i=t.getLowestSetBit(),s=n.getLowestSetBit();if(s<0)return t;i<s&&(s=i),s>0&&(t.rShiftTo(s,t),n.rShiftTo(s,n));while(t.signum()>0)(i=t.getLowestSetBit())>0&&t.rShiftTo(i,t),(i=n.getLowestSetBit())>0&&n.rShiftTo(i,n),t.compareTo(n)>=0?(t.subTo(n,t),t.rShiftTo(1,t)):(n.subTo(t,n),n.rShiftTo(1,n));return s>0&&n.lShiftTo(s,n),n}function nn(e){if(e<=0)return 0;var t=this.DV%e,n=this.s<0?e-1:0;if(this.t>0)if(t==0)n=this.data[0]%e;else for(var r=this.t-1;r>=0;--r)n=(t*n+this.data[r])%e;return n}function rn(e){var t=e.isEven();if(this.isEven()&&t||e.signum()==0)return i.ZERO;var n=e.clone(),r=this.clone(),s=y(1),o=y(0),u=y(0),a=y(1);while(n.signum()!=0){while(n.isEven()){n.rShiftTo(1,n);if(t){if(!s.isEven()||!o.isEven())s.addTo(this,s),o.subTo(e,o);s.rShiftTo(1,s)}else o.isEven()||o.subTo(e,o);o.rShiftTo(1,o)}while(r.isEven()){r.rShiftTo(1,r);if(t){if(!u.isEven()||!a.isEven())u.addTo(this,u),a.subTo(e,a);u.rShiftTo(1,u)}else a.isEven()||a.subTo(e,a);a.rShiftTo(1,a)}n.compareTo(r)>=0?(n.subTo(r,n),t&&s.subTo(u,s),o.subTo(a,o)):(r.subTo(n,r),t&&u.subTo(s,u),a.subTo(o,a))}return r.compareTo(i.ONE)!=0?i.ZERO:a.compareTo(e)>=0?a.subtract(e):a.signum()<0?(a.addTo(e,a),a.signum()<0?a.add(e):a):a}function un(e){var t,n=this.abs();if(n.t==1&&n.data[0]<=sn[sn.length-1]){for(t=0;t<sn.length;++t)if(n.data[0]==sn[t])return!0;return!1}if(n.isEven())return!1;t=1;while(t<sn.length){var r=sn[t],i=t+1;while(i<sn.length&&r<on)r*=sn[i++];r=n.modInt(r);while(t<i)if(r%sn[t++]==0)return!1}return n.millerRabin(e)}function an(e){var t=this.subtract(i.ONE),n=t.getLowestSetBit();if(n<=0)return!1;var r=t.shiftRight(n),s=fn(),o;for(var u=0;u<e;++u){do o=new i(this.bitLength(),s);while(o.compareTo(i.ONE)<=0||o.compareTo(t)>=0);var a=o.modPow(r,this);if(a.compareTo(i.ONE)!=0&&a.compareTo(t)!=0){var f=1;while(f++<n&&a.compareTo(t)!=0){a=a.modPowInt(2,this);if(a.compareTo(i.ONE)==0)return!1}if(a.compareTo(t)!=0)return!1}}return!0}function fn(){return{nextBytes:function(e){for(var t=0;t<e.length;++t)e[t]=Math.floor(Math.random()*255)}}}var t,n=0xdeadbeefcafe,r=(n&16777215)==15715070;typeof navigator=="undefined"?(i.prototype.am=a,t=28):r&&navigator.appName=="Microsoft Internet Explorer"?(i.prototype.am=u,t=30):r&&navigator.appName!="Netscape"?(i.prototype.am=o,t=26):(i.prototype.am=a,t=28),i.prototype.DB=t,i.prototype.DM=(1<<t)-1,i.prototype.DV=1<<t;var f=52;i.prototype.FV=Math.pow(2,f),i.prototype.F1=f-t,i.prototype.F2=2*t-f;var l="0123456789abcdefghijklmnopqrstuvwxyz",c=new Array,h,p;h="0".charCodeAt(0);for(p=0;p<=9;++p)c[h++]=p;h="a".charCodeAt(0);for(p=10;p<36;++p)c[h++]=p;h="A".charCodeAt(0);for(p=10;p<36;++p)c[h++]=p;B.prototype.convert=j,B.prototype.revert=F,B.prototype.reduce=I,B.prototype.mulTo=q,B.prototype.sqrTo=R,z.prototype.convert=W,z.prototype.revert=X,z.prototype.reduce=V,z.prototype.mulTo=J,z.prototype.sqrTo=$,i.prototype.copyTo=m,i.prototype.fromInt=g,i.prototype.fromString=b,i.prototype.clamp=w,i.prototype.dlShiftTo=k,i.prototype.drShiftTo=L,i.prototype.lShiftTo=A,i.prototype.rShiftTo=O,i.prototype.subTo=M,i.prototype.multiplyTo=_,i.prototype.squareTo=D,i.prototype.divRemTo=P,i.prototype.invDigit=U,i.prototype.isEven=K,i.prototype.exp=Q,i.prototype.toString=E,i.prototype.negate=S,i.prototype.abs=x,i.prototype.compareTo=T,i.prototype.bitLength=C,i.prototype.mod=H,i.prototype.modPowInt=G,i.ZERO=y(0),i.ONE=y(1),Rt.prototype.convert=Ut,Rt.prototype.revert=Ut,Rt.prototype.mulTo=zt,Rt.prototype.sqrTo=Wt,Jt.prototype.convert=Kt,Jt.prototype.revert=Qt,Jt.prototype.reduce=Gt,Jt.prototype.mulTo=Zt,Jt.prototype.sqrTo=Yt;var sn=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509],on=(1<<26)/sn[sn.length-1];i.prototype.chunkSize=nt,i.prototype.toRadix=it,i.prototype.fromRadix=st,i.prototype.fromNumber=ot,i.prototype.bitwiseTo=ct,i.prototype.changeBit=Lt,i.prototype.addTo=_t,i.prototype.dMultiply=It,i.prototype.dAddOffset=qt,i.prototype.multiplyLowerTo=Vt,i.prototype.multiplyUpperTo=$t,i.prototype.modInt=nn,i.prototype.millerRabin=an,i.prototype.clone=Y,i.prototype.intValue=Z,i.prototype.byteValue=et,i.prototype.shortValue=tt,i.prototype.signum=rt,i.prototype.toByteArray=ut,i.prototype.equals=at,i.prototype.min=ft,i.prototype.max=lt,i.prototype.and=pt,i.prototype.or=vt,i.prototype.xor=gt,i.prototype.andNot=bt,i.prototype.not=wt,i.prototype.shiftLeft=Et,i.prototype.shiftRight=St,i.prototype.getLowestSetBit=Tt,i.prototype.bitCount=Ct,i.prototype.testBit=kt,i.prototype.setBit=At,i.prototype.clearBit=Ot,i.prototype.flipBit=Mt,i.prototype.add=Dt,i.prototype.subtract=Pt,i.prototype.multiply=Ht,i.prototype.divide=Bt,i.prototype.remainder=jt,i.prototype.divideAndRemainder=Ft,i.prototype.modPow=en,i.prototype.modInverse=rn,i.prototype.pow=Xt,i.prototype.gcd=tn,i.prototype.isProbablePrime=un,e.jsbn=e.jsbn||{},e.jsbn.BigInteger=i}var r="jsbn";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/jsbn",["require","module"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){function n(e,t,n){var r="",i=Math.ceil(t/n.digestLength);for(var s=0;s<i;++s){var o=String.fromCharCode(s>>24&255,s>>16&255,s>>8&255,s&255);n.start(),n.update(e+o),r+=n.digest().getBytes()}return r.substring(0,t)}var t=e.pkcs1=e.pkcs1||{};t.encode_rsa_oaep=function(t,r,i){var s=undefined,o=undefined,u=undefined;typeof i=="string"?(s=i,o=arguments[3]||undefined,u=arguments[4]||undefined):i&&(s=i.label||undefined,o=i.seed||undefined,u=i.md||undefined),u?u.start():u=e.md.sha1.create();var a=Math.ceil(t.n.bitLength()/8),f=a-2*u.digestLength-2;if(r.length>f)throw{message:"RSAES-OAEP input message length is too long.",length:r.length,maxLength:f};s||(s=""),u.update(s,"raw");var l=u.digest(),c="",h=f-r.length;for(var p=0;p<h;p++)c+="\0";var d=l.getBytes()+c+""+r;if(!o)o=e.random.getBytes(u.digestLength);else if(o.length!==u.digestLength)throw{message:"Invalid RSAES-OAEP seed. The seed length must match the digest length.",seedLength:o.length,digestLength:u.digestLength};var v=n(o,a-u.digestLength-1,u),m=e.util.xorBytes(d,v,d.length),g=n(m,u.digestLength,u),y=e.util.xorBytes(o,g,o.length);return"\0"+y+m},t.decode_rsa_oaep=function(t,r,i){var s=undefined,o=undefined;typeof i=="string"?(s=i,o=arguments[3]||undefined):i&&(s=i.label||undefined,o=i.md||undefined);var u=Math.ceil(t.n.bitLength()/8);if(r.length!==u)throw{message:"RSAES-OAEP encoded message length is invalid.",length:r.length,expectedLength:u};o===undefined?o=e.md.sha1.create():o.start();if(u<2*o.digestLength+2)throw{message:"RSAES-OAEP key is too short for the hash function."};s||(s=""),o.update(s,"raw");var a=o.digest().getBytes(),f=r.charAt(0),l=r.substring(1,o.digestLength+1),c=r.substring(1+o.digestLength),h=n(c,o.digestLength,o),p=e.util.xorBytes(l,h,l.length),d=n(p,u-o.digestLength-1,o),v=e.util.xorBytes(c,d,c.length),m=v.substring(0,o.digestLength),g=f!=="\0";for(var y=0;y<o.digestLength;++y)g|=a.charAt(y)!==m.charAt(y);var b=1,w=o.digestLength;for(var E=o.digestLength;E<v.length;E++){var S=v.charCodeAt(E),x=S&1^1,T=b?65534:0;g|=S&T,b&=x,w+=b}if(g||v.charCodeAt(w)!==1)throw{message:"Invalid RSAES-OAEP padding."};return v.substring(w+1)}}var r="pkcs1";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/pkcs1",["require","module","./util","./random","./sha1"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){function c(t,n,r){var i=e.util.createBuffer(),s=Math.ceil(n.n.bitLength()/8);if(t.length>s-11)throw{message:"Message is too long for PKCS#1 v1.5 padding.",length:t.length,max:s-11};i.putByte(0),i.putByte(r);var o=s-3-t.length,u;if(r===0||r===1){u=r===0?0:255;for(var a=0;a<o;++a)i.putByte(u)}else while(o>0){var f=0,l=e.random.getBytes(o);for(var a=0;a<o;++a)u=l.charCodeAt(a),u===0?++f:i.putByte(u);o=f}return i.putByte(0),i.putBytes(t),i}function h(t,n,r,i){var s=Math.ceil(n.n.bitLength()/8),o=e.util.createBuffer(t),u=o.getByte(),a=o.getByte();if(u!==0||r&&a!==0&&a!==1||!r&&a!=2||r&&a===0&&typeof i=="undefined")throw{message:"Encryption block is invalid."};var f=0;if(a===0){f=s-3-i;for(var l=0;l<f;++l)if(o.getByte()!==0)throw{message:"Encryption block is invalid."}}else if(a===1){f=0;while(o.length()>1){if(o.getByte()!==255){--o.read;break}++f}}else if(a===2){f=0;while(o.length()>1){if(o.getByte()===0){--o.read;break}++f}}var c=o.getByte();if(c!==0||f!==s-3-o.length())throw{message:"Encryption block is invalid."};return o.getBytes()}function p(n,i,s){function p(){d(n.pBits,function(e,t){if(e)return s(e);n.p=t,d(n.qBits,v)})}function d(e,r){function p(){var r=e-1,i=new t(e,n.rng);return i.testBit(r)||i.bitwiseTo(t.ONE.shiftLeft(r),h,i),i.dAddOffset(31-i.mod(c).byteValue(),0),i}function v(s){if(d)return;--o;var u=s.data;if(u.found){for(var c=0;c<i.length;++c)i[c].terminate();return d=!0,r(null,new t(u.prime,16))}l.bitLength()>e&&(l=p());var h=l.toString(16);s.target.postMessage({e:n.eInt,hex:h,workLoad:a}),l.dAddOffset(f,0)}var i=[];for(var s=0;s<u;++s)i[s]= new Worker("./forge/prime.worker.js");var o=u,l=p();for(var s=0;s<u;++s)i[s].addEventListener("message",v);var d=!1}function v(e,i){n.q=i;if(n.p.compareTo(n.q)<0){var o=n.p;n.p=n.q,n.q=o}n.p1=n.p.subtract(t.ONE),n.q1=n.q.subtract(t.ONE),n.phi=n.p1.multiply(n.q1);if(n.phi.gcd(n.e).compareTo(t.ONE)!==0){n.p=n.q=null,p();return}n.n=n.p.multiply(n.q);if(n.n.bitLength()!==n.bits){n.q=null,d(n.qBits,v);return}var u=n.e.modInverse(n.phi);n.keys={privateKey:r.rsa.setPrivateKey(n.n,n.e,u,n.p,n.q,u.mod(n.p1),u.mod(n.q1),n.q.modInverse(n.p)),publicKey:r.rsa.setPublicKey(n.n,n.e)},s(null,n.keys)}typeof i=="function"&&(s=i,i={});if(typeof Worker=="undefined"){function o(){if(r.rsa.stepKeyPairGenerationState(n,10))return s(null,n.keys);e.util.setImmediate(o)}return o()}var u=i.workers||2,a=i.workLoad||100,f=a*30/8,l=i.workerScript||"forge/prime.worker.js",c=new t(null);c.fromInt(30);var h=function(e,t){return e|t};p()}function d(t){var n=t.toString(16);return n[0]>="8"&&(n="00"+n),e.util.hexToBytes(n)}function v(e){return e<=100?27:e<=150?18:e<=200?15:e<=250?12:e<=300?9:e<=350?8:e<=400?7:e<=500?6:e<=600?5:e<=800?4:e<=1250?3:2}if(typeof t=="undefined")var t=e.jsbn.BigInteger;var n=e.asn1;e.pki=e.pki||{},e.pki.rsa=e.rsa=e.rsa||{};var r=e.pki,i=[6,4,2,4,2,4,6,2],s={name:"PrivateKeyInfo",tagClass:n.Class.UNIVERSAL,type:n.Type.SEQUENCE,constructed:!0,value:[{name:"PrivateKeyInfo.version",tagClass:n.Class.UNIVERSAL,type:n.Type.INTEGER,constructed:!1,capture:"privateKeyVersion"},{name:"PrivateKeyInfo.privateKeyAlgorithm",tagClass:n.Class.UNIVERSAL,type:n.Type.SEQUENCE,constructed:!0,value:[{name:"AlgorithmIdentifier.algorithm",tagClass:n.Class.UNIVERSAL,type:n.Type.OID,constructed:!1,capture:"privateKeyOid"}]},{name:"PrivateKeyInfo",tagClass:n.Class.UNIVERSAL,type:n.Type.OCTETSTRING,constructed:!1,capture:"privateKey"}]},o={name:"RSAPrivateKey",tagClass:n.Class.UNIVERSAL,type:n.Type.SEQUENCE,constructed:!0,value:[{name:"RSAPrivateKey.version",tagClass:n.Class.UNIVERSAL,type:n.Type.INTEGER,constructed:!1,capture:"privateKeyVersion"},{name:"RSAPrivateKey.modulus",tagClass:n.Class.UNIVERSAL,type:n.Type.INTEGER,constructed:!1,capture:"privateKeyModulus"},{name:"RSAPrivateKey.publicExponent",tagClass:n.Class.UNIVERSAL,type:n.Type.INTEGER,constructed:!1,capture:"privateKeyPublicExponent"},{name:"RSAPrivateKey.privateExponent",tagClass:n.Class.UNIVERSAL,type:n.Type.INTEGER,constructed:!1,capture:"privateKeyPrivateExponent"},{name:"RSAPrivateKey.prime1",tagClass:n.Class.UNIVERSAL,type:n.Type.INTEGER,constructed:!1,capture:"privateKeyPrime1"},{name:"RSAPrivateKey.prime2",tagClass:n.Class.UNIVERSAL,type:n.Type.INTEGER,constructed:!1,capture:"privateKeyPrime2"},{name:"RSAPrivateKey.exponent1",tagClass:n.Class.UNIVERSAL,type:n.Type.INTEGER,constructed:!1,capture:"privateKeyExponent1"},{name:"RSAPrivateKey.exponent2",tagClass:n.Class.UNIVERSAL,type:n.Type.INTEGER,constructed:!1,capture:"privateKeyExponent2"},{name:"RSAPrivateKey.coefficient",tagClass:n.Class.UNIVERSAL,type:n.Type.INTEGER,constructed:!1,capture:"privateKeyCoefficient"}]},u={name:"RSAPublicKey",tagClass:n.Class.UNIVERSAL,type:n.Type.SEQUENCE,constructed:!0,value:[{name:"RSAPublicKey.modulus",tagClass:n.Class.UNIVERSAL,type:n.Type.INTEGER,constructed:!1,capture:"publicKeyModulus"},{name:"RSAPublicKey.exponent",tagClass:n.Class.UNIVERSAL,type:n.Type.INTEGER,constructed:!1,capture:"publicKeyExponent"}]},a=e.pki.rsa.publicKeyValidator={name:"SubjectPublicKeyInfo",tagClass:n.Class.UNIVERSAL,type:n.Type.SEQUENCE,constructed:!0,captureAsn1:"subjectPublicKeyInfo",value:[{name:"SubjectPublicKeyInfo.AlgorithmIdentifier",tagClass:n.Class.UNIVERSAL,type:n.Type.SEQUENCE,constructed:!0,value:[{name:"AlgorithmIdentifier.algorithm",tagClass:n.Class.UNIVERSAL,type:n.Type.OID,constructed:!1,capture:"publicKeyOid"}]},{name:"SubjectPublicKeyInfo.subjectPublicKey",tagClass:n.Class.UNIVERSAL,type:n.Type.BITSTRING,constructed:!1,value:[{name:"SubjectPublicKeyInfo.subjectPublicKey.RSAPublicKey",tagClass:n.Class.UNIVERSAL,type:n.Type.SEQUENCE,constructed:!0,optional:!0,captureAsn1:"rsaPublicKey"}]}]},f=function(e){var t;if(e.algorithm in r.oids){t=r.oids[e.algorithm];var i=n.oidToDer(t).getBytes(),s=n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[]),o=n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[]);o.value.push(n.create(n.Class.UNIVERSAL,n.Type.OID,!1,i)),o.value.push(n.create(n.Class.UNIVERSAL,n.Type.NULL,!1,""));var u=n.create(n.Class.UNIVERSAL,n.Type.OCTETSTRING,!1,e.digest().getBytes());return s.value.push(o),s.value.push(u),n.toDer(s).getBytes()}throw{message:"Unknown message digest algorithm.",algorithm:e.algorithm}},l=function(e,n,r){var i;if(r)i=e.modPow(n.e,n.n);else if(!n.p||!n.q)i=e.modPow(n.d,n.n);else{n.dP||(n.dP=n.d.mod(n.p.subtract(t.ONE))),n.dQ||(n.dQ=n.d.mod(n.q.subtract(t.ONE))),n.qInv||(n.qInv=n.q.modInverse(n.p));var s=e.mod(n.p).modPow(n.dP,n.p),o=e.mod(n.q).modPow(n.dQ,n.q);while(s.compareTo(o)<0)s=s.add(n.p);i=s.subtract(o).multiply(n.qInv).mod(n.p).multiply(n.q).add(o)}return i};r.rsa.encrypt=function(n,r,i){var s=i,o,u=Math.ceil(r.n.bitLength()/8);i!==!1&&i!==!0?(s=i===2,o=c(n,r,i)):(o=e.util.createBuffer(),o.putBytes(n));var a=new t(o.toHex(),16),f=l(a,r,s),h=f.toString(16),p=e.util.createBuffer(),d=u-Math.ceil(h.length/2);while(d>0)p.putByte(0),--d;return p.putBytes(e.util.hexToBytes(h)),p.getBytes()},r.rsa.decrypt=function(n,r,i,s){var o=Math.ceil(r.n.bitLength()/8);if(n.length!==o)throw{message:"Encrypted message length is invalid.",length:n.length,expected:o};var u=new t(e.util.createBuffer(n).toHex(),16);if(u.compareTo(r.n)>=0)throw{message:"Encrypted message is invalid."};var a=l(u,r,i),f=a.toString(16),c=e.util.createBuffer(),p=o-Math.ceil(f.length/2);while(p>0)c.putByte(0),--p;return c.putBytes(e.util.hexToBytes(f)),s!==!1?h(c.getBytes(),r,i):c.getBytes()},r.rsa.createKeyPairGenerationState=function(n,r){typeof n=="string"&&(n=parseInt(n,10)),n=n||2048;var i={nextBytes:function(t){var n=e.random.getBytes(t.length);for(var r=0;r<t.length;++r)t[r]=n.charCodeAt(r)}},s={state:0,bits:n,rng:i,eInt:r||65537,e:new t(null),p:null,q:null,qBits:n>>1,pBits:n-(n>>1),pqState:0,num:null,keys:null};return s.e.fromInt(s.eInt),s},r.rsa.stepKeyPairGenerationState=function(e,n){var s=new t(null);s.fromInt(30);var o=0,u=function(e,t){return e|t},a=+(new Date),f,l=0;while(e.keys===null&&(n<=0||l<n)){if(e.state===0){var c=e.p===null?e.pBits:e.qBits,h=c-1;e.pqState===0?(e.num=new t(c,e.rng),e.num.testBit(h)||e.num.bitwiseTo(t.ONE.shiftLeft(h),u,e.num),e.num.dAddOffset(31-e.num.mod(s).byteValue(),0),o=0,++e.pqState):e.pqState===1?e.num.bitLength()>c?e.pqState=0:e.num.isProbablePrime(v(e.num.bitLength()))?++e.pqState:e.num.dAddOffset(i[o++%8],0):e.pqState===2?e.pqState=e.num.subtract(t.ONE).gcd(e.e).compareTo(t.ONE)===0?3:0:e.pqState===3&&(e.pqState=0,e.p===null?e.p=e.num:e.q=e.num,e.p!==null&&e.q!==null&&++e.state,e.num=null)}else if(e.state===1)e.p.compareTo(e.q)<0&&(e.num=e.p,e.p=e.q,e.q=e.num),++e.state;else if(e.state===2)e.p1=e.p.subtract(t.ONE),e.q1=e.q.subtract(t.ONE),e.phi=e.p1.multiply(e.q1),++e.state;else if(e.state===3)e.phi.gcd(e.e).compareTo(t.ONE)===0?++e.state:(e.p=null,e.q=null,e.state=0);else if(e.state===4)e.n=e.p.multiply(e.q),e.n.bitLength()===e.bits?++e.state:(e.q=null,e.state=0);else if(e.state===5){var p=e.e.modInverse(e.phi);e.keys={privateKey:r.rsa.setPrivateKey(e.n,e.e,p,e.p,e.q,p.mod(e.p1),p.mod(e.q1),e.q.modInverse(e.p)),publicKey:r.rsa.setPublicKey(e.n,e.e)}}f=+(new Date),l+=f-a,a=f}return e.keys!==null},r.rsa.generateKeyPair=function(e,t,n,i){arguments.length===1?typeof e=="object"?(n=e,e=undefined):typeof e=="function"&&(i=e,e=undefined):arguments.length===2?(typeof e=="number"?typeof t=="function"?i=t:n=t:(n=e,i=t,e=undefined),t=undefined):arguments.length===3&&(typeof t=="number"?typeof n=="function"&&(i=n,n=undefined):(i=n,n=t,t=undefined)),n=n||{},e===undefined&&(e=n.bits||2048),t===undefined&&(t=n.e||65537);var s=r.rsa.createKeyPairGenerationState(e,t);if(!i)return r.rsa.stepKeyPairGenerationState(s,0),s.keys;p(s,n,i)},r.setRsaPublicKey=r.rsa.setPublicKey=function(t,i){var s={n:t,e:i};return s.encrypt=function(t,n,i){typeof n=="string"?n=n.toUpperCase():n===undefined&&(n="RSAES-PKCS1-V1_5");if(n==="RSAES-PKCS1-V1_5")n={encode:function(e,t,n){return c(e,t,2).getBytes()}};else if(n==="RSA-OAEP"||n==="RSAES-OAEP")n={encode:function(t,n){return e.pkcs1.encode_rsa_oaep(n,t,i)}};else{if(["RAW","NONE","NULL",null].indexOf(n)===-1)throw{message:'Unsupported encryption scheme: "'+n+'".'};n={encode:function(e){return e}}}var o=n.encode(t,s,!0);return r.rsa.encrypt(o,s,!0)},s.verify=function(e,t,i){typeof i=="string"?i=i.toUpperCase():i===undefined&&(i="RSASSA-PKCS1-V1_5");if(i==="RSASSA-PKCS1-V1_5")i={verify:function(e,t){t=h(t,s,!0);var r=n.fromDer(t);return e===r.value[1].value}};else if(i==="NONE"||i==="NULL"||i===null)i={verify:function(e,t){return t=h(t,s,!0),e===t}};var o=r.rsa.decrypt(t,s,!0,!1);return i.verify(e,o,s.n.bitLength())},s},r.setRsaPrivateKey=r.rsa.setPrivateKey=function(t,n,i,s,o,u,a,l){var c={n:t,e:n,d:i,p:s,q:o,dP:u,dQ:a,qInv:l};return c.decrypt=function(t,n,i){typeof n=="string"?n=n.toUpperCase():n===undefined&&(n="RSAES-PKCS1-V1_5");var s=r.rsa.decrypt(t,c,!1,!1);if(n==="RSAES-PKCS1-V1_5")n={decode:h};else if(n==="RSA-OAEP"||n==="RSAES-OAEP")n={decode:function(t,n){return e.pkcs1.decode_rsa_oaep(n,t,i)}};else{if(["RAW","NONE","NULL",null].indexOf(n)===-1)throw{message:'Unsupported encryption scheme: "'+n+'".'};n={decode:function(e){return e}}}return n.decode(s,c,!1)},c.sign=function(e,t){var n=!1;typeof t=="string"&&(t=t.toUpperCase());if(t===undefined||t==="RSASSA-PKCS1-V1_5")t={encode:f},n=1;else if(t==="NONE"||t==="NULL"||t===null)t={encode:function(){return e}},n=1;var i=t.encode(e,c.n.bitLength());return r.rsa.encrypt(i,c,n)},c},r.wrapRsaPrivateKey=function(e){return n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[n.create(n.Class.UNIVERSAL,n.Type.INTEGER,!1,n.integerToDer(0).getBytes()),n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[n.create(n.Class.UNIVERSAL,n.Type.OID,!1,n.oidToDer(r.oids.rsaEncryption).getBytes()),n.create(n.Class.UNIVERSAL,n.Type.NULL,!1,"")]),n.create(n.Class.UNIVERSAL,n.Type.OCTETSTRING,!1,n.toDer(e).getBytes())])},r.wrapRsaPrivateKey=function(e){return n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[n.create(n.Class.UNIVERSAL,n.Type.INTEGER,!1,n.integerToDer(0).getBytes()),n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[n.create(n.Class.UNIVERSAL,n.Type.OID,!1,n.oidToDer(r.oids.rsaEncryption).getBytes()),n.create(n.Class.UNIVERSAL,n.Type.NULL,!1,"")]),n.create(n.Class.UNIVERSAL,n.Type.OCTETSTRING,!1,n.toDer(e).getBytes())])},r.privateKeyFromAsn1=function(i){var u={},a=[];n.validate(i,s,u,a)&&(i=n.fromDer(e.util.createBuffer(u.privateKey))),u={},a=[];if(!n.validate(i,o,u,a))throw{message:"Cannot read private key. ASN.1 object does not contain an RSAPrivateKey.",errors:a};var f,l,c,h,p,d,v,m;return f=e.util.createBuffer(u.privateKeyModulus).toHex(),l=e.util.createBuffer(u.privateKeyPublicExponent).toHex(),c=e.util.createBuffer(u.privateKeyPrivateExponent).toHex(),h=e.util.createBuffer(u.privateKeyPrime1).toHex(),p=e.util.createBuffer(u.privateKeyPrime2).toHex(),d=e.util.createBuffer(u.privateKeyExponent1).toHex(),v=e.util.createBuffer(u.privateKeyExponent2).toHex(),m=e.util.createBuffer(u.privateKeyCoefficient).toHex(),r.setRsaPrivateKey(new t(f,16),new t(l,16),new t(c,16),new t(h,16),new t(p,16),new t(d,16),new t(v,16),new t(m,16))},r.privateKeyToAsn1=r.privateKeyToRSAPrivateKey=function(e){return n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[n.create(n.Class.UNIVERSAL,n.Type.INTEGER,!1,n.integerToDer(0).getBytes()),n.create(n.Class.UNIVERSAL,n.Type.INTEGER,!1,d(e.n)),n.create(n.Class.UNIVERSAL,n.Type.INTEGER,!1,d(e.e)),n.create(n.Class.UNIVERSAL,n.Type.INTEGER,!1,d(e.d)),n.create(n.Class.UNIVERSAL,n.Type.INTEGER,!1,d(e.p)),n.create(n.Class.UNIVERSAL,n.Type.INTEGER,!1,d(e.q)),n.create(n.Class.UNIVERSAL,n.Type.INTEGER,!1,d(e.dP)),n.create(n.Class.UNIVERSAL,n.Type.INTEGER,!1,d(e.dQ)),n.create(n.Class.UNIVERSAL,n.Type.INTEGER,!1,d(e.qInv))])},r.publicKeyFromAsn1=function(i){var s={},o=[];if(n.validate(i,a,s,o)){var f=n.derToOid(s.publicKeyOid);if(f!==r.oids.rsaEncryption)throw{message:"Cannot read public key. Unknown OID.",oid:f};i=s.rsaPublicKey}o=[];if(!n.validate(i,u,s,o))throw{message:"Cannot read public key. ASN.1 object does not contain an RSAPublicKey.",errors:o};var l=e.util.createBuffer(s.publicKeyModulus).toHex(),c=e.util.createBuffer(s.publicKeyExponent).toHex();return r.setRsaPublicKey(new t(l,16),new t(c,16))},r.publicKeyToAsn1=r.publicKeyToSubjectPublicKeyInfo=function(e){return n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[n.create(n.Class.UNIVERSAL,n.Type.OID,!1,n.oidToDer(r.oids.rsaEncryption).getBytes()),n.create(n.Class.UNIVERSAL,n.Type.NULL,!1,"")]),n.create(n.Class.UNIVERSAL,n.Type.BITSTRING,!1,[r.publicKeyToRSAPublicKey(e)])])},r.publicKeyToRSAPublicKey=function(e){return n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[n.create(n.Class.UNIVERSAL,n.Type.INTEGER,!1,d(e.n)),n.create(n.Class.UNIVERSAL,n.Type.INTEGER,!1,d(e.e))])}}var r="rsa";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/rsa",["require","module","./asn1","./oids","./random","./util","./jsbn","./pkcs1"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){function a(e,t,n){var r=[f(e+t)];for(var i=16,s=1;i<n;++s,i+=16)r.push(f(r[s-1]+e+t));return r.join("").substr(0,n)}function f(t){return e.md.md5.create().update(t).digest().getBytes()}if(typeof t=="undefined")var t=e.jsbn.BigInteger;var n=e.asn1,r=e.pki=e.pki||{};r.pbe=e.pbe=e.pbe||{};var i=r.oids,s={name:"EncryptedPrivateKeyInfo",tagClass:n.Class.UNIVERSAL,type:n.Type.SEQUENCE,constructed:!0,value:[{name:"EncryptedPrivateKeyInfo.encryptionAlgorithm",tagClass:n.Class.UNIVERSAL,type:n.Type.SEQUENCE,constructed:!0,value:[{name:"AlgorithmIdentifier.algorithm",tagClass:n.Class.UNIVERSAL,type:n.Type.OID,constructed:!1,capture:"encryptionOid"},{name:"AlgorithmIdentifier.parameters",tagClass:n.Class.UNIVERSAL,type:n.Type.SEQUENCE,constructed:!0,captureAsn1:"encryptionParams"}]},{name:"EncryptedPrivateKeyInfo.encryptedData",tagClass:n.Class.UNIVERSAL,type:n.Type.OCTETSTRING,constructed:!1,capture:"encryptedData"}]},o={name:"PBES2Algorithms",tagClass:n.Class.UNIVERSAL,type:n.Type.SEQUENCE,constructed:!0,value:[{name:"PBES2Algorithms.keyDerivationFunc",tagClass:n.Class.UNIVERSAL,type:n.Type.SEQUENCE,constructed:!0,value:[{name:"PBES2Algorithms.keyDerivationFunc.oid",tagClass:n.Class.UNIVERSAL,type:n.Type.OID,constructed:!1,capture:"kdfOid"},{name:"PBES2Algorithms.params",tagClass:n.Class.UNIVERSAL,type:n.Type.SEQUENCE,constructed:!0,value:[{name:"PBES2Algorithms.params.salt",tagClass:n.Class.UNIVERSAL,type:n.Type.OCTETSTRING,constructed:!1,capture:"kdfSalt"},{name:"PBES2Algorithms.params.iterationCount",tagClass:n.Class.UNIVERSAL,type:n.Type.INTEGER,onstructed:!0,capture:"kdfIterationCount"}]}]},{name:"PBES2Algorithms.encryptionScheme",tagClass:n.Class.UNIVERSAL,type:n.Type.SEQUENCE,constructed:!0,value:[{name:"PBES2Algorithms.encryptionScheme.oid",tagClass:n.Class.UNIVERSAL,type:n.Type.OID,constructed:!1,capture:"encOid"},{name:"PBES2Algorithms.encryptionScheme.iv",tagClass:n.Class.UNIVERSAL,type:n.Type.OCTETSTRING,constructed:!1,capture:"encIv"}]}]},u={name:"pkcs-12PbeParams",tagClass:n.Class.UNIVERSAL,type:n.Type.SEQUENCE,constructed:!0,value:[{name:"pkcs-12PbeParams.salt",tagClass:n.Class.UNIVERSAL,type:n.Type.OCTETSTRING,constructed:!1,capture:"salt"},{name:"pkcs-12PbeParams.iterations",tagClass:n.Class.UNIVERSAL,type:n.Type.INTEGER,constructed:!1,capture:"iterations"}]};r.encryptPrivateKeyInfo=function(t,s,o){o=o||{},o.saltSize=o.saltSize||8,o.count=o.count||2048,o.algorithm=o.algorithm||"aes128";var u=e.random.getBytes(o.saltSize),a=o.count,f=n.integerToDer(a),l,c,h;if(o.algorithm.indexOf("aes")===0){var p;if(o.algorithm==="aes128")l=16,p=i["aes128-CBC"];else if(o.algorithm==="aes192")l=24,p=i["aes192-CBC"];else{if(o.algorithm!=="aes256")throw{message:"Cannot encrypt private key. Unknown encryption algorithm.",algorithm:o.algorithm};l=32,p=i["aes256-CBC"]}var d=e.pkcs5.pbkdf2(s,u,a,l),v=e.random.getBytes(16),m=e.aes.createEncryptionCipher(d);m.start(v),m.update(n.toDer(t)),m.finish(),h=m.output.getBytes(),c=n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[n.create(n.Class.UNIVERSAL,n.Type.OID,!1,n.oidToDer(i.pkcs5PBES2).getBytes()),n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[n.create(n.Class.UNIVERSAL,n.Type.OID,!1,n.oidToDer(i.pkcs5PBKDF2).getBytes()),n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[n.create(n.Class.UNIVERSAL,n.Type.OCTETSTRING,!1,u),n.create(n.Class.UNIVERSAL,n.Type.INTEGER,!1,f.getBytes())])]),n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[n.create(n.Class.UNIVERSAL,n.Type.OID,!1,n.oidToDer(p).getBytes()),n.create(n.Class.UNIVERSAL,n.Type.OCTETSTRING,!1,v)])])])}else{if(o.algorithm!=="3des")throw{message:"Cannot encrypt private key. Unknown encryption algorithm.",algorithm:o.algorithm};l=24;var g=new e.util.ByteBuffer(u),d=r.pbe.generatePkcs12Key(s,g,1,a,l),v=r.pbe.generatePkcs12Key(s,g,2,a,l),m=e.des.createEncryptionCipher(d);m.start(v),m.update(n.toDer(t)),m.finish(),h=m.output.getBytes(),c=n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[n.create(n.Class.UNIVERSAL,n.Type.OID,!1,n.oidToDer(i["pbeWithSHAAnd3-KeyTripleDES-CBC"]).getBytes()),n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[n.create(n.Class.UNIVERSAL,n.Type.OCTETSTRING,!1,u),n.create(n.Class.UNIVERSAL,n.Type.INTEGER,!1,f.getBytes())])])}var y=n.create(n.Class.UNIVERSAL,n.Type.SEQUENCE,!0,[c,n.create(n.Class.UNIVERSAL,n.Type.OCTETSTRING,!1,h)]);return y},r.decryptPrivateKeyInfo=function(t,i){var o=null,u={},a=[];if(!n.validate(t,s,u,a))throw{message:"Cannot read encrypted private key. ASN.1 object is not a supported EncryptedPrivateKeyInfo.",errors:a};var f=n.derToOid(u.encryptionOid),l=r.pbe.getCipher(f,u.encryptionParams,i),c=e.util.createBuffer(u.encryptedData);return l.update(c),l.finish()&&(o=n.fromDer(l.output)),o},r.encryptedPrivateKeyToPem=function(t,r){var i={type:"ENCRYPTED PRIVATE KEY",body:n.toDer(t).getBytes()};return e.pem.encode(i,{maxline:r})},r.encryptedPrivateKeyFromPem=function(t){var r=e.pem.decode(t)[0];if(r.type!=="ENCRYPTED PRIVATE KEY")throw{message:'Could not convert encrypted private key from PEM; PEM header type is "ENCRYPTED PRIVATE KEY".',headerType:r.type};if(r.procType&&r.procType.type==="ENCRYPTED")throw{message:"Could not convert encrypted private key from PEM; PEM is encrypted."};return n.fromDer(r.body)},r.encryptRsaPrivateKey=function(t,i,s){s=s||{};if(!s.legacy){var o=r.wrapRsaPrivateKey(r.privateKeyToAsn1(t));return o=r.encryptPrivateKeyInfo(o,i,s),r.encryptedPrivateKeyToPem(o)}var u,f,l,c;switch(s.algorithm){case"aes128":u="AES-128-CBC",l=16,f=e.random.getBytes(16),c=e.aes.createEncryptionCipher;break;case"aes192":u="AES-192-CBC",l=24,f=e.random.getBytes(16),c=e.aes.createEncryptionCipher;break;case"aes256":u="AES-256-CBC",l=32,f=e.random.getBytes(16),c=e.aes.createEncryptionCipher;break;case"3des":u="DES-EDE3-CBC",l=24,f=e.random.getBytes(8),c=e.des.createEncryptionCipher;break;default:throw{message:'Could not encrypt RSA private key; unsupported encryption algorithm "'+s.algorithm+'".',algorithm:s.algorithm}}var h=a(i,f.substr(0,8),l),p=c(h);p.start(f),p.update(n.toDer(r.privateKeyToAsn1(t))),p.finish();var d={type:"RSA PRIVATE KEY",procType:{version:"4",type:"ENCRYPTED"},dekInfo:{algorithm:u,parameters:e.util.bytesToHex(f).toUpperCase()},body:p.output.getBytes()};return e.pem.encode(d)},r.decryptRsaPrivateKey=function(t,i){var s=null,o=e.pem.decode(t)[0];if(o.type!=="ENCRYPTED PRIVATE KEY"&&o.type!=="PRIVATE KEY"&&o.type!=="RSA PRIVATE KEY")throw{message:'Could not convert private key from PEM; PEM header type is not "ENCRYPTED PRIVATE KEY", "PRIVATE KEY", or "RSA PRIVATE KEY".',headerType:o.type};if(o.procType&&o.procType.type==="ENCRYPTED"){var u,f;switch(o.dekInfo.algorithm){case"DES-EDE3-CBC":u=24,f=e.des.createDecryptionCipher;break;case"AES-128-CBC":u=16,f=e.aes.createDecryptionCipher;break;case"AES-192-CBC":u=24,f=e.aes.createDecryptionCipher;break;case"AES-256-CBC":u=32,f=e.aes.createDecryptionCipher;break;case"RC2-40-CBC":u=5,f=function(t){return e.rc2.createDecryptionCipher(t,40)};break;case"RC2-64-CBC":u=8,f=function(t){return e.rc2.createDecryptionCipher(t,64)};break;case"RC2-128-CBC":u=16,f=function(t){return e.rc2.createDecryptionCipher(t,128)};break;default:throw{message:'Could not decrypt private key; unsupported encryption algorithm "'+o.dekInfo.algorithm+'".',algorithm:o.dekInfo.algorithm}}var l=e.util.hexToBytes(o.dekInfo.parameters),c=a(i,l.substr(0,8),u),h=f(c);h.start(l),h.update(e.util.createBuffer(o.body));if(!h.finish())return s;s=h.output.getBytes()}else s=o.body;return o.type==="ENCRYPTED PRIVATE KEY"?s=r.decryptPrivateKeyInfo(n.fromDer(s),i):s=n.fromDer(s),s!==null&&(s=r.privateKeyFromAsn1(s)),s},r.pbe.generatePkcs12Key=function(t,n,r,i,s,o){var u,a;if(typeof o=="undefined"||o===null)o=e.md.sha1.create();var f=o.digestLength,l=o.blockLength,c=new e.util.ByteBuffer,h=new e.util.ByteBuffer;for(a=0;a<t.length;a++)h.putInt16(t.charCodeAt(a));h.putInt16(0);var p=h.length(),d=n.length(),v=new e.util.ByteBuffer;v.fillWithByte(r,l);var m=l*Math.ceil(d/l),g=new e.util.ByteBuffer;for(a=0;a<m;a++)g.putByte(n.at(a%d));var y=l*Math.ceil(p/l),b=new e.util.ByteBuffer;for(a=0;a<y;a++)b.putByte(h.at(a%p));var w=g;w.putBuffer(b);var E=Math.ceil(s/f);for(var S=1;S<=E;S++){var x=new e.util.ByteBuffer;x.putBytes(v.bytes()),x.putBytes(w.bytes());for(var T=0;T<i;T++)o.start(),o.update(x.getBytes()),x=o.digest();var N=new e.util.ByteBuffer;for(a=0;a<l;a++)N.putByte(x.at(a%f));var C=Math.ceil(d/l)+Math.ceil(p/l),k=new e.util.ByteBuffer;for(u=0;u<C;u++){var L=new e.util.ByteBuffer(w.getBytes(l)),A=511;for(a=N.length()-1;a>=0;a--)A>>=8,A+=N.at(a)+L.at(a),L.setAt(a,A&255);k.putBuffer(L)}w=k,c.putBuffer(x)}return c.truncate(c.length()-s),c},r.pbe.getCipher=function(e,t,n){switch(e){case r.oids.pkcs5PBES2:return r.pbe.getCipherForPBES2(e,t,n);case r.oids["pbeWithSHAAnd3-KeyTripleDES-CBC"]:case r.oids["pbewithSHAAnd40BitRC2-CBC"]:return r.pbe.getCipherForPKCS12PBE(e,t,n);default:throw{message:"Cannot read encrypted PBE data block. Unsupported OID.",oid:e,supportedOids:["pkcs5PBES2","pbeWithSHAAnd3-KeyTripleDES-CBC","pbewithSHAAnd40BitRC2-CBC"]}}},r.pbe.getCipherForPBES2=function(t,i,s){var u={},a=[];if(!n.validate(i,o,u,a))throw{message:"Cannot read password-based-encryption algorithm parameters. ASN.1 object is not a supported EncryptedPrivateKeyInfo.",errors:a};t=n.derToOid(u.kdfOid);if(t!==r.oids.pkcs5PBKDF2)throw{message:"Cannot read encrypted private key. Unsupported key derivation function OID.",oid:t,supportedOids:["pkcs5PBKDF2"]};t=n.derToOid(u.encOid);if(t!==r.oids["aes128-CBC"]&&t!==r.oids["aes192-CBC"]&&t!==r.oids["aes256-CBC"])throw{message:"Cannot read encrypted private key. Unsupported encryption scheme OID.",oid:t,supportedOids:["aes128-CBC","aes192-CBC","aes256-CBC"]};var f=u.kdfSalt,l=e.util.createBuffer(u.kdfIterationCount);l=l.getInt(l.length()<<3);var c;t===r.oids["aes128-CBC"]?c=16:t===r.oids["aes192-CBC"]?c=24:t===r.oids["aes256-CBC"]&&(c=32);var h=e.pkcs5.pbkdf2(s,f,l,c),p=u.encIv,d=e.aes.createDecryptionCipher(h);return d.start(p),d},r.pbe.getCipherForPKCS12PBE=function(t,i,s){var o={},a=[];if(!n.validate(i,u,o,a))throw{message:"Cannot read password-based-encryption algorithm parameters. ASN.1 object is not a supported EncryptedPrivateKeyInfo.",errors:a};var f=e.util.createBuffer(o.salt),l=e.util.createBuffer(o.iterations);l=l.getInt(l.length()<<3);var c,h,p;switch(t){case r.oids["pbeWithSHAAnd3-KeyTripleDES-CBC"]:c=24,h=8,p=e.des.startDecrypting;break;case r.oids["pbewithSHAAnd40BitRC2-CBC"]:c=5,h=8,p=function(t,n){var r=e.rc2.createDecryptionCipher(t,40);return r.start(n,null),r};break;default:throw{message:"Cannot read PKCS #12 PBE data block. Unsupported OID.",oid:t}}var d=r.pbe.generatePkcs12Key(s,f,1,l,c),v=r.pbe.generatePkcs12Key(s,f,2,l,h);return p(d,v)}}var r="pbe";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/pbe",["require","module","./aes","./asn1","./des","./md","./oids","./pem","./pbkdf2","./random","./rc2","./rsa","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){var t=e.asn1,n=e.pkcs7asn1=e.pkcs7asn1||{};e.pkcs7=e.pkcs7||{},e.pkcs7.asn1=n;var r={name:"ContentInfo",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"ContentInfo.ContentType",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1,capture:"contentType"},{name:"ContentInfo.content",tagClass:t.Class.CONTEXT_SPECIFIC,type:0,constructed:!0,optional:!0,captureAsn1:"content"}]};n.contentInfoValidator=r;var i={name:"EncryptedContentInfo",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"EncryptedContentInfo.contentType",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1,capture:"contentType"},{name:"EncryptedContentInfo.contentEncryptionAlgorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"EncryptedContentInfo.contentEncryptionAlgorithm.algorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1,capture:"encAlgorithm"},{name:"EncryptedContentInfo.contentEncryptionAlgorithm.parameter",tagClass:t.Class.UNIVERSAL,captureAsn1:"encParameter"}]},{name:"EncryptedContentInfo.encryptedContent",tagClass:t.Class.CONTEXT_SPECIFIC,type:0,capture:"encryptedContent"}]};n.envelopedDataValidator={name:"EnvelopedData",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"EnvelopedData.Version",tagClass:t.Class.UNIVERSAL,type:t.Type.INTEGER,constructed:!1,capture:"version"},{name:"EnvelopedData.RecipientInfos",tagClass:t.Class.UNIVERSAL,type:t.Type.SET,constructed:!0,captureAsn1:"recipientInfos"}].concat(i)},n.encryptedDataValidator={name:"EncryptedData",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"EncryptedData.Version",tagClass:t.Class.UNIVERSAL,type:t.Type.INTEGER,constructed:!1,capture:"version"}].concat(i)};var s={name:"SignerInfo",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"SignerInfo.Version",tagClass:t.Class.UNIVERSAL,type:t.Type.INTEGER,constructed:!1},{name:"SignerInfo.IssuerAndSerialNumber",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0},{name:"SignerInfo.DigestAlgorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0},{name:"SignerInfo.AuthenticatedAttributes",tagClass:t.Class.CONTEXT_SPECIFIC,type:0,constructed:!0,optional:!0,capture:"authenticatedAttributes"},{name:"SignerInfo.DigestEncryptionAlgorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0},{name:"SignerInfo.EncryptedDigest",tagClass:t.Class.UNIVERSAL,type:t.Type.OCTETSTRING,constructed:!1,capture:"signature"},{name:"SignerInfo.UnauthenticatedAttributes",tagClass:t.Class.CONTEXT_SPECIFIC,type:1,constructed:!0,optional:!0}]};n.signedDataValidator={name:"SignedData",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"SignedData.Version",tagClass:t.Class.UNIVERSAL,type:t.Type.INTEGER,constructed:!1,capture:"version"},{name:"SignedData.DigestAlgorithms",tagClass:t.Class.UNIVERSAL,type:t.Type.SET,constructed:!0,captureAsn1:"digestAlgorithms"},r,{name:"SignedData.Certificates",tagClass:t.Class.CONTEXT_SPECIFIC,type:0,optional:!0,captureAsn1:"certificates"},{name:"SignedData.CertificateRevocationLists",tagClass:t.Class.CONTEXT_SPECIFIC,type:1,optional:!0,captureAsn1:"crls"},{name:"SignedData.SignerInfos",tagClass:t.Class.UNIVERSAL,type:t.Type.SET,capture:"signerInfos",optional:!0,value:[s]}]},n.recipientInfoValidator={name:"RecipientInfo",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"RecipientInfo.version",tagClass:t.Class.UNIVERSAL,type:t.Type.INTEGER,constructed:!1,capture:"version"},{name:"RecipientInfo.issuerAndSerial",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"RecipientInfo.issuerAndSerial.issuer",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,captureAsn1:"issuer"},{name:"RecipientInfo.issuerAndSerial.serialNumber",tagClass:t.Class.UNIVERSAL,type:t.Type.INTEGER,constructed:!1,capture:"serial"}]},{name:"RecipientInfo.keyEncryptionAlgorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"RecipientInfo.keyEncryptionAlgorithm.algorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1,capture:"encAlgorithm"},{name:"RecipientInfo.keyEncryptionAlgorithm.parameter",tagClass:t.Class.UNIVERSAL,constructed:!1,captureAsn1:"encParameter"}]},{name:"RecipientInfo.encryptedKey",tagClass:t.Class.UNIVERSAL,type:t.Type.OCTETSTRING,constructed:!1,capture:"encKey"}]}}var r="pkcs7asn1";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/pkcs7asn1",["require","module","./asn1","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){e.mgf=e.mgf||{};var t=e.mgf.mgf1=e.mgf1=e.mgf1||{};t.create=function(t){var n={generate:function(n,r){var i=new e.util.ByteBuffer,s=Math.ceil(r/t.digestLength);for(var o=0;o<s;o++){var u=new e.util.ByteBuffer;u.putInt32(o),t.start(),t.update(n+u.getBytes()),i.putBuffer(t.digest())}return i.truncate(i.length()-r),i.getBytes()}};return n}}var r="mgf1";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/mgf1",["require","module","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){e.mgf=e.mgf||{},e.mgf.mgf1=e.mgf1}var r="mgf";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/mgf",["require","module","./mgf1"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){var t=e.pss=e.pss||{};t.create=function(t,n,r){var i=t.digestLength,s={};return s.verify=function(s,o,u){var a,f=u-1,l=Math.ceil(f/8);o=o.substr(-l);if(l<i+r+2)throw{message:"Inconsistent parameters to PSS signature verification."};if(o.charCodeAt(l-1)!==188)throw{message:"Encoded message does not end in 0xBC."};var c=l-i-1,h=o.substr(0,c),p=o.substr(c,i),d=65280>>8*l-f&255;if((h.charCodeAt(0)&d)!==0)throw{message:"Bits beyond keysize not zero as expected."};var v=n.generate(p,c),m="";for(a=0;a<c;a++)m+=String.fromCharCode(h.charCodeAt(a)^v.charCodeAt(a));m=String.fromCharCode(m.charCodeAt(0)&~d)+m.substr(1);var g=l-i-r-2;for(a=0;a<g;a++)if(m.charCodeAt(a)!==0)throw{message:"Leftmost octets not zero as expected"};if(m.charCodeAt(g)!==1)throw{message:"Inconsistent PSS signature, 0x01 marker not found"};var y=m.substr(-r),b=new e.util.ByteBuffer;b.fillWithByte(0,8),b.putBytes(s),b.putBytes(y),t.start(),t.update(b.getBytes());var w=t.digest().getBytes();return p===w},s.encode=function(s,o){var u,a=o-1,f=Math.ceil(a/8),l=s.digest().getBytes();if(f<i+r+2)throw{message:"Message is too long to encrypt"};var c=e.random.getBytes(r),h=new e.util.ByteBuffer;h.fillWithByte(0,8),h.putBytes(l),h.putBytes(c),t.start(),t.update(h.getBytes());var p=t.digest().getBytes(),d=new e.util.ByteBuffer;d.fillWithByte(0,f-r-i-2),d.putByte(1),d.putBytes(c);var v=d.getBytes(),m=f-i-1,g=n.generate(p,m),y="";for(u=0;u<m;u++)y+=String.fromCharCode(v.charCodeAt(u)^g.charCodeAt(u));var b=65280>>8*f-a&255;return y=String.fromCharCode(y.charCodeAt(0)&~b)+y.substr(1),y+p+String.fromCharCode(188)},s}}var r="pss";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/pss",["require","module","./random","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){function l(e,t){typeof t=="string"&&(t={shortName:t});var n=null,r;for(var i=0;n===null&&i<e.attributes.length;++i)r=e.attributes[i],t.type&&t.type===r.type?n=r:t.name&&t.name===r.name?n=r:t.shortName&&t.shortName===r.shortName&&(n=r);return n}function p(n){var r=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[]),i,s,o=n.attributes;for(var u=0;u<o.length;++u){i=o[u];var a=i.value,f=t.Type.PRINTABLESTRING;"valueTagClass"in i&&(f=i.valueTagClass,f===t.Type.UTF8&&(a=e.util.encodeUtf8(a))),s=t.create(t.Class.UNIVERSAL,t.Type.SET,!0,[t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(i.type).getBytes()),t.create(t.Class.UNIVERSAL,f,!1,a)])]),r.value.push(s)}return r}function d(e){var n=t.create(t.Class.CONTEXT_SPECIFIC,3,!0,[]),r=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[]);n.value.push(r);var i,s;for(var o=0;o<e.length;++o){i=e[o],s=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[]),r.value.push(s),s.value.push(t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(i.id).getBytes())),i.critical&&s.value.push(t.create(t.Class.UNIVERSAL,t.Type.BOOLEAN,!1,String.fromCharCode(255)));var u=i.value;typeof i.value!="string"&&(u=t.toDer(u).getBytes()),s.value.push(t.create(t.Class.UNIVERSAL,t.Type.OCTETSTRING,!1,u))}return n}function v(n){var r={};for(var i=0;i<n.length;++i){var s=n[i];console.log("attr",s);if(s.shortName&&(s.valueTagClass===t.Type.UTF8||s.valueTagClass===t.Type.PRINTABLESTRING||s.valueTagClass===t.Type.IA5String)){var o=s.value;s.valueTagClass===t.Type.UTF8&&(o=e.util.encodeUtf8(s.value)),s.shortName in r?e.util.isArray(r[s.shortName])?r[s.shortName].push(o):r[s.shortName]=[r[s.shortName],o]:r[s.shortName]=o}}return r}function m(e){var t;for(var r=0;r<e.length;++r){t=e[r],typeof t.name=="undefined"&&(t.type&&t.type in n.oids?t.name=n.oids[t.type]:t.shortName&&t.shortName in i&&(t.name=n.oids[i[t.shortName]]));if(typeof t.type=="undefined"){if(!(t.name&&t.name in n.oids))throw{message:"Attribute type not specified.",attribute:t};t.type=n.oids[t.name]}typeof t.shortName=="undefined"&&t.name&&t.name in i&&(t.shortName=i[t.name]);if(typeof t.value=="undefined")throw{message:"Attribute value not specified.",attribute:t}}}function g(e,n){switch(e){case r["RSASSA-PSS"]:var i=[];return n.hash.algorithmOid!==undefined&&i.push(t.create(t.Class.CONTEXT_SPECIFIC,0,!0,[t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(n.hash.algorithmOid).getBytes()),t.create(t.Class.UNIVERSAL,t.Type.NULL,!1,"")])])),n.mgf.algorithmOid!==undefined&&i.push(t.create(t.Class.CONTEXT_SPECIFIC,1,!0,[t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(n.mgf.algorithmOid).getBytes()),t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(n.mgf.hash.algorithmOid).getBytes()),t.create(t.Class.UNIVERSAL,t.Type.NULL,!1,"")])])])),n.saltLength!==undefined&&i.push(t.create(t.Class.CONTEXT_SPECIFIC,2,!0,[t.create(t.Class.UNIVERSAL,t.Type.INTEGER,!1,t.integerToDer(n.saltLength).getBytes())])),t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,i);default:return t.create(t.Class.UNIVERSAL,t.Type.NULL,!1,"")}}function y(n){var r=t.create(t.Class.CONTEXT_SPECIFIC,0,!0,[]);if(n.attributes.length===0)return r;var i=n.attributes;for(var s=0;s<i.length;++s){var o=i[s],u=o.value,a=t.Type.UTF8;"valueTagClass"in o&&(a=o.valueTagClass),a===t.Type.UTF8&&(u=e.util.encodeUtf8(u));var f=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(o.type).getBytes()),t.create(t.Class.UNIVERSAL,t.Type.SET,!0,[t.create(t.Class.UNIVERSAL,a,!1,u)])]);r.value.push(f)}return r}var t=e.asn1,n=e.pki=e.pki||{},r=n.oids,i={};i.CN=r.commonName,i.commonName="CN",i.C=r.countryName,i.countryName="C",i.L=r.localityName,i.localityName="L",i.ST=r.stateOrProvinceName,i.stateOrProvinceName="ST",i.O=r.organizationName,i.organizationName="O",i.OU=r.organizationalUnitName,i.organizationalUnitName="OU",i.E=r.emailAddress,i.emailAddress="E";var s=e.pki.rsa.publicKeyValidator,o={name:"Certificate",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"Certificate.TBSCertificate",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,captureAsn1:"tbsCertificate",value:[{name:"Certificate.TBSCertificate.version",tagClass:t.Class.CONTEXT_SPECIFIC,type:0,constructed:!0,optional:!0,value:[{name:"Certificate.TBSCertificate.version.integer",tagClass:t.Class.UNIVERSAL,type:t.Type.INTEGER,constructed:!1,capture:"certVersion"}]},{name:"Certificate.TBSCertificate.serialNumber",tagClass:t.Class.UNIVERSAL,type:t.Type.INTEGER,constructed:!1,capture:"certSerialNumber"},{name:"Certificate.TBSCertificate.signature",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"Certificate.TBSCertificate.signature.algorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1,capture:"certinfoSignatureOid"},{name:"Certificate.TBSCertificate.signature.parameters",tagClass:t.Class.UNIVERSAL,optional:!0,captureAsn1:"certinfoSignatureParams"}]},{name:"Certificate.TBSCertificate.issuer",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,captureAsn1:"certIssuer"},{name:"Certificate.TBSCertificate.validity",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"Certificate.TBSCertificate.validity.notBefore (utc)",tagClass:t.Class.UNIVERSAL,type:t.Type.UTCTIME,constructed:!1,optional:!0,capture:"certValidity1UTCTime"},{name:"Certificate.TBSCertificate.validity.notBefore (generalized)",tagClass:t.Class.UNIVERSAL,type:t.Type.GENERALIZEDTIME,constructed:!1,optional:!0,capture:"certValidity2GeneralizedTime"},{name:"Certificate.TBSCertificate.validity.notAfter (utc)",tagClass:t.Class.UNIVERSAL,type:t.Type.UTCTIME,constructed:!1,optional:!0,capture:"certValidity3UTCTime"},{name:"Certificate.TBSCertificate.validity.notAfter (generalized)",tagClass:t.Class.UNIVERSAL,type:t.Type.GENERALIZEDTIME,constructed:!1,optional:!0,capture:"certValidity4GeneralizedTime"}]},{name:"Certificate.TBSCertificate.subject",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,captureAsn1:"certSubject"},s,{name:"Certificate.TBSCertificate.issuerUniqueID",tagClass:t.Class.CONTEXT_SPECIFIC,type:1,constructed:!0,optional:!0,value:[{name:"Certificate.TBSCertificate.issuerUniqueID.id",tagClass:t.Class.UNIVERSAL,type:t.Type.BITSTRING,constructed:!1,capture:"certIssuerUniqueId"}]},{name:"Certificate.TBSCertificate.subjectUniqueID",tagClass:t.Class.CONTEXT_SPECIFIC,type:2,constructed:!0,optional:!0,value:[{name:"Certificate.TBSCertificate.subjectUniqueID.id",tagClass:t.Class.UNIVERSAL,type:t.Type.BITSTRING,constructed:!1,capture:"certSubjectUniqueId"}]},{name:"Certificate.TBSCertificate.extensions",tagClass:t.Class.CONTEXT_SPECIFIC,type:3,constructed:!0,captureAsn1:"certExtensions",optional:!0}]},{name:"Certificate.signatureAlgorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"Certificate.signatureAlgorithm.algorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1,capture:"certSignatureOid"},{name:"Certificate.TBSCertificate.signature.parameters",tagClass:t.Class.UNIVERSAL,optional:!0,captureAsn1:"certSignatureParams"}]},{name:"Certificate.signatureValue",tagClass:t.Class.UNIVERSAL,type:t.Type.BITSTRING,constructed:!1,capture:"certSignature"}]},u={name:"rsapss",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"rsapss.hashAlgorithm",tagClass:t.Class.CONTEXT_SPECIFIC,type:0,constructed:!0,value:[{name:"rsapss.hashAlgorithm.AlgorithmIdentifier",tagClass:t.Class.UNIVERSAL,type:t.Class.SEQUENCE,constructed:!0,optional:!0,value:[{name:"rsapss.hashAlgorithm.AlgorithmIdentifier.algorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1,capture:"hashOid"}]}]},{name:"rsapss.maskGenAlgorithm",tagClass:t.Class.CONTEXT_SPECIFIC,type:1,constructed:!0,value:[{name:"rsapss.maskGenAlgorithm.AlgorithmIdentifier",tagClass:t.Class.UNIVERSAL,type:t.Class.SEQUENCE,constructed:!0,optional:!0,value:[{name:"rsapss.maskGenAlgorithm.AlgorithmIdentifier.algorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1,capture:"maskGenOid"},{name:"rsapss.maskGenAlgorithm.AlgorithmIdentifier.params",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"rsapss.maskGenAlgorithm.AlgorithmIdentifier.params.algorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1,capture:"maskGenHashOid"}]}]}]},{name:"rsapss.saltLength",tagClass:t.Class.CONTEXT_SPECIFIC,type:2,optional:!0,value:[{name:"rsapss.saltLength.saltLength",tagClass:t.Class.UNIVERSAL,type:t.Class.INTEGER,constructed:!1,capture:"saltLength"}]},{name:"rsapss.trailerField",tagClass:t.Class.CONTEXT_SPECIFIC,type:3,optional:!0,value:[{name:"rsapss.trailer.trailer",tagClass:t.Class.UNIVERSAL,type:t.Class.INTEGER,constructed:!1,capture:"trailer"}]}]},a={name:"CertificationRequestInfo",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,captureAsn1:"certificationRequestInfo",value:[{name:"CertificationRequestInfo.integer",tagClass:t.Class.UNIVERSAL,type:t.Type.INTEGER,constructed:!1,capture:"certificationRequestInfoVersion"},{name:"CertificationRequestInfo.subject",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,captureAsn1:"certificationRequestInfoSubject"},s,{name:"CertificationRequestInfo.attributes",tagClass:t.Class.CONTEXT_SPECIFIC,type:0,constructed:!0,optional:!0,capture:"certificationRequestInfoAttributes",value:[{name:"CertificationRequestInfo.attributes",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"CertificationRequestInfo.attributes.type",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1},{name:"CertificationRequestInfo.attributes.value",tagClass:t.Class.UNIVERSAL,type:t.Type.SET,constructed:!0}]}]}]},f={name:"CertificationRequest",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,captureAsn1:"csr",value:[a,{name:"CertificationRequest.signatureAlgorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"CertificationRequest.signatureAlgorithm.algorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1,capture:"csrSignatureOid"},{name:"CertificationRequest.signatureAlgorithm.parameters",tagClass:t.Class.UNIVERSAL,optional:!0,captureAsn1:"csrSignatureParams"}]},{name:"CertificationRequest.signature",tagClass:t.Class.UNIVERSAL,type:t.Type.BITSTRING,constructed:!1,capture:"csrSignature"}]};n.RDNAttributesAsArray=function(e,n){var s=[],o,u,a;for(var f=0;f<e.value.length;++f){o=e.value[f];for(var l=0;l<o.value.length;++l)a={},u=o.value[l],a.type=t.derToOid(u.value[0].value),a.value=u.value[1].value,a.valueTagClass=u.value[1].type,a.type in r&&(a.name=r[a.type],a.name in i&&(a.shortName=i[a.name])),n&&(n.update(a.type),n.update(a.value)),s.push(a)}return s},n.CRIAttributesAsArray=function(e){var n=[];for(var s=0;s<e.length;++s){var o=e[s],u=t.derToOid(o.value[0].value),a=o.value[1].value;for(var f=0;f<a.length;++f){var l={};l.type=u,l.value=a[f].value,l.valueTagClass=a[f].type,l.type in r&&(l.name=r[l.type],l.name in i&&(l.shortName=i[l.name])),n.push(l)}}return n};var c=function(n){var i=[],s,o,u;for(var a=0;a<n.value.length;++a){u=n.value[a];for(var f=0;f<u.value.length;++f){o=u.value[f],s={},s.id=t.derToOid(o.value[0].value),s.critical=!1,o.value[1].type===t.Type.BOOLEAN?(s.critical=o.value[1].value.charCodeAt(0)!==0,s.value=o.value[2].value):s.value=o.value[1].value;if(s.id in r){s.name=r[s.id];if(s.name==="keyUsage"){var l=t.fromDer(s.value),c=0,h=0;l.value.length>1&&(c=l.value.charCodeAt(1),h=l.value.length>2?l.value.charCodeAt(2):0),s.digitalSignature=(c&128)===128,s.nonRepudiation=(c&64)===64,s.keyEncipherment=(c&32)===32,s.dataEncipherment=(c&16)===16,s.keyAgreement=(c&8)===8,s.keyCertSign=(c&4)===4,s.cRLSign=(c&2)===2,s.encipherOnly=(c&1)===1,s.decipherOnly=(h&128)===128}else if(s.name==="basicConstraints"){var l=t.fromDer(s.value);l.value.length>0&&l.value[0].type===t.Type.BOOLEAN?s.cA=l.value[0].value.charCodeAt(0)!==0:s.cA=!1;var p=null;l.value.length>0&&l.value[0].type===t.Type.INTEGER?p=l.value[0].value:l.value.length>1&&(p=l.value[1].value),p!==null&&(s.pathLenConstraint=t.derToInteger(p))}else if(s.name==="extKeyUsage"){var l=t.fromDer(s.value);for(var d=0;d<l.value.length;++d){var v=t.derToOid(l.value[d].value);v in r?s[r[v]]=!0:s[v]=!0}}else if(s.name==="nsCertType"){var l=t.fromDer(s.value),c=0;l.value.length>1&&(c=l.value.charCodeAt(1)),s.client=(c&128)===128,s.server=(c&64)===64,s.email=(c&32)===32,s.objsign=(c&16)===16,s.reserved=(c&8)===8,s.sslCA=(c&4)===4,s.emailCA=(c&2)===2,s.objCA=(c&1)===1}else if(s.name==="subjectAltName"||s.name==="issuerAltName"){s.altNames=[];var m,l=t.fromDer(s.value);for(var g=0;g<l.value.length;++g){m=l.value[g];var y={type:m.type,value:m.value};s.altNames.push(y);switch(m.type){case 1:case 2:case 6:break;case 7:y.ip=e.util.bytesToIP(m.value);break;case 8:y.oid=t.derToOid(m.value);break;default:}}}else if(s.name==="subjectKeyIdentifier"){var l=t.fromDer(s.value);s.subjectKeyIdentifier=e.util.bytesToHex(l.value)}}i.push(s)}}return i},h=function(e,n,i){var s={};if(e!==r["RSASSA-PSS"])return s;i&&(s={hash:{algorithmOid:r.sha1},mgf:{algorithmOid:r.mgf1,hash:{algorithmOid:r.sha1}},saltLength:20});var o={},a=[];if(!t.validate(n,u,o,a))throw{message:"Cannot read RSASSA-PSS parameter block.",errors:a};return o.hashOid!==undefined&&(s.hash=s.hash||{},s.hash.algorithmOid=t.derToOid(o.hashOid)),o.maskGenOid!==undefined&&(s.mgf=s.mgf||{},s.mgf.algorithmOid=t.derToOid(o.maskGenOid),s.mgf.hash=s.mgf.hash||{},s.mgf.hash.algorithmOid=t.derToOid(o.maskGenHashOid)),o.saltLength!==undefined&&(s.saltLength=o.saltLength.charCodeAt(0)),s};n.certificateFromPem=function(r,i,s){var o=e.pem.decode(r)[0];if(o.type!=="CERTIFICATE"&&o.type!=="X509 CERTIFICATE"&&o.type!=="TRUSTED CERTIFICATE")throw{message:'Could not convert certificate from PEM; PEM header type is not "CERTIFICATE", "X509 CERTIFICATE", or "TRUSTED CERTIFICATE".',headerType:o.type};if(o.procType&&o.procType.type==="ENCRYPTED")throw{message:"Could not convert certificate from PEM; PEM is encrypted."};var u=t.fromDer(o.body,s);return n.certificateFromAsn1(u,i)},n.certificateToPem=function(r,i){var s={type:"CERTIFICATE",body:t.toDer(n.certificateToAsn1(r)).getBytes()};return e.pem.encode(s,{maxline:i})},n.publicKeyFromPem=function(r){var i=e.pem.decode(r)[0];if(i.type!=="PUBLIC KEY"&&i.type!=="RSA PUBLIC KEY")throw{message:'Could not convert public key from PEM; PEM header type is not "PUBLIC KEY" or "RSA PUBLIC KEY".',headerType:i.type};if(i.procType&&i.procType.type==="ENCRYPTED")throw{message:"Could not convert public key from PEM; PEM is encrypted."};var s=t.fromDer(i.body);return n.publicKeyFromAsn1(s)},n.publicKeyToPem=function(r,i){var s={type:"PUBLIC KEY",body:t.toDer(n.publicKeyToAsn1(r)).getBytes()};return e.pem.encode(s,{maxline:i})},n.publicKeyToRSAPublicKeyPem=function(r,i){var s={type:"RSA PUBLIC KEY",body:t.toDer(n.publicKeyToRSAPublicKey(r)).getBytes()};return e.pem.encode(s,{maxline:i})},n.certificationRequestFromPem=function(r,i,s){var o=e.pem.decode(r)[0];if(o.type!=="CERTIFICATE REQUEST")throw{message:'Could not convert certification request from PEM; PEM header type is not "CERTIFICATE REQUEST".',headerType:o.type};if(o.procType&&o.procType.type==="ENCRYPTED")throw{message:"Could not convert certification request from PEM; PEM is encrypted."};var u=t.fromDer(o.body,s);return n.certificationRequestFromAsn1(u,i)},n.certificationRequestToPem=function(r,i){var s={type:"CERTIFICATE REQUEST",body:t.toDer(n.certificationRequestToAsn1(r)).getBytes()};return e.pem.encode(s,{maxline:i})},n.createCertificate=function(){var i={};return i.version=2,i.serialNumber="00",i.signatureOid=null,i.signature=null,i.siginfo={},i.siginfo.algorithmOid=null,i.validity={},i.validity.notBefore=new Date,i.validity.notAfter=new Date,i.issuer={},i.issuer.getField=function(e){return l(i.issuer,e)},i.issuer.addField=function(e){m([e]),i.issuer.attributes.push(e)},i.issuer.attributes=[],i.issuer.hash=null,i.subject={},i.subject.getField=function(e){return l(i.subject,e)},i.subject.addField=function(e){m([e]),i.subject.attributes.push(e)},i.subject.attributes=[],i.subject.hash=null,i.extensions=[],i.publicKey=null,i.md=null,i.setSubject=function(e,t){m(e),i.subject.attributes=e,delete i.subject.uniqueId,t&&(i.subject.uniqueId=t),i.subject.hash=null},i.setIssuer=function(e,t){m(e),i.issuer.attributes=e,delete i.issuer.uniqueId,t&&(i.issuer.uniqueId=t),i.issuer.hash=null},i.setExtensions=function(s){var o;for(var u=0;u<s.length;++u){o=s[u],typeof o.name=="undefined"&&o.id&&o.id in n.oids&&(o.name=n.oids[o.id]);if(typeof o.id=="undefined"){if(!(o.name&&o.name in n.oids))throw{message:"Extension ID not specified.",extension:o};o.id=n.oids[o.name]}if(typeof o.value=="undefined"){if(o.name==="keyUsage"){var a=0,f=0,l=0;o.digitalSignature&&(f|=128,a=7),o.nonRepudiation&&(f|=64,a=6),o.keyEncipherment&&(f|=32,a=5),o.dataEncipherment&&(f|=16,a=4),o.keyAgreement&&(f|=8,a=3),o.keyCertSign&&(f|=4,a=2),o.cRLSign&&(f|=2,a=1),o.encipherOnly&&(f|=1,a=0),o.decipherOnly&&(l|=128,a=7);var c=String.fromCharCode(a);l!==0?c+=String.fromCharCode(f)+String.fromCharCode(l):f!==0&&(c+=String.fromCharCode(f)),o.value=t.create(t.Class.UNIVERSAL,t.Type.BITSTRING,!1,c)}else if(o.name==="basicConstraints")o.value=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[]),o.cA&&o.value.value.push(t.create(t.Class.UNIVERSAL,t.Type.BOOLEAN,!1,String.fromCharCode(255))),"pathLenConstraint"in o&&o.value.value.push(t.create(t.Class.UNIVERSAL,t.Type.INTEGER,!1,t.integerToDer(o.pathLenConstraint).getBytes()));else if(o.name==="extKeyUsage"){o.value=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[]);var h=o.value.value;for(var p in o){if(o[p]!==!0)continue;p in r?h.push(t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(r[p]).getBytes())):p.indexOf(".")!==-1&&h.push(t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(p).getBytes()))}}else if(o.name==="nsCertType"){var a=0,f=0;o.client&&(f|=128,a=7),o.server&&(f|=64,a=6),o.email&&(f|=32,a=5),o.objsign&&(f|=16,a=4),o.reserved&&(f|=8,a=3),o.sslCA&&(f|=4,a=2),o.emailCA&&(f|=2,a=1),o.objCA&&(f|=1,a=0);var c=String.fromCharCode(a);f!==0&&(c+=String.fromCharCode(f)),o.value=t.create(t.Class.UNIVERSAL,t.Type.BITSTRING,!1,c)}else if(o.name==="subjectAltName"||o.name==="issuerAltName"){o.value=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[]);var d;for(var v=0;v<o.altNames.length;++v){d=o.altNames[v];var c=d.value;if(d.type===7&&d.ip){c=e.util.bytesFromIP(d.ip);if(c===null)throw{message:'Extension "ip" value is not a valid IPv4 or IPv6 address.',extension:o}}else d.type===8&&(d.oid?c=t.oidToDer(t.oidToDer(d.oid)):c=t.oidToDer(c));o.value.value.push(t.create(t.Class.CONTEXT_SPECIFIC,d.type,!1,c))}}else if(o.name==="subjectKeyIdentifier"){var m=i.generateSubjectKeyIdentifier();o.subjectKeyIdentifier=m.toHex(),o.value=t.create(t.Class.UNIVERSAL,t.Type.OCTETSTRING,!1,m.getBytes())}if(typeof o.value=="undefined")throw{message:"Extension value not specified.",extension:o}}}i.extensions=s},i.getExtension=function(e){typeof e=="string"&&(e={name:e});var t=null,n;for(var r=0;t===null&&r<i.extensions.length;++r)n=i.extensions[r],e.id&&n.id===e.id?t=n:e.name&&n.name===e.name&&(t=n);return t},i.sign=function(s,o){i.md=o||e.md.sha1.create();var u=r[i.md.algorithm+"WithRSAEncryption"];if(!u)throw{message:"Could not compute certificate digest. Unknown message digest algorithm OID.",algorithm:i.md.algorithm};i.signatureOid=i.siginfo.algorithmOid=u,i.tbsCertificate=n.getTBSCertificate(i);var a=t.toDer(i.tbsCertificate);i.md.update(a.getBytes()),i.signature=s.sign(i.md)},i.verify=function(s){var o=!1;if(!i.issued(s)){var u=s.issuer,a=i.subject;throw{message:"The parent certificate did not issue the given child certificate; the child certificate's issuer does not match the parent's subject.",expectedIssuer:u.attributes,actualIssuer:a.attributes}}var f=s.md;if(f===null){if(s.signatureOid in r){var l=r[s.signatureOid];switch(l){case"sha1WithRSAEncryption":f=e.md.sha1.create();break;case"md5WithRSAEncryption":f=e.md.md5.create();break;case"sha256WithRSAEncryption":f=e.md.sha256.create();break;case"RSASSA-PSS":f=e.md.sha256.create()}}if(f===null)throw{message:"Could not compute certificate digest. Unknown signature OID.",signatureOid:s.signatureOid};var c=s.tbsCertificate||n.getTBSCertificate(s),h=t.toDer(c);f.update(h.getBytes())}if(f!==null){var p=undefined;switch(s.signatureOid){case r.sha1WithRSAEncryption:p=undefined;break;case r["RSASSA-PSS"]:var d,v;d=r[s.signatureParameters.mgf.hash.algorithmOid];if(d===undefined||e.md[d]===undefined)throw{message:"Unsupported MGF hash function.",oid:s.signatureParameters.mgf.hash.algorithmOid,name:d};v=r[s.signatureParameters.mgf.algorithmOid];if(v===undefined||e.mgf[v]===undefined)throw{message:"Unsupported MGF function.",oid:s.signatureParameters.mgf.algorithmOid,name:v};v=e.mgf[v].create(e.md[d].create()),d=r[s.signatureParameters.hash.algorithmOid];if(d===undefined||e.md[d]===undefined)throw{message:"Unsupported RSASSA-PSS hash function.",oid:s.signatureParameters.hash.algorithmOid,name:d};p=e.pss.create(e.md[d].create(),v,s.signatureParameters.saltLength)}o=i.publicKey.verify(f.digest().getBytes(),s.signature,p)}return o},i.isIssuer=function(e){var t=!1,n=i.issuer,r=e.subject;if(n.hash&&r.hash)t=n.hash===r.hash;else if(n.attributes.length===r.attributes.length){t=!0;var s,o;for(var u=0;t&&u<n.attributes.length;++u){s=n.attributes[u],o=r.attributes[u];if(s.type!==o.type||s.value!==o.value)t=!1}}return t},i.issued=function(e){return e.isIssuer(i)},i.generateSubjectKeyIdentifier=function(){var r=t.toDer(n.publicKeyToRSAPublicKey(i.publicKey)),s=e.md.sha1.create();return s.update(r.getBytes()),s.digest()},i.verifySubjectKeyIdentifier=function(){var t=r.subjectKeyIdentifier;for(var n=0;n<i.extensions.length;++n){var s=i.extensions[n];if(s.id===t){var o=i.generateSubjectKeyIdentifier().getBytes();return e.util.hexToBytes(s.subjectKeyIdentifier)===o}}return!1},i},n.certificateFromAsn1=function(i,s){var u={},a=[];if(!t.validate(i,o,u,a))throw{message:"Cannot read X.509 certificate. ASN.1 object is not an X509v3 Certificate.",errors:a};if(typeof u.certSignature!="string"){var f="\0";for(var p=0;p<u.certSignature.length;++p)f+=t.toDer(u.certSignature[p]).getBytes();u.certSignature=f}var d=t.derToOid(u.publicKeyOid);if(d!==n.oids.rsaEncryption)throw{message:"Cannot read public key. OID is not RSA."};var v=n.createCertificate();v.version=u.certVersion?u.certVersion.charCodeAt(0):0;var g=e.util.createBuffer(u.certSerialNumber);v.serialNumber=g.toHex(),v.signatureOid=e.asn1.derToOid(u.certSignatureOid),v.signatureParameters=h(v.signatureOid,u.certSignatureParams,!0),v.siginfo.algorithmOid=e.asn1.derToOid(u.certinfoSignatureOid),v.siginfo.parameters=h(v.siginfo.algorithmOid,u.certinfoSignatureParams,!1);var y=e.util.createBuffer(u.certSignature);++y.read,v.signature=y.getBytes();var b=[];u.certValidity1UTCTime!==undefined&&b.push(t.utcTimeToDate(u.certValidity1UTCTime)),u.certValidity2GeneralizedTime!==undefined&&b.push(t.generalizedTimeToDate(u.certValidity2GeneralizedTime)),u.certValidity3UTCTime!==undefined&&b.push(t.utcTimeToDate(u.certValidity3UTCTime)),u.certValidity4GeneralizedTime!==undefined&&b.push(t.generalizedTimeToDate(u.certValidity4GeneralizedTime));if(b.length>2)throw{message:"Cannot read notBefore/notAfter validity times; more than two times were provided in the certificate."};if(b.length<2)throw{message:"Cannot read notBefore/notAfter validity times; they were not provided as either UTCTime or GeneralizedTime."};v.validity.notBefore=b[0],v.validity.notAfter=b[1],v.tbsCertificate=u.tbsCertificate;if(s){v.md=null;if(v.signatureOid in r){var d=r[v.signatureOid];switch(d){case"sha1WithRSAEncryption":v.md=e.md.sha1.create();break;case"md5WithRSAEncryption":v.md=e.md.md5.create();break;case"sha256WithRSAEncryption":v.md=e.md.sha256.create();break;case"RSASSA-PSS":v.md=e.md.sha256.create()}}if(v.md===null)throw{message:"Could not compute certificate digest. Unknown signature OID.",signatureOid:v.signatureOid};var w=t.toDer(v.tbsCertificate);v.md.update(w.getBytes())}var E=e.md.sha1.create();v.issuer.getField=function(e){return l(v.issuer,e)},v.issuer.addField=function(e){m([e]),v.issuer.attributes.push(e)},v.issuer.attributes=n.RDNAttributesAsArray(u.certIssuer,E),u.certIssuerUniqueId&&(v.issuer.uniqueId=u.certIssuerUniqueId),v.issuer.hash=E.digest().toHex();var S=e.md.sha1.create();return v.subject.getField=function(e){return l(v.subject,e)},v.subject.addField=function(e){m([e]),v.subject.attributes.push(e)},v.subject.attributes=n.RDNAttributesAsArray(u.certSubject,S),u.certSubjectUniqueId&&(v.subject.uniqueId=u.certSubjectUniqueId),v.subject.hash=S.digest().toHex(),u.certExtensions?v.extensions=c(u.certExtensions):v.extensions=[],v.publicKey=n.publicKeyFromAsn1(u.subjectPublicKeyInfo),v},n.certificationRequestFromAsn1=function(i,s){var o={},u=[];if(!t.validate(i,f,o,u))throw{message:"Cannot read PKCS#10 certificate request. ASN.1 object is not a PKCS#10 CertificationRequest.",errors:u};if(typeof o.csrSignature!="string"){var a="\0";for(var c=0;c<o.csrSignature.length;++c)a+=t.toDer(o.csrSignature[c]).getBytes();o.csrSignature=a}var p=t.derToOid(o.publicKeyOid);if(p!==n.oids.rsaEncryption)throw{message:"Cannot read public key. OID is not RSA."};var d=n.createCertificationRequest();d.version=o.csrVersion?o.csrVersion.charCodeAt(0):0,d.signatureOid=e.asn1.derToOid(o.csrSignatureOid),d.signatureParameters=h(d.signatureOid,o.csrSignatureParams,!0),d.siginfo.algorithmOid=e.asn1.derToOid(o.csrSignatureOid),d.siginfo.parameters=h(d.siginfo.algorithmOid,o.csrSignatureParams,!1);var v=e.util.createBuffer(o.csrSignature);++v.read,d.signature=v.getBytes(),d.certificationRequestInfo=o.certificationRequestInfo;if(s){d.md=null;if(d.signatureOid in r){var p=r[d.signatureOid];switch(p){case"sha1WithRSAEncryption":d.md=e.md.sha1.create();break;case"md5WithRSAEncryption":d.md=e.md.md5.create();break;case"sha256WithRSAEncryption":d.md=e.md.sha256.create();break;case"RSASSA-PSS":d.md=e.md.sha256.create()}}if(d.md===null)throw{message:"Could not compute certification request digest. Unknown signature OID.",signatureOid:d.signatureOid};var g=t.toDer(d.certificationRequestInfo);d.md.update(g.getBytes())}var y=e.md.sha1.create();return d.subject.getField=function(e){return l(d.subject,e)},d.subject.addField=function(e){m([e]),d.subject.attributes.push(e)},d.subject.attributes=n.RDNAttributesAsArray(o.certificationRequestInfoSubject,y),d.subject.hash=y.digest().toHex(),d.publicKey=n.publicKeyFromAsn1(o.subjectPublicKeyInfo),d.getAttribute=function(e){return l(d.attributes,e)},d.addAttribute=function(e){m([e]),d.attributes.push(e)},d.attributes=n.CRIAttributesAsArray(o.certificationRequestInfoAttributes),d},n.createCertificationRequest=function(){var i={};return i.version=0,i.signatureOid=null,i.signature=null,i.siginfo={},i.siginfo.algorithmOid=null,i.subject={},i.subject.getField=function(e){return l(i.subject,e)},i.subject.addField=function(e){m([e]),i.subject.attributes.push(e)},i.subject.attributes=[],i.subject.hash=null,i.publicKey=null,i.attributes=[],i.getAttribute=function(e){return l(i.attributes,e)},i.addAttribute=function(e){m([e]),i.attributes.push(e)},i.md=null,i.setSubject=function(e){m(e),i.subject.attributes=e,i.subject.hash=null},i.setAttributes=function(e){m(e),i.attributes=e},i.sign=function(s,o){i.md=o||e.md.sha1.create();var u=r[i.md.algorithm+"WithRSAEncryption"];if(!u)throw{message:"Could not compute certification request digest. Unknown message digest algorithm OID.",algorithm:i.md.algorithm};i.signatureOid=i.siginfo.algorithmOid=u,i.certificationRequestInfo=n.getCertificationRequestInfo(i);var a=t.toDer(i.certificationRequestInfo);i.md.update(a.getBytes()),i.signature=s.sign(i.md)},i.verify=function(){var s=!1,o=i.md;if(o===null){if(i.signatureOid in r){var u=r[i.signatureOid];switch(u){case"sha1WithRSAEncryption":o=e.md.sha1.create();break;case"md5WithRSAEncryption":o=e.md.md5.create();break;case"sha256WithRSAEncryption":o=e.md.sha256.create();break;case"RSASSA-PSS":o=e.md.sha256.create()}}if(o===null)throw{message:"Could not compute certification request digest. Unknown signature OID.",signatureOid:i.signatureOid};var a=i.certificationRequestInfo||n.getCertificationRequestInfo(i),f=t.toDer(a);o.update(f.getBytes())}if(o!==null){var l;switch(i.signatureOid){case r.sha1WithRSAEncryption:break;case r["RSASSA-PSS"]:var c,h;c=r[i.signatureParameters.mgf.hash.algorithmOid];if(c===undefined||e.md[c]===undefined)throw{message:"Unsupported MGF hash function.",oid:i.signatureParameters.mgf.hash.algorithmOid,name:c};h=r[i.signatureParameters.mgf.algorithmOid];if(h===undefined||e.mgf[h]===undefined)throw{message:"Unsupported MGF function.",oid:i.signatureParameters.mgf.algorithmOid,name:h};h=e.mgf[h].create(e.md[c].create()),c=r[i.signatureParameters.hash.algorithmOid];if(c===undefined||e.md[c]===undefined)throw{message:"Unsupported RSASSA-PSS hash function.",oid:i.signatureParameters.hash.algorithmOid,name:c};l=e.pss.create(e.md[c].create(),h,i.signatureParameters.saltLength)}s=i.publicKey.verify(o.digest().getBytes(),i.signature,l)}return s},i},n.getTBSCertificate=function(r){var i=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.CONTEXT_SPECIFIC,0,!0,[t.create(t.Class.UNIVERSAL,t.Type.INTEGER,!1,t.integerToDer(r.version).getBytes())]),t.create(t.Class.UNIVERSAL,t.Type.INTEGER,!1,e.util.hexToBytes(r.serialNumber)),t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(r.siginfo.algorithmOid).getBytes()),g(r.siginfo.algorithmOid,r.siginfo.parameters)]),p(r.issuer),t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.UTCTIME,!1,t.dateToUtcTime(r.validity.notBefore)),t.create(t.Class.UNIVERSAL,t.Type.UTCTIME,!1,t.dateToUtcTime(r.validity.notAfter))]),p(r.subject),n.publicKeyToAsn1(r.publicKey)]);return r.issuer.uniqueId&&i.value.push(t.create(t.Class.CONTEXT_SPECIFIC,1,!0,[t.create(t.Class.UNIVERSAL,t.Type.BITSTRING,!1,String.fromCharCode(0)+r.issuer.uniqueId)])),r.subject.uniqueId&&i.value.push(t.create(t.Class.CONTEXT_SPECIFIC,2,!0,[t.create(t.Class.UNIVERSAL,t.Type.BITSTRING,!1,String.fromCharCode(0)+r.subject.uniqueId)])),r.extensions.length>0&&i.value.push(d(r.extensions)),i},n.getCertificationRequestInfo=function(e){var r=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.INTEGER,!1,t.integerToDer(e.version).getBytes()),p(e.subject),n.publicKeyToAsn1(e.publicKey),y(e)]);return r},n.distinguishedNameToAsn1=function(e){return p(e)},n.certificateToAsn1=function(e){var r=e.tbsCertificate||n.getTBSCertificate(e);return t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[r,t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(e.signatureOid).getBytes()),g(e.signatureOid,e.signatureParameters)]),t.create(t.Class.UNIVERSAL,t.Type.BITSTRING,!1,String.fromCharCode(0)+e.signature)])},n.certificationRequestToAsn1=function(e){var r=e.certificationRequestInfo||n.getCertificationRequestInfo(e);return t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[r,t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(e.signatureOid).getBytes()),g(e.signatureOid,e.signatureParameters)]),t.create(t.Class.UNIVERSAL,t.Type.BITSTRING,!1,String.fromCharCode(0)+e.signature)])},n.createCaStore=function(t){var r={certs:{}};r.getIssuer=function(t){var i=null;if(!t.issuer.hash){var s=e.md.sha1.create();t.issuer.attributes=n.RDNAttributesAsArray(p(t.issuer),s),t.issuer.hash=s.digest().toHex()}if(t.issuer.hash in r.certs){i=r.certs[t.issuer.hash];if(e.util.isArray(i))throw{message:"Resolving multiple issuer matches not implemented yet."}}return i},r.addCertificate=function(t){typeof t=="string"&&(t=e.pki.certificateFromPem(t));if(!t.subject.hash){var i=e.md.sha1.create();t.subject.attributes=n.RDNAttributesAsArray(p(t.subject),i),t.subject.hash=i.digest().toHex()}if(t.subject.hash in r.certs){var s=r.certs[t.subject.hash];e.util.isArray(s)||(s=[s]),s.push(t)}else r.certs[t.subject.hash]=t};if(t)for(var i=0;i<t.length;++i){var s=t[i];r.addCertificate(s)}return r},n.certificateError={bad_certificate:"forge.pki.BadCertificate",unsupported_certificate:"forge.pki.UnsupportedCertificate",certificate_revoked:"forge.pki.CertificateRevoked",certificate_expired:"forge.pki.CertificateExpired",certificate_unknown:"forge.pki.CertificateUnknown",unknown_ca:"forge.pki.UnknownCertificateAuthority"},n.verifyCertificateChain=function(t,r,i){r=r.slice(0);var s=r.slice(0),o=new Date,u=!0,a=null,f=0,l=null;do{var c=r.shift();if(o<c.validity.notBefore||o>c.validity.notAfter)a={message:"Certificate is not valid yet or has expired.",error:n.certificateError.certificate_expired,notBefore:c.validity.notBefore,notAfter:c.validity.notAfter,now:o};else{var h=!1;if(r.length>0){l=r[0];try{h=l.verify(c)}catch(p){}}else{var d=t.getIssuer(c);if(d===null)a={message:"Certificate is not trusted.",error:n.certificateError.unknown_ca};else{e.util.isArray(d)||(d=[d]);while(!h&&d.length>0){l=d.shift();try{h=l.verify(c)}catch(p){}}}}a===null&&!h&&(a={message:"Certificate signature is invalid.",error:n.certificateError.bad_certificate})}a===null&&!c.isIssuer(l)&&(a={message:"Certificate issuer is invalid.",error:n.certificateError.bad_certificate});if(a===null){var v={keyUsage:!0,basicConstraints:!0};for(var m=0;a===null&&m<c.extensions.length;++m){var g=c.extensions[m];g.critical&&!(g.name in v)&&(a={message:"Certificate has an unsupported critical extension.",error:n.certificateError.unsupported_certificate})}}if(!u||r.length===0&&!l){var y=c.getExtension("basicConstraints"),b=c.getExtension("keyUsage");b!==null&&(!b.keyCertSign||y===null)&&(a={message:"Certificate keyUsage or basicConstraints conflict or indicate that the certificate is not a CA. If the certificate is the only one in the chain or isn't the first then the certificate must be a valid CA.",error:n.certificateError.bad_certificate}),a===null&&y!==null&&!y.cA&&(a={message:"Certificate basicConstraints indicates the certificate is not a CA.",error:n.certificateError.bad_certificate});if(a===null&&b!==null&&"pathLenConstraint"in y){var w=0;for(var m=1;m<r.length-1;++m)r[m].isIssuer(r[m])&&++w;var E=y.pathLenConstraint+1;r.length-w>E&&(a={message:"Certificate basicConstraints pathLenConstraint violated.",error:n.certificateError.bad_certificate})}}var S=a===null?!0:a.error,x=i?i(S,f,s):S;if(x!==!0){S===!0&&(a={message:"The application rejected the certificate.",error:n.certificateError.bad_certificate});if(x||x===0)typeof x=="object"&&!e.util.isArray(x)?(x.message&&(a.message=x.message),x.error&&(a.error=x.error)):typeof x=="string"&&(a.error=x);throw a}a=null,u=!1,++f}while(r.length>0);return!0}}var r="x509";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n.pki}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/x509",["require","module","./aes","./asn1","./des","./md","./mgf","./oids","./pem","./pss","./rsa","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){function f(e,t,n,r){var i=[];for(var s=0;s<e.length;s++)for(var o=0;o<e[s].safeBags.length;o++){var u=e[s].safeBags[o];if(r!==undefined&&u.type!==r)continue;u.attributes[t]!==undefined&&u.attributes[t].indexOf(n)>=0&&i.push(u)}return i}function l(e,r,s,o){r=t.fromDer(r,s);if(r.tagClass!==t.Class.UNIVERSAL||r.type!==t.Type.SEQUENCE||r.constructed!==!0)throw{message:"PKCS#12 AuthenticatedSafe expected to be a SEQUENCE OF ContentInfo"};for(var u=0;u<r.value.length;u++){var a=r.value[u],f={},l=[];if(!t.validate(a,i,f,l))throw{message:"Cannot read ContentInfo.",errors:l};var p={encrypted:!1},d=null,v=f.content.value[0];switch(t.derToOid(f.contentType)){case n.oids.data:if(v.tagClass!==t.Class.UNIVERSAL||v.type!==t.Type.OCTETSTRING)throw{message:"PKCS#12 SafeContents Data is not an OCTET STRING."};d=v.value;break;case n.oids.encryptedData:if(o===undefined)throw{message:"Found PKCS#12 Encrypted SafeContents Data but no password available."};d=c(v,o),p.encrypted=!0;break;default:throw{message:"Unsupported PKCS#12 contentType.",contentType:t.derToOid(f.contentType)}}p.safeBags=h(d,s,o),e.safeContents.push(p)}}function c(r,i){var s={},o=[];if(!t.validate(r,e.pkcs7.asn1.encryptedDataValidator,s,o))throw{message:"Cannot read EncryptedContentInfo. ",errors:o};var u=t.derToOid(s.contentType);if(u!==n.oids.data)throw{message:"PKCS#12 EncryptedContentInfo ContentType is not Data.",oid:u};u=t.derToOid(s.encAlgorithm);var a=n.pbe.getCipher(u,s.encParameter,i),f=e.util.createBuffer(s.encryptedContent);a.update(f);if(!a.finish())throw{message:"Failed to decrypt PKCS#12 SafeContents."};return a.output.getBytes()}function h(e,r,i){e=t.fromDer(e,r);if(e.tagClass!==t.Class.UNIVERSAL||e.type!==t.Type.SEQUENCE||e.constructed!==!0)throw{message:"PKCS#12 SafeContents expected to be a SEQUENCE OF SafeBag"};var s=[];for(var u=0;u<e.value.length;u++){var f=e.value[u],l={},c=[];if(!t.validate(f,o,l,c))throw{message:"Cannot read SafeBag.",errors:c};var h={type:t.derToOid(l.bagId),attributes:p(l.bagAttributes)};s.push(h);var d,v,m=l.bagValue.value[0];switch(h.type){case n.oids.pkcs8ShroudedKeyBag:if(i===undefined)throw{message:"Found PKCS#8 ShroudedKeyBag but no password available."};m=n.decryptPrivateKeyInfo(m,i);if(m===null)throw{message:"Unable to decrypt PKCS#8 ShroudedKeyBag, wrong password?"};case n.oids.keyBag:h.key=n.privateKeyFromAsn1(m);continue;case n.oids.certBag:d=a,v=function(){if(t.derToOid(l.certId)!==n.oids.x509Certificate)throw{message:"Unsupported certificate type, only X.509 supported.",oid:t.derToOid(l.certId)};h.cert=n.certificateFromAsn1(t.fromDer(l.cert,r),!0)};break;default:throw{message:"Unsupported PKCS#12 SafeBag type.",oid:h.type}}if(d!==undefined&&!t.validate(m,d,l,c))throw{message:"Cannot read PKCS#12 "+d.name,errors:c};v()}return s}function p(e){var r={};if(e!==undefined)for(var i=0;i<e.length;++i){var s={},o=[];if(!t.validate(e[i],u,s,o))throw{message:"Cannot read PKCS#12 BagAttribute.",errors:o};var a=t.derToOid(s.oid);if(n.oids[a]===undefined)continue;r[n.oids[a]]=[];for(var f=0;f<s.values.length;++f)r[n.oids[a]].push(s.values[f].value)}return r}var t=e.asn1,n=e.pki,r=e.pkcs12=e.pkcs12||{},i={name:"ContentInfo",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"ContentInfo.contentType",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1,capture:"contentType"},{name:"ContentInfo.content",tagClass:t.Class.CONTEXT_SPECIFIC,constructed:!0,captureAsn1:"content"}]},s={name:"PFX",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"PFX.version",tagClass:t.Class.UNIVERSAL,type:t.Type.INTEGER,constructed:!1,capture:"version"},i,{name:"PFX.macData",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,optional:!0,captureAsn1:"mac",value:[{name:"PFX.macData.mac",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"PFX.macData.mac.digestAlgorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"PFX.macData.mac.digestAlgorithm.algorithm",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1,capture:"macAlgorithm"},{name:"PFX.macData.mac.digestAlgorithm.parameters",tagClass:t.Class.UNIVERSAL,captureAsn1:"macAlgorithmParameters"}]},{name:"PFX.macData.mac.digest",tagClass:t.Class.UNIVERSAL,type:t.Type.OCTETSTRING,constructed:!1,capture:"macDigest"}]},{name:"PFX.macData.macSalt",tagClass:t.Class.UNIVERSAL,type:t.Type.OCTETSTRING,constructed:!1,capture:"macSalt"},{name:"PFX.macData.iterations",tagClass:t.Class.UNIVERSAL,type:t.Type.INTEGER,constructed:!1,optional:!0,capture:"macIterations"}]}]},o={name:"SafeBag",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"SafeBag.bagId",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1,capture:"bagId"},{name:"SafeBag.bagValue",tagClass:t.Class.CONTEXT_SPECIFIC,constructed:!0,captureAsn1:"bagValue"},{name:"SafeBag.bagAttributes",tagClass:t.Class.UNIVERSAL,type:t.Type.SET,constructed:!0,optional:!0,capture:"bagAttributes"}]},u={name:"Attribute",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"Attribute.attrId",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1,capture:"oid"},{name:"Attribute.attrValues",tagClass:t.Class.UNIVERSAL,type:t.Type.SET,constructed:!0,capture:"values"}]},a={name:"CertBag",tagClass:t.Class.UNIVERSAL,type:t.Type.SEQUENCE,constructed:!0,value:[{name:"CertBag.certId",tagClass:t.Class.UNIVERSAL,type:t.Type.OID,constructed:!1,capture:"certId"},{name:"CertBag.certValue",tagClass:t.Class.CONTEXT_SPECIFIC,constructed:!0,value:[{name:"CertBag.certValue[0]",tagClass:t.Class.UNIVERSAL,type:t.Class.OCTETSTRING,constructed:!1,capture:"cert"}]}]};r.pkcs12FromAsn1=function(i,o,u){typeof o=="string"?(u=o,o=!0):o===undefined&&(o=!0);var a={},c=[];if(!t.validate(i,s,a,c))throw{message:"Cannot read PKCS#12 PFX. ASN.1 object is not an PKCS#12 PFX.",errors:c};var h={version:a.version.charCodeAt(0),safeContents:[],getBags:function(t){var n={},r;return"localKeyId"in t?r=t.localKeyId:"localKeyIdHex"in t&&(r=e.util.hexToBytes(t.localKeyIdHex)),r!==undefined&&(n.localKeyId=f(h.safeContents,"localKeyId",r,t.bagType)),"friendlyName"in t&&(n.friendlyName=f(h.safeContents,"friendlyName",t.friendlyName,t.bagType)),n},getBagsByFriendlyName:function(e,t){return f(h.safeContents,"friendlyName",e,t)},getBagsByLocalKeyId:function(e,t){return f(h.safeContents,"localKeyId",e,t)}};if(a.version.charCodeAt(0)!==3)throw{message:"PKCS#12 PFX of version other than 3 not supported.",version:a.version.charCodeAt(0)};if(t.derToOid(a.contentType)!==n.oids.data)throw{message:"Only PKCS#12 PFX in password integrity mode supported.",oid:t.derToOid(a.contentType)};var p=a.content.value[0];if(p.tagClass!==t.Class.UNIVERSAL||p.type!==t.Type.OCTETSTRING)throw{message:"PKCS#12 authSafe content data is not an OCTET STRING."};if(a.mac){var d=null,v=0,m=t.derToOid(a.macAlgorithm);switch(m){case n.oids.sha1:d=e.md.sha1.create(),v=20;break;case n.oids.sha256:d=e.md.sha256.create(),v=32;break;case n.oids.sha384:d=e.md.sha384.create(),v=48;break;case n.oids.sha512:d=e.md.sha512.create(),v=64;break;case n.oids.md5:d=e.md.md5.create(),v=16}if(d===null)throw{message:"PKCS#12 uses unsupported MAC algorithm: "+m};var g=new e.util.ByteBuffer(a.macSalt),y="macIterations"in a?parseInt(e.util.bytesToHex(a.macIterations),16):1,b=r.generateKey(u||"",g,3,y,v,d),w=e.hmac.create();w.start(d,b),w.update(p.value);var E=w.getMac();if(E.getBytes()!==a.macDigest)throw{message:"PKCS#12 MAC could not be verified. Invalid password?"}}return l(h,p.value,o,u),h},r.toPkcs12Asn1=function(i,s,o,u){u=u||{},u.saltSize=u.saltSize||8,u.count=u.count||2048,u.algorithm=u.algorithm||u.encAlgorithm||"aes128","useMac"in u||(u.useMac=!0),"localKeyId"in u||(u.localKeyId=null),"generateLocalKeyId"in u||(u.generateLocalKeyId=!0);var a=u.localKeyId,f;if(a!==null)a=e.util.hexToBytes(a);else if(u.generateLocalKeyId)if(s){var l=e.util.isArray(s)?s[0]:s;typeof l=="string"&&(l=n.certificateFromPem(l));var c=e.md.sha1.create();c.update(t.toDer(n.certificateToAsn1(l)).getBytes()),a=c.digest().getBytes()}else a=e.random.getBytes(20);var h=[];a!==null&&h.push(t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(n.oids.localKeyId).getBytes()),t.create(t.Class.UNIVERSAL,t.Type.SET,!0,[t.create(t.Class.UNIVERSAL,t.Type.OCTETSTRING,!1,a)])])),"friendlyName"in u&&h.push(t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(n.oids.friendlyName).getBytes()),t.create(t.Class.UNIVERSAL,t.Type.SET,!0,[t.create(t.Class.UNIVERSAL,t.Type.BMPSTRING,!1,u.friendlyName)])])),h.length>0&&(f=t.create(t.Class.UNIVERSAL,t.Type.SET,!0,h));var p=[],d=[];s!==null&&(e.util.isArray(s)?d=s:d=[s]);var v=[];for(var m=0;m<d.length;++m){s=d[m],typeof s=="string"&&(s=n.certificateFromPem(s));var g=m===0?f:undefined,y=n.certificateToAsn1(s),b=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(n.oids.certBag).getBytes()),t.create(t.Class.CONTEXT_SPECIFIC,0,!0,[t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(n.oids.x509Certificate).getBytes()),t.create(t.Class.CONTEXT_SPECIFIC,0,!0,[t.create(t.Class.UNIVERSAL,t.Type.OCTETSTRING,!1,t.toDer(y).getBytes())])])]),g]);v.push(b)}if(v.length>0){var w=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,v),E=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(n.oids.data).getBytes()),t.create(t.Class.CONTEXT_SPECIFIC,0,!0,[t.create(t.Class.UNIVERSAL,t.Type.OCTETSTRING,!1,t.toDer(w).getBytes())])]);p.push(E)}var S=null;if(i!==null){var x=n.wrapRsaPrivateKey(n.privateKeyToAsn1(i));o===null?S=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(n.oids.keyBag).getBytes()),t.create(t.Class.CONTEXT_SPECIFIC,0,!0,[x]),f]):S=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(n.oids.pkcs8ShroudedKeyBag).getBytes()),t.create(t.Class.CONTEXT_SPECIFIC,0,!0,[n.encryptPrivateKeyInfo(x,o,u)]),f]);var T=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[S]),N=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(n.oids.data).getBytes()),t.create(t.Class.CONTEXT_SPECIFIC,0,!0,[t.create(t.Class.UNIVERSAL,t.Type.OCTETSTRING,!1,t.toDer(T).getBytes())])]);p.push(N)}var C=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,p),k;if(u.useMac){var c=e.md.sha1.create(),L=new e.util.ByteBuffer(e.random.getBytes(u.saltSize)),A=u.count,i=r.generateKey(o||"",L,3,A,20),O=e.hmac.create();O.start(c,i),O.update(t.toDer(C).getBytes());var M=O.getMac();k=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(n.oids.sha1).getBytes()),t.create(t.Class.UNIVERSAL,t.Type.NULL,!1,"")]),t.create(t.Class.UNIVERSAL,t.Type.OCTETSTRING,!1,M.getBytes())]),t.create(t.Class.UNIVERSAL,t.Type.OCTETSTRING,!1,L.getBytes()),t.create(t.Class.UNIVERSAL,t.Type.INTEGER,!1,t.integerToDer(A).getBytes())])}return t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.INTEGER,!1,t.integerToDer(3).getBytes()),t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(n.oids.data).getBytes()),t.create(t.Class.CONTEXT_SPECIFIC,0,!0,[t.create(t.Class.UNIVERSAL,t.Type.OCTETSTRING,!1,t.toDer(C).getBytes())])]),k])},r.generateKey=e.pbe.generatePkcs12Key}var r="pkcs12";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/pkcs12",["require","module","./asn1","./hmac","./oids","./pkcs7asn1","./pbe","./random","./rsa","./sha1","./util","./x509"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){var t=e.asn1,n=e.pki=e.pki||{};n.pemToDer=function(t){var n=e.pem.decode(t)[0];if(n.procType&&n.procType.type==="ENCRYPTED")throw{message:"Could not convert PEM to DER; PEM is encrypted."};return e.util.createBuffer(n.body)},n.privateKeyFromPem=function(r){var i=e.pem.decode(r)[0];if(i.type!=="PRIVATE KEY"&&i.type!=="RSA PRIVATE KEY")throw{message:'Could not convert private key from PEM; PEM header type is not "PRIVATE KEY" or "RSA PRIVATE KEY".',headerType:i.type};if(i.procType&&i.procType.type==="ENCRYPTED")throw{message:"Could not convert private key from PEM; PEM is encrypted."};var s=t.fromDer(i.body);return n.privateKeyFromAsn1(s)},n.privateKeyToPem=function(r,i){var s={type:"RSA PRIVATE KEY",body:t.toDer(n.privateKeyToAsn1(r)).getBytes()};return e.pem.encode(s,{maxline:i})}}var r="pki";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/pki",["require","module","./asn1","./oids","./pbe","./pem","./pbkdf2","./pkcs12","./pss","./rsa","./util","./x509"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){var t=function(t,n,r,i){var s=e.util.createBuffer(),o=t.length>>1,u=o+(t.length&1),a=t.substr(0,u),f=t.substr(o,u),l=e.util.createBuffer(),c=e.hmac.create();r=n+r;var h=Math.ceil(i/16),p=Math.ceil(i/20);c.start("MD5",a);var d=e.util.createBuffer();l.putBytes(r);for(var v=0;v<h;++v)c.start(null,null),c.update(l.getBytes()),l.putBuffer(c.digest()),c.start(null,null),c.update(l.bytes()+r),d.putBuffer(c.digest());c.start("SHA1",f);var m=e.util.createBuffer();l.clear(),l.putBytes(r);for(var v=0;v<p;++v)c.start(null,null),c.update(l.getBytes()),l.putBuffer(c.digest()),c.start(null,null),c.update(l.bytes()+r),m.putBuffer(c.digest());return s.putBytes(e.util.xorBytes(d.getBytes(),m.getBytes(),i)),s},n=function(e,t,n,r){},r=function(t,n,r){var i=e.hmac.create();i.start("SHA1",t);var s=e.util.createBuffer();return s.putInt32(n[0]),s.putInt32(n[1]),s.putByte(r.type),s.putByte(r.version.major),s.putByte(r.version.minor),s.putInt16(r.length),s.putBytes(r.fragment.bytes()),i.update(s.getBytes()),i.digest().getBytes()},i=function(t,n,r){var i=!1;try{var s=t.deflate(n.fragment.getBytes());n.fragment=e.util.createBuffer(s),n.length=s.length,i=!0}catch(o){}return i},s=function(t,n,r){var i=!1;try{var s=t.inflate(n.fragment.getBytes());n.fragment=e.util.createBuffer(s),n.length=s.length,i=!0}catch(o){}return i},o=function(t,n){var r=0;switch(n){case 1:r=t.getByte();break;case 2:r=t.getInt16();break;case 3:r=t.getInt24();break;case 4:r=t.getInt32()}return e.util.createBuffer(t.getBytes(r))},u=function(e,t,n){e.putInt(n.length(),t<<3),e.putBuffer(n)},a={};a.Version={major:3,minor:1},a.MaxFragment=15360,a.ConnectionEnd={server:0,client:1},a.PRFAlgorithm={tls_prf_sha256:0},a.BulkCipherAlgorithm={none:null,rc4:0,des3:1,aes:2},a.CipherType={stream:0,block:1,aead:2},a.MACAlgorithm={none:null,hmac_md5:0,hmac_sha1:1,hmac_sha256:2,hmac_sha384:3,hmac_sha512:4},a.CompressionMethod={none:0,deflate:1},a.ContentType={change_cipher_spec:20,alert:21,handshake:22,application_data:23},a.HandshakeType={hello_request:0,client_hello:1,server_hello:2,certificate:11,server_key_exchange:12,certificate_request:13,server_hello_done:14,certificate_verify:15,client_key_exchange:16,finished:20},a.Alert={},a.Alert.Level={warning:1,fatal:2},a.Alert.Description={close_notify:0,unexpected_message:10,bad_record_mac:20,decryption_failed:21,record_overflow:22,decompression_failure:30,handshake_failure:40,bad_certificate:42,unsupported_certificate:43,certificate_revoked:44,certificate_expired:45,certificate_unknown:46,illegal_parameter:47,unknown_ca:48,access_denied:49,decode_error:50,decrypt_error:51,export_restriction:60,protocol_version:70,insufficient_security:71,internal_error:80,user_canceled:90,no_renegotiation:100},a.CipherSuites={},a.getCipherSuite=function(e){var t=null;for(var n in a.CipherSuites){var r=a.CipherSuites[n];if(r.id[0]===e.charCodeAt(0)&&r.id[1]===e.charCodeAt(1)){t=r;break}}return t},a.handleUnexpected=function(e,t){var n=!e.open&&e.entity===a.ConnectionEnd.client;n||e.error(e,{message:"Unexpected message. Received TLS record out of order.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.unexpected_message}})},a.handleHelloRequest=function(e,t,n){!e.handshaking&&e.handshakes>0&&(a.queue(e,a.createAlert({level:a.Alert.Level.warning,description:a.Alert.Description.no_renegotiation})),a.flush(e)),e.process()},a.parseHelloMessage=function(t,n,r){var i=null,s=t.entity===a.ConnectionEnd.client;if(r<38)t.error(t,{message:s?"Invalid ServerHello message. Message too short.":"Invalid ClientHello message. Message too short.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.illegal_parameter}});else{var u=n.fragment,f=u.length();i={version:{major:u.getByte(),minor:u.getByte()},random:e.util.createBuffer(u.getBytes(32)),session_id:o(u,1),extensions:[]},s?(i.cipher_suite=u.getBytes(2),i.compression_method=u.getByte()):(i.cipher_suites=o(u,2),i.compression_methods=o(u,1)),f=r-(f-u.length());if(f>0){var l=o(u,2);while(l.length()>0)i.extensions.push({type:[l.getByte(),l.getByte()],data:o(l,2)});if(!s)for(var c=0;c<i.extensions.length;++c){var h=i.extensions[c];if(h.type[0]===0&&h.type[1]===0){var p=o(h.data,2);while(p.length()>0){var d=p.getByte();if(d!==0)break;t.session.serverNameList.push(o(p,2).getBytes())}}}}(i.version.major!==a.Version.major||i.version.minor!==a.Version.minor)&&t.error(t,{message:"Incompatible TLS version.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.protocol_version}});if(s)t.session.cipherSuite=a.getCipherSuite(i.cipher_suite);else{var v=e.util.createBuffer(i.cipher_suites.bytes());while(v.length()>0){t.session.cipherSuite=a.getCipherSuite(v.getBytes(2));if(t.session.cipherSuite!==null)break}}if(t.session.cipherSuite===null)return t.error(t,{message:"No cipher suites in common.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.handshake_failure},cipherSuite:e.util.bytesToHex(i.cipher_suite)});s?t.session.compressionMethod=i.compression_method:t.session.compressionMethod=a.CompressionMethod.none}return i},a.createSecurityParameters=function(e,t){var n=e.entity===a.ConnectionEnd.client,r=t.random.bytes(),i=n?e.session.sp.client_random:r,s=n?r:a.createRandom().getBytes();e.session.sp={entity:e.entity,prf_algorithm:a.PRFAlgorithm.tls_prf_sha256,bulk_cipher_algorithm:null,cipher_type:null,enc_key_length:null,block_length:null,fixed_iv_length:null,record_iv_length:null,mac_algorithm:null,mac_length:null,mac_key_length:null,compression_algorithm:e.session.compressionMethod,pre_master_secret:null,master_secret:null,client_random:i,server_random:s}},a.handleServerHello=function(e,t,n){var r=a.parseHelloMessage(e,t,n);if(!e.fail){var i=r.session_id.bytes();i.length>0&&i===e.session.id?(e.expect=d,e.session.resuming=!0,e.session.sp.server_random=r.random.bytes()):(e.expect=l,e.session.resuming=!1,a.createSecurityParameters(e,r)),e.session.id=i,e.process()}},a.handleClientHello=function(t,n,r){var i=a.parseHelloMessage(t,n,r);if(!t.fail){var s=i.session_id.bytes(),o=null;t.sessionCache&&(o=t.sessionCache.getSession(s),o===null&&(s="")),s.length===0&&(s=e.random.getBytes(32)),t.session.id=s,t.session.clientHelloVersion=i.version,t.session.sp=o?o.sp:{},o!==null?(t.expect=S,t.session.resuming=!0,t.session.sp.client_random=i.random.bytes()):(t.expect=t.verifyClient!==!1?b:w,t.session.resuming=!1,a.createSecurityParameters(t,i)),t.open=!0,a.queue(t,a.createRecord({type:a.ContentType.handshake,data:a.createServerHello(t)})),t.session.resuming?(a.queue(t,a.createRecord({type:a.ContentType.change_cipher_spec,data:a.createChangeCipherSpec()})),t.state.pending=a.createConnectionState(t),t.state.current.write=t.state.pending.write,a.queue(t,a.createRecord({type:a.ContentType.handshake,data:a.createFinished(t)}))):(a.queue(t,a.createRecord({type:a.ContentType.handshake,data:a.createCertificate(t)})),t.fail||(a.queue(t,a.createRecord({type:a.ContentType.handshake,data:a.createServerKeyExchange(t)})),t.verifyClient!==!1&&a.queue(t,a.createRecord({type:a.ContentType.handshake,data:a.createCertificateRequest(t)})),a.queue(t,a.createRecord({type:a.ContentType.handshake,data:a.createServerHelloDone(t)})))),a.flush(t),t.process()}},a.handleCertificate=function(t,n,r){if(r<3)t.error(t,{message:"Invalid Certificate message. Message too short.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.illegal_parameter}});else{var i=n.fragment,s={certificate_list:o(i,3)},u,f,l=[];try{while(s.certificate_list.length()>0)u=o(s.certificate_list,3),f=e.asn1.fromDer(u),u=e.pki.certificateFromAsn1(f,!0),l.push(u)}catch(h){t.error(t,{message:"Could not parse certificate list.",cause:h,send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.bad_certificate}})}if(!t.fail){var p=t.entity===a.ConnectionEnd.client;!p&&t.verifyClient!==!0||l.length!==0?l.length===0?t.expect=p?c:w:(p?t.session.serverCertificate=l[0]:t.session.clientCertificate=l[0],a.verifyCertificateChain(t,l)&&(t.expect=p?c:w)):t.error(t,{message:p?"No server certificate provided.":"No client certificate provided.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.illegal_parameter}}),t.process()}}},a.handleServerKeyExchange=function(e,t,n){n>0?e.error(e,{message:"Invalid key parameters. Only RSA is supported.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.unsupported_certificate}}):(e.expect=h,e.process())},a.handleClientKeyExchange=function(t,n,r){if(r<48)t.error(t,{message:"Invalid key parameters. Only RSA is supported.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.unsupported_certificate}});else{var i=n.fragment,s={enc_pre_master_secret:o(i,2).getBytes()},u=null;if(t.getPrivateKey)try{u=t.getPrivateKey(t,t.session.serverCertificate),u=e.pki.privateKeyFromPem(u)}catch(f){t.error(t,{message:"Could not get private key.",cause:f,send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.internal_error}})}if(u===null)t.error(t,{message:"No private key set.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.internal_error}});else try{var l=t.session.sp;l.pre_master_secret=u.decrypt(s.enc_pre_master_secret);var c=t.session.clientHelloVersion;if(c.major!==l.pre_master_secret.charCodeAt(0)||c.minor!==l.pre_master_secret.charCodeAt(1))throw{message:"TLS version rollback attack detected."}}catch(f){l.pre_master_secret=e.random.getBytes(48)}}t.fail||(t.expect=S,t.session.clientCertificate!==null&&(t.expect=E),t.process())},a.handleCertificateRequest=function(e,t,n){if(n<3)e.error(e,{message:"Invalid CertificateRequest. Message too short.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.illegal_parameter}});else{var r=t.fragment,i={certificate_types:o(r,1),certificate_authorities:o(r,2)};e.session.certificateRequest=i,e.expect=p,e.process()}},a.handleCertificateVerify=function(t,n,r){if(r<2)t.error(t,{message:"Invalid CertificateVerify. Message too short.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.illegal_parameter}});else{var i=n.fragment;i.read-=4;var s=i.bytes();i.read+=4;var u={signature:o(i,2).getBytes()},f=e.util.createBuffer();f.putBuffer(t.session.md5.digest()),f.putBuffer(t.session.sha1.digest()),f=f.getBytes();try{var l=t.session.clientCertificate;if(!l.publicKey.verify(f,u.signature,"NONE"))throw{message:"CertificateVerify signature does not match."};t.session.md5.update(s),t.session.sha1.update(s)}catch(c){t.error(t,{message:"Bad signature in CertificateVerify.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.handshake_failure}})}t.fail||(t.expect=S,t.process())}},a.handleServerHelloDone=function(t,n,r){if(r>0)t.error(t,{message:"Invalid ServerHelloDone message. Invalid length.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.record_overflow}});else if(t.serverCertificate===null){var i={message:"No server certificate provided. Not enough security.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.insufficient_security}},s=t.verify(t,i.alert.description,depth,[]);if(s===!0)i=null;else{if(s||s===0)typeof s=="object"&&!e.util.isArray(s)?(s.message&&(i.message=s.message),s.alert&&(i.alert.description=s.alert)):typeof s=="number"&&(i.alert.description=s);t.error(t,i)}}!t.fail&&t.session.certificateRequest!==null&&(n=a.createRecord({type:a.ContentType.handshake,data:a.createCertificate(t)}),a.queue(t,n));if(!t.fail){n=a.createRecord({type:a.ContentType.handshake,data:a.createClientKeyExchange(t)}),a.queue(t,n),t.expect=g;var o=function(e,t){e.session.certificateRequest!==null&&e.session.clientCertificate!==null&&a.queue(e,a.createRecord({type:a.ContentType.handshake,data:a.createCertificateVerify(e,t)})),a.queue(e,a.createRecord({type:a.ContentType.change_cipher_spec,data:a.createChangeCipherSpec()})),e.state.pending=a.createConnectionState(e),e.state.current.write=e.state.pending.write,a.queue(e,a.createRecord({type:a.ContentType.handshake,data:a.createFinished(e)})),e.expect=d,a.flush(e),e.process()};t.session.certificateRequest===null||t.session.clientCertificate===null?o(t,null):a.getClientSignature(t,o)}},a.handleChangeCipherSpec=function(e,t){if(t.fragment.getByte()!==1)e.error(e,{message:"Invalid ChangeCipherSpec message received.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.illegal_parameter}});else{var n=e.entity===a.ConnectionEnd.client;if(e.session.resuming&&n||!e.session.resuming&&!n)e.state.pending=a.createConnectionState(e);e.state.current.read=e.state.pending.read;if(!e.session.resuming&&n||e.session.resuming&&!n)e.state.pending=null;e.expect=n?v:x,e.process()}},a.handleFinished=function(n,r,i){var s=r.fragment;s.read-=4;var o=s.bytes();s.read+=4;var u=r.fragment.getBytes();s=e.util.createBuffer(),s.putBuffer(n.session.md5.digest()),s.putBuffer(n.session.sha1.digest());var f=n.entity===a.ConnectionEnd.client,l=f?"server finished":"client finished",c=n.session.sp,h=12,p=t;s=p(c.master_secret,l,s.getBytes(),h);if(s.getBytes()!==u)n.error(n,{message:"Invalid verify_data in Finished message.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.decrypt_error}});else{n.session.md5.update(o),n.session.sha1.update(o);if(n.session.resuming&&f||!n.session.resuming&&!f)a.queue(n,a.createRecord({type:a.ContentType.change_cipher_spec,data:a.createChangeCipherSpec()})),n.state.current.write=n.state.pending.write,n.state.pending=null,a.queue(n,a.createRecord({type:a.ContentType.handshake,data:a.createFinished(n)}));n.expect=f?m:T,n.handshaking=!1,++n.handshakes,n.peerCertificate=f?n.session.serverCertificate:n.session.clientCertificate,n.sessionCache?(n.session={id:n.session.id,sp:n.session.sp},n.session.sp.keys=null):n.session=null,a.flush(n),n.isConnected=!0,n.connected(n),n.process()}},a.handleAlert=function(e,t){var n=t.fragment,r={level:n.getByte(),description:n.getByte()},i;switch(r.description){case a.Alert.Description.close_notify:i="Connection closed.";break;case a.Alert.Description.unexpected_message:i="Unexpected message.";break;case a.Alert.Description.bad_record_mac:i="Bad record MAC.";break;case a.Alert.Description.decryption_failed:i="Decryption failed.";break;case a.Alert.Description.record_overflow:i="Record overflow.";break;case a.Alert.Description.decompression_failure:i="Decompression failed.";break;case a.Alert.Description.handshake_failure:i="Handshake failure.";break;case a.Alert.Description.bad_certificate:i="Bad certificate.";break;case a.Alert.Description.unsupported_certificate:i="Unsupported certificate.";break;case a.Alert.Description.certificate_revoked:i="Certificate revoked.";break;case a.Alert.Description.certificate_expired:i="Certificate expired.";break;case a.Alert.Description.certificate_unknown:i="Certificate unknown.";break;case a.Alert.Description.illegal_parameter:i="Illegal parameter.";break;case a.Alert.Description.unknown_ca:i="Unknown certificate authority.";break;case a.Alert.Description.access_denied:i="Access denied.";break;case a.Alert.Description.decode_error:i="Decode error.";break;case a.Alert.Description.decrypt_error:i="Decrypt error.";break;case a.Alert.Description.export_restriction:i="Export restriction.";break;case a.Alert.Description.protocol_version:i="Unsupported protocol version.";break;case a.Alert.Description.insufficient_security:i="Insufficient security.";break;case a.Alert.Description.internal_error:i="Internal error.";break;case a.Alert.Description.user_canceled:i="User canceled.";break;case a.Alert.Description.no_renegotiation:i="Renegotiation not supported.";break;default:i="Unknown error."}r.description===a.Alert.Description.close_notify?e.close():(e.error(e,{message:i,send:!1,origin:e.entity===a.ConnectionEnd.client?"server":"client",alert:r}),e.process())},a.handleHandshake=function(t,n){var r=n.fragment,i=r.getByte(),s=r.getInt24();if(s>r.length())t.fragmented=n,n.fragment=e.util.createBuffer(),r.read-=4,t.process();else{t.fragmented=null,r.read-=4;var o=r.bytes(s+4);r.read+=4,i in I[t.entity][t.expect]?(t.entity===a.ConnectionEnd.server&&!t.open&&!t.fail&&(t.handshaking=!0,t.session={serverNameList:[],cipherSuite:null,compressionMethod:null,serverCertificate:null,clientCertificate:null,md5:e.md.md5.create(),sha1:e.md.sha1.create()}),i!==a.HandshakeType.hello_request&&i!==a.HandshakeType.certificate_verify&&i!==a.HandshakeType.finished&&(t.session.md5.update(o),t.session.sha1.update(o)),I[t.entity][t.expect][i](t,n,s)):a.handleUnexpected(t,n)}},a.handleApplicationData=function(e,t){e.data.putBuffer(t.fragment),e.dataReady(e),e.process()};var f=0,l=1,c=2,h=3,p=4,d=5,v=6,m=7,g=8,y=0,b=1,w=2,E=3,S=4,x=5,T=6,N=7,C=a.handleUnexpected,k=a.handleChangeCipherSpec,L=a.handleAlert,A=a.handleHandshake,O=a.handleApplicationData,M=[];M[a.ConnectionEnd.client]=[[C,L,A,C],[C,L,A,C],[C,L,A,C],[C,L,A,C],[C,L,A,C],[k,L,C,C],[C,L,A,C],[C,L,A,O],[C,L,A,C]],M[a.ConnectionEnd.server]=[[C,L,A,C],[C,L,A,C],[C,L,A,C],[C,L,A,C],[k,L,C,C],[C,L,A,C],[C,L,A,O],[C,L,A,C]];var _=a.handleHelloRequest,D=a.handleServerHello,P=a.handleCertificate,H=a.handleServerKeyExchange,B=a.handleCertificateRequest,j=a.handleServerHelloDone,F=a.handleFinished,I=[];I[a.ConnectionEnd.client]=[[C,C,D,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C],[_,C,C,C,C,C,C,C,C,C,C,P,H,B,j,C,C,C,C,C,C],[_,C,C,C,C,C,C,C,C,C,C,C,H,B,j,C,C,C,C,C,C],[_,C,C,C,C,C,C,C,C,C,C,C,C,B,j,C,C,C,C,C,C],[_,C,C,C,C,C,C,C,C,C,C,C,C,C,j,C,C,C,C,C,C],[_,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C],[_,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,F],[_,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C],[_,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C]];var q=a.handleClientHello,R=a.handleClientKeyExchange,U=a.handleCertificateVerify;I[a.ConnectionEnd.server]=[[C,q,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C],[C,C,C,C,C,C,C,C,C,C,C,P,C,C,C,C,C,C,C,C,C],[C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,R,C,C,C,C],[C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,U,C,C,C,C,C],[C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C],[C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,F],[C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C],[C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C,C]],a.generateKeys=function(e,n){var r=t,i=n.client_random+n.server_random;e.session.resuming||(n.master_secret=r(n.pre_master_secret,"master secret",i,48).bytes(),n.pre_master_secret=null),i=n.server_random+n.client_random;var s=2*n.mac_key_length+2*n.enc_key_length+2*n.fixed_iv_length,o=r(n.master_secret,"key expansion",i,s);return{client_write_MAC_key:o.getBytes(n.mac_key_length),server_write_MAC_key:o.getBytes(n.mac_key_length),client_write_key:o.getBytes(n.enc_key_length),server_write_key:o.getBytes(n.enc_key_length),client_write_IV:o.getBytes(n.fixed_iv_length),server_write_IV:o.getBytes(n.fixed_iv_length)}},a.createConnectionState=function(e){var t=e.entity===a.ConnectionEnd.client,n=function(){var e={sequenceNumber:[0,0],macKey:null,macLength:0,macFunction:null,cipherState:null,cipherFunction:function(e){return!0},compressionState:null,compressFunction:function(e){return!0},updateSequenceNumber:function(){e.sequenceNumber[1]===4294967295?(e.sequenceNumber[1]=0,++e.sequenceNumber[0]):++e.sequenceNumber[1]}};return e},r={read:n(),write:n()};r.read.update=function(e,t){return r.read.cipherFunction(t,r.read)?r.read.compressFunction(e,t,r.read)||e.error(e,{message:"Could not decompress record.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.decompression_failure}}):e.error(e,{message:"Could not decrypt record or bad MAC.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.bad_record_mac}}),!e.fail},r.write.update=function(e,t){return r.write.compressFunction(e,t,r.write)?r.write.cipherFunction(t,r.write)||e.error(e,{message:"Could not encrypt record.",send:!1,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.internal_error}}):e.error(e,{message:"Could not compress record.",send:!1,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.internal_error}}),!e.fail};if(e.session){var o=e.session.sp;e.session.cipherSuite.initSecurityParameters(o),o.keys=a.generateKeys(e,o),r.read.macKey=t?o.keys.server_write_MAC_key:o.keys.client_write_MAC_key,r.write.macKey=t?o.keys.client_write_MAC_key:o.keys.server_write_MAC_key,e.session.cipherSuite.initConnectionState(r,e,o);switch(o.compression_algorithm){case a.CompressionMethod.none:break;case a.CompressionMethod.deflate:r.read.compressFunction=s,r.write.compressFunction=i;break;default:throw{message:"Unsupported compression algorithm."}}}return r},a.createRandom=function(){var t=new Date,n=+t+t.getTimezoneOffset()*6e4,r=e.util.createBuffer();return r.putInt32(n),r.putBytes(e.random.getBytes(28)),r},a.createRecord=function(e){if(!e.data)return null;var t={type:e.type,version:{major:a.Version.major,minor:a.Version.minor},length:e.data.length(),fragment:e.data};return t},a.createAlert=function(t){var n=e.util.createBuffer();return n.putByte(t.level),n.putByte(t.description),a.createRecord({type:a.ContentType.alert,data:n})},a.createClientHello=function(t){var n=e.util.createBuffer();for(var r=0;r<t.cipherSuites.length;++r){var i=t.cipherSuites[r];n.putByte(i.id[0]),n.putByte(i.id[1])}var s=n.length(),o=e.util.createBuffer();o.putByte(a.CompressionMethod.none);var f=o.length(),l=e.util.createBuffer();if(t.virtualHost){var c=e.util.createBuffer();c.putByte(0),c.putByte(0);var h=e.util.createBuffer();h.putByte(0),u(h,2,e.util.createBuffer(t.virtualHost));var p=e.util.createBuffer();u(p,2,h),u(c,2,p),l.putBuffer(c)}var d=l.length();d>0&&(d+=2);var v=t.session.id,m=v.length+1+2+4+28+2+s+1+f+d,g=e.util.createBuffer();return g.putByte(a.HandshakeType.client_hello),g.putInt24(m),g.putByte(a.Version.major),g.putByte(a.Version.minor),g.putBytes(t.session.sp.client_random),u(g,1,e.util.createBuffer(v)),u(g,2,n),u(g,1,o),d>0&&u(g,2,l),g},a.createServerHello=function(t){var n=t.session.id,r=n.length+1+2+4+28+2+1,i=e.util.createBuffer();return i.putByte(a.HandshakeType.server_hello),i.putInt24(r),i.putByte(a.Version.major),i.putByte(a.Version.minor),i.putBytes(t.session.sp.server_random),u(i,1,e.util.createBuffer(n)),i.putByte(t.session.cipherSuite.id[0]),i.putByte(t.session.cipherSuite.id[1]),i.putByte(t.session.compressionMethod),i},a.createCertificate=function(t){var n=t.entity===a.ConnectionEnd.client,r=null;t.getCertificate&&(r=t.getCertificate(t,n?t.session.certificateRequest:t.session.serverNameList));var i=e.util.createBuffer();if(r!==null)try{e.util.isArray(r)||(r=[r]);var s=null;for(var o=0;o<r.length;++o){var f=e.pem.decode(r[o])[0];if(f.type!=="CERTIFICATE"&&f.type!=="X509 CERTIFICATE"&&f.type!=="TRUSTED CERTIFICATE")throw{message:'Could not convert certificate from PEM; PEM header type is not "CERTIFICATE", "X509 CERTIFICATE", or "TRUSTED CERTIFICATE".',headerType:f.type};if(f.procType&&f.procType.type==="ENCRYPTED")throw{message:"Could not convert certificate from PEM; PEM is encrypted."};var l=e.util.createBuffer(f.body);s===null&&(s=e.asn1.fromDer(l.bytes(),!1));var c=e.util.createBuffer();u(c,3,l),i.putBuffer(c)}r=e.pki.certificateFromAsn1(s),n?t.session.clientCertificate=r:t.session.serverCertificate=r}catch(h){return t.error(t,{message:"Could not send certificate list.",cause:h,send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.bad_certificate}})}var p=3+i.length(),d=e.util.createBuffer();return d.putByte(a.HandshakeType.certificate),d.putInt24(p),u(d,3,i),d},a.createClientKeyExchange=function(t){var n=e.util.createBuffer();n.putByte(a.Version.major),n.putByte(a.Version.minor),n.putBytes(e.random.getBytes(46));var r=t.session.sp;r.pre_master_secret=n.getBytes();var i=t.session.serverCertificate.publicKey;n=i.encrypt(r.pre_master_secret);var s=n.length+2,o=e.util.createBuffer();return o.putByte(a.HandshakeType.client_key_exchange),o.putInt24(s),o.putInt16(n.length),o.putBytes(n),o},a.createServerKeyExchange=function(t){var n=0,r=e.util.createBuffer();return n>0&&(r.putByte(a.HandshakeType.server_key_exchange),r.putInt24(n)),r},a.getClientSignature=function(t,n){var r=e.util.createBuffer();r.putBuffer(t.session.md5.digest()),r.putBuffer(t.session.sha1.digest()),r=r.getBytes(),t.getSignature=t.getSignature||function(t,n,r){var i=null;if(t.getPrivateKey)try{i=t.getPrivateKey(t,t.session.clientCertificate),i=e.pki.privateKeyFromPem(i)}catch(s){t.error(t,{message:"Could not get private key.",cause:s,send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.internal_error}})}i===null?t.error(t,{message:"No private key set.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.internal_error}}):n=i.sign(n,null),r(t,n)},t.getSignature(t,r,n)},a.createCertificateVerify=function(t,n){var r=n.length+2,i=e.util.createBuffer();return i.putByte(a.HandshakeType.certificate_verify),i.putInt24(r),i.putInt16(n.length),i.putBytes(n),i},a.createCertificateRequest=function(t){var n=e.util.createBuffer();n.putByte(1);var r=e.util.createBuffer();for(var i in t.caStore.certs){var s=t.caStore.certs[i],o=e.pki.distinguishedNameToAsn1(s.subject);r.putBuffer(e.asn1.toDer(o))}var f=1+n.length()+2+r.length(),l=e.util.createBuffer();return l.putByte(a.HandshakeType.certificate_request),l.putInt24(f),u(l,1,n),u(l,2,r),l},a.createServerHelloDone=function(t){var n=e.util.createBuffer();return n.putByte(a.HandshakeType.server_hello_done),n.putInt24(0),n},a.createChangeCipherSpec=function(){var t=e.util.createBuffer();return t.putByte(1),t},a.createFinished=function(n){var r=e.util.createBuffer();r.putBuffer(n.session.md5.digest()),r.putBuffer(n.session.sha1.digest());var i=n.entity===a.ConnectionEnd.client,s=n.session.sp,o=12,u=t,f=i?"client finished":"server finished";r=u(s.master_secret,f,r.getBytes(),o);var l=e.util.createBuffer();return l.putByte(a.HandshakeType.finished),l.putInt24(r.length()),l.putBuffer(r),l},a.queue=function(t,n){if(!n)return;if(n.type===a.ContentType.handshake){var r=n.fragment.bytes();t.session.md5.update(r),t.session.sha1.update(r),r=null}var i;if(n.fragment.length()<=a.MaxFragment)i=[n];else{i=[];var s=n.fragment.bytes();while(s.length>a.MaxFragment)i.push(a.createRecord({type:n.type,data:e.util.createBuffer(s.slice(0,a.MaxFragment))})),s=s.slice(a.MaxFragment);s.length>0&&i.push(a.createRecord({type:n.type,data:e.util.createBuffer(s)}))}for(var o=0;o<i.length&&!t.fail;++o){var u=i[o],f=t.state.current.write;f.update(t,u)&&t.records.push(u)}},a.flush=function(e){for(var t=0;t<e.records.length;++t){var n=e.records[t];e.tlsData.putByte(n.type),e.tlsData.putByte(n.version.major),e.tlsData.putByte(n.version.minor),e.tlsData.putInt16(n.fragment.length()),e.tlsData.putBuffer(e.records[t].fragment)}return e.records=[],e.tlsDataReady(e)};var z=function(t){switch(t){case!0:return!0;case e.pki.certificateError.bad_certificate:return a.Alert.Description.bad_certificate;case e.pki.certificateError.unsupported_certificate:return a.Alert.Description.unsupported_certificate;case e.pki.certificateError.certificate_revoked:return a.Alert.Description.certificate_revoked;case e.pki.certificateError.certificate_expired:return a.Alert.Description.certificate_expired;case e.pki.certificateError.certificate_unknown:return a.Alert.Description.certificate_unknown;case e.pki.certificateError.unknown_ca:return a.Alert.Description.unknown_ca;default:return a.Alert.Description.bad_certificate}},W=function(t){switch(t){case!0:return!0;case a.Alert.Description.bad_certificate:return e.pki.certificateError.bad_certificate;case a.Alert.Description.unsupported_certificate:return e.pki.certificateError.unsupported_certificate;case a.Alert.Description.certificate_revoked:return e.pki.certificateError.certificate_revoked;case a.Alert.Description.certificate_expired:return e.pki.certificateError.certificate_expired;case a.Alert.Description.certificate_unknown:return e.pki.certificateError.certificate_unknown;case a.Alert.Description.unknown_ca:return e.pki.certificateError.unknown_ca;default:return e.pki.certificateError.bad_certificate}};a.verifyCertificateChain=function(t,n){try{e.pki.verifyCertificateChain(t.caStore,n,function(r,i,s){var o=z(r),u=t.verify(t,r,i,s);if(u!==!0){if(typeof u=="object"&&!e.util.isArray(u)){var f={message:"The application rejected the certificate.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.bad_certificate}};throw u.message&&(f.message=u.message),u.alert&&(f.alert.description=u.alert),f}u!==r&&(u=W(u))}return u})}catch(r){if(typeof r!="object"||e.util.isArray(r))r={send:!0,alert:{level:a.Alert.Level.fatal,description:z(r)}};"send"in r||(r.send=!0),"alert"in r||(r.alert={level:a.Alert.Level.fatal,description:z(r.error)}),t.error(t,r)}return!t.fail},a.createSessionCache=function(t,n){var r=null;if(t&&t.getSession&&t.setSession&&t.order)r=t;else{r={},r.cache=t||{},r.capacity=Math.max(n||100,1),r.order=[];for(var i in t)r.order.length<=n?r.order.push(i):delete t[i];r.getSession=function(t){var n=null,i=null;t?i=e.util.bytesToHex(t):r.order.length>0&&(i=r.order[0]);if(i!==null&&i in r.cache){n=r.cache[i],delete r.cache[i];for(var s in r.order)if(r.order[s]===i){r.order.splice(s,1);break}}return n},r.setSession=function(t,n){if(r.order.length===r.capacity){var i=r.order.shift();delete r.cache[i]}var i=e.util.bytesToHex(t);r.order.push(i),r.cache[i]=n}}return r},a.createConnection=function(t){var n=null;t.caStore?e.util.isArray(t.caStore)?n=e.pki.createCaStore(t.caStore):n=t.caStore:n=e.pki.createCaStore();var r=t.cipherSuites||null;if(r===null){r=[];for(var i in a.CipherSuites)r.push(a.CipherSuites[i])}var s=t.server||!1?a.ConnectionEnd.server:a.ConnectionEnd.client,o=t.sessionCache?a.createSessionCache(t.sessionCache):null,u={entity:s,sessionId:t.sessionId,caStore:n,sessionCache:o,cipherSuites:r,connected:t.connected,virtualHost:t.virtualHost||null,verifyClient:t.verifyClient||!1,verify:t.verify||function(e,t,n,r){return t},getCertificate:t.getCertificate||null,getPrivateKey:t.getPrivateKey||null,getSignature:t.getSignature||null,input:e.util.createBuffer(),tlsData:e.util.createBuffer(),data:e.util.createBuffer(),tlsDataReady:t.tlsDataReady,dataReady:t.dataReady,closed:t.closed,error:function(e,n){n.origin=n.origin||(e.entity===a.ConnectionEnd.client?"client":"server"),n.send&&(a.queue(e,a.createAlert(n.alert)),a.flush(e));var r=n.fatal!==!1;r&&(e.fail=!0),t.error(e,n),r&&e.close(!1)},deflate:t.deflate||null,inflate:t.inflate||null};u.reset=function(e){u.record=null,u.session=null,u.peerCertificate=null,u.state={pending:null,current:null},u.expect=u.entity===a.ConnectionEnd.client?f:y,u.fragmented=null,u.records=[],u.open=!1,u.handshakes=0,u.handshaking=!1,u.isConnected=!1,u.fail=!e&&typeof e!="undefined",u.input.clear(),u.tlsData.clear(),u.data.clear(),u.state.current=a.createConnectionState(u)},u.reset();var l=function(e,t){var n=t.type-a.ContentType.change_cipher_spec,r=M[e.entity][e.expect];n in r?r[n](e,t):a.handleUnexpected(e,t)},c=function(t){var n=0,r=t.input,i=r.length();return i<5?n=5-i:(t.record={type:r.getByte(),version:{major:r.getByte(),minor:r.getByte()},length:r.getInt16(),fragment:e.util.createBuffer(),ready:!1},(t.record.version.major!==a.Version.major||t.record.version.minor!==a.Version.minor)&&t.error(t,{message:"Incompatible TLS version.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.protocol_version}})),n},h=function(e){var t=0,n=e.input,r=n.length();if(r<e.record.length)t=e.record.length-r;else{e.record.fragment.putBytes(n.getBytes(e.record.length)),n.compact();var i=e.state.current.read;i.update(e,e.record)&&(e.fragmented!==null&&(e.fragmented.type===e.record.type?(e.fragmented.fragment.putBuffer(e.record.fragment),e.record=e.fragmented):e.error(e,{message:"Invalid fragmented record.",send:!0,alert:{level:a.Alert.Level.fatal,description:a.Alert.Description.unexpected_message}})),e.record.ready=!0)}return t};return u.handshake=function(t){if(u.entity!==a.ConnectionEnd.client)u.error(u,{message:"Cannot initiate handshake as a server.",fatal:!1});else if(u.handshaking)u.error(u,{message:"Handshake already in progress.",fatal:!1});else{u.fail&&!u.open&&u.handshakes===0&&(u.fail=!1),u.handshaking=!0,t=t||"";var n=null;t.length>0&&(u.sessionCache&&(n=u.sessionCache.getSession(t)),n===null&&(t="")),t.length===0&&u.sessionCache&&(n=u.sessionCache.getSession(),n!==null&&(t=n.id)),u.session={id:t,cipherSuite:null,compressionMethod:null,serverCertificate:null,certificateRequest:null,clientCertificate:null,sp:n?n.sp:{},md5:e.md.md5.create(),sha1:e.md.sha1.create()},u.session.sp.client_random=a.createRandom().getBytes(),u.open=!0,a.queue(u,a.createRecord({type:a.ContentType.handshake,data:a.createClientHello(u)})),a.flush(u)}},u.process=function(e){var t=0;return e&&u.input.putBytes(e),u.fail||(u.record!==null&&u.record.ready&&u.record.fragment.isEmpty()&&(u.record=null),u.record===null&&(t=c(u)),!u.fail&&u.record!==null&&!u.record.ready&&(t=h(u)),!u.fail&&u.record!==null&&u.record.ready&&l(u,u.record)),t},u.prepare=function(t){return a.queue(u,a.createRecord({type:a.ContentType.application_data,data:e.util.createBuffer(t)})),a.flush(u)},u.close=function(e){!u.fail&&u.sessionCache&&u.session&&u.sessionCache.setSession(u.session.id,u.session);if(u.open){u.open=!1,u.input.clear();if(u.isConnected||u.handshaking)u.isConnected=u.handshaking=!1,a.queue(u,a.createAlert({level:a.Alert.Level.warning,description:a.Alert.Description.close_notify})),a.flush(u);u.closed(u)}u.reset(e)},u},e.tls=e.tls||{};for(var X in a)typeof a[X]!="function"&&(e.tls[X]=a[X]);e.tls.prf_tls1=t,e.tls.hmac_sha1=r,e.tls.createSessionCache=a.createSessionCache,e.tls.createConnection=a.createConnection}var r="tls";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/tls",["require","module","./asn1","./hmac","./md","./pem","./pki","./random","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){function n(n,i,s){var u=i.entity===e.tls.ConnectionEnd.client;n.read.cipherState={init:!1,cipher:e.aes.createDecryptionCipher(u?s.keys.server_write_key:s.keys.client_write_key),iv:u?s.keys.server_write_IV:s.keys.client_write_IV},n.write.cipherState={init:!1,cipher:e.aes.createEncryptionCipher(u?s.keys.client_write_key:s.keys.server_write_key),iv:u?s.keys.client_write_IV:s.keys.server_write_IV},n.read.cipherFunction=o,n.write.cipherFunction=r,n.read.macLength=n.write.macLength=s.mac_length,n.read.macFunction=n.write.macFunction=t.hmac_sha1}function r(t,n){var r=!1,s=n.macFunction(n.macKey,n.sequenceNumber,t);t.fragment.putBytes(s),n.updateSequenceNumber();var o;t.version.minor>1?o=e.random.getBytes(16):o=n.cipherState.init?null:n.cipherState.iv,n.cipherState.init=!0;var u=n.cipherState.cipher;return u.start(o),t.version.minor>1&&u.output.putBytes(o),u.update(t.fragment),u.finish(i)&&(t.fragment=u.output,t.length=t.fragment.length(),r=!0),r}function i(e,t,n){if(!n){var r=e-t.length()%e;t.fillWithByte(r-1,r)}return!0}function s(e,t,n){var r=!0;if(n){var i=t.length(),s=t.last();for(var o=i-1-s;o<i-1;++o)r=r&&t.at(o)==s;r&&t.truncate(s+1)}return r}function o(t,n){var r=!1,i=n.cipherState.init?null:n.cipherState.iv;n.cipherState.init=!0;var o=n.cipherState.cipher;o.start(i),o.update(t.fragment),r=o.finish(s);var u=n.macLength,a="";for(var f=0;f<u;++f)a+=String.fromCharCode(0);var l=o.output.length();l>=u?(t.fragment=o.output.getBytes(l-u),a=o.output.getBytes(u)):t.fragment=o.output.getBytes(),t.fragment=e.util.createBuffer(t.fragment),t.length=t.fragment.length();var c=n.macFunction(n.macKey,n.sequenceNumber,t);return n.updateSequenceNumber(),r=c===a&&r,r}var t=e.tls;t.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA={id:[0,47],name:"TLS_RSA_WITH_AES_128_CBC_SHA",initSecurityParameters:function(e){e.bulk_cipher_algorithm=t.BulkCipherAlgorithm.aes,e.cipher_type=t.CipherType.block,e.enc_key_length=16,e.block_length=16,e.fixed_iv_length=16,e.record_iv_length=16,e.mac_algorithm=t.MACAlgorithm.hmac_sha1,e.mac_length=20,e.mac_key_length=20},initConnectionState:n},t.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA={id:[0,53],name:"TLS_RSA_WITH_AES_256_CBC_SHA",initSecurityParameters:function(e){e.bulk_cipher_algorithm=t.BulkCipherAlgorithm.aes,e.cipher_type=t.CipherType.block,e.enc_key_length=32,e.block_length=16,e.fixed_iv_length=16,e.record_iv_length=16,e.mac_algorithm=t.MACAlgorithm.hmac_sha1,e.mac_length=20,e.mac_key_length=20},initConnectionState:n}}var r="aesCipherSuites";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/aesCipherSuites",["require","module","./aes","./tls"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){e.debug=e.debug||{},e.debug.storage={},e.debug.get=function(t,n){var r;return typeof t=="undefined"?r=e.debug.storage:t in e.debug.storage&&(typeof n=="undefined"?r=e.debug.storage[t]:r=e.debug.storage[t][n]),r},e.debug.set=function(t,n,r){t in e.debug.storage||(e.debug.storage[t]={}),e.debug.storage[t][n]=r},e.debug.clear=function(t,n){typeof t=="undefined"?e.debug.storage={}:t in e.debug.storage&&(typeof n=="undefined"?delete e.debug.storage[t]:delete e.debug.storage[t][n])}}var r="debug";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/debug",["require","module"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){e.log=e.log||{},e.log.levels=["none","error","warning","info","debug","verbose","max"];var t={},n=[],r=null;e.log.LEVEL_LOCKED=2,e.log.NO_LEVEL_CHECK=4,e.log.INTERPOLATE=8;for(var i=0;i<e.log.levels.length;++i){var s=e.log.levels[i];t[s]={index:i,name:s.toUpperCase()}}e.log.logMessage=function(r){var i=t[r.level].index;for(var s=0;s<n.length;++s){var o=n[s];if(o.flags&e.log.NO_LEVEL_CHECK)o.f(r);else{var u=t[o.level].index;i<=u&&o.f(o,r)}}},e.log.prepareStandard=function(e){"standard"in e||(e.standard=t[e.level].name+" ["+e.category+"] "+e.message)},e.log.prepareFull=function(t){if(!("full"in t)){var n=[t.message];n=n.concat([]||t.arguments),t.full=e.util.format.apply(this,n)}},e.log.prepareStandardFull=function(t){"standardFull"in t||(e.log.prepareStandard(t),t.standardFull=t.standard)};var o=["error","warning","info","debug","verbose"];for(var i=0;i<o.length;++i)(function(t){e.log[t]=function(n,r){var i=Array.prototype.slice.call(arguments).slice(2),s={timestamp:new Date,level:t,category:n,message:r,arguments:i};e.log.logMessage(s)}})(o[i]);e.log.makeLogger=function(t){var n={flags:0,f:t};return e.log.setLevel(n,"none"),n},e.log.setLevel=function(t,n){var r=!1;if(t&&!(t.flags&e.log.LEVEL_LOCKED))for(var i=0;i<e.log.levels.length;++i){var s=e.log.levels[i];if(n==s){t.level=n,r=!0;break}}return r},e.log.lock=function(t,n){typeof n=="undefined"||n?t.flags|=e.log.LEVEL_LOCKED:t.flags&=~e.log.LEVEL_LOCKED},e.log.addLogger=function(e){n.push(e)};if(typeof console!="undefined"&&"log"in console){var u;if(console.error&&console.warn&&console.info&&console.debug){var a={error:console.error,warning:console.warn,info:console.info,debug:console.debug,verbose:console.debug},f=function(t,n){e.log.prepareStandard(n);var r=a[n.level],i=[n.standard];i=i.concat(n.arguments.slice()),r.apply(console,i)};u=e.log.makeLogger(f)}else{var f=function(t,n){e.log.prepareStandardFull(n),console.log(n.standardFull)};u=e.log.makeLogger(f)}e.log.setLevel(u,"debug"),e.log.addLogger(u),r=u}else console={log:function(){}};if(r!==null){var l=e.util.getQueryVariables();"console.level"in l&&e.log.setLevel(r,l["console.level"].slice(-1)[0]);if("console.lock"in l){var c=l["console.lock"].slice(-1)[0];c=="true"&&e.log.lock(r)}}e.log.consoleLogger=r}var r="log";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/log",["require","module","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){var t=e.asn1,n=e.pkcs7=e.pkcs7||{};n.messageFromPem=function(r){var i=e.pem.decode(r)[0];if(i.type!=="PKCS7")throw{message:'Could not convert PKCS#7 message from PEM; PEM header type is not "PKCS#7".',headerType:i.type};if(i.procType&&i.procType.type==="ENCRYPTED")throw{message:"Could not convert PKCS#7 message from PEM; PEM is encrypted."};var s=t.fromDer(i.body);return n.messageFromAsn1(s)},n.messageToPem=function(n,r){var i={type:"PKCS7",body:t.toDer(n.toAsn1()).getBytes()};return e.pem.encode(i,{maxline:r})},n.messageFromAsn1=function(r){var i={},s=[];if(!t.validate(r,n.asn1.contentInfoValidator,i,s))throw{message:"Cannot read PKCS#7 message. ASN.1 object is not an PKCS#7 ContentInfo.",errors:s};var o=t.derToOid(i.contentType),u;switch(o){case e.pki.oids.envelopedData:u=n.createEnvelopedData();break;case e.pki.oids.encryptedData:u=n.createEncryptedData();break;case e.pki.oids.signedData:u=n.createSignedData();break;default:throw{message:"Cannot read PKCS#7 message. ContentType with OID "+o+" is not (yet) supported."}}return u.fromAsn1(i.content.value[0]),u};var r=function(r){var i={},s=[];if(!t.validate(r,n.asn1.recipientInfoValidator,i,s))throw{message:"Cannot read PKCS#7 message. ASN.1 object is not an PKCS#7 EnvelopedData.",errors:s};return{version:i.version.charCodeAt(0),issuer:e.pki.RDNAttributesAsArray(i.issuer),serialNumber:e.util.createBuffer(i.serial).toHex(),encryptedContent:{algorithm:t.derToOid(i.encAlgorithm),parameter:i.encParameter.value,content:i.encKey}}},i=function(n){return t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.INTEGER,!1,t.integerToDer(n.version).getBytes()),t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[e.pki.distinguishedNameToAsn1({attributes:n.issuer}),t.create(t.Class.UNIVERSAL,t.Type.INTEGER,!1,e.util.hexToBytes(n.serialNumber))]),t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(n.encryptedContent.algorithm).getBytes()),t.create(t.Class.UNIVERSAL,t.Type.NULL,!1,"")]),t.create(t.Class.UNIVERSAL,t.Type.OCTETSTRING,!1,n.encryptedContent.content)])},s=function(e){var t=[];for(var n=0;n<e.length;n++)t.push(r(e[n]));return t},o=function(e){var t=[];for(var n=0;n<e.length;n++)t.push(i(e[n]));return t},u=function(n){return[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(e.pki.oids.data).getBytes()),t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(n.algorithm).getBytes()),t.create(t.Class.UNIVERSAL,t.Type.OCTETSTRING,!1,n.parameter.getBytes())]),t.create(t.Class.CONTEXT_SPECIFIC,0,!0,[t.create(t.Class.UNIVERSAL,t.Type.OCTETSTRING,!1,n.content.getBytes())])]},a=function(n,r,i){var s={},o=[];if(!t.validate(r,i,s,o))throw{message:"Cannot read PKCS#7 message. ASN.1 object is not a supported PKCS#7 message.",errors:o};var u=t.derToOid(s.contentType);if(u!==e.pki.oids.data)throw{message:"Unsupported PKCS#7 message. Only wrapped ContentType Data supported."};if(s.encryptedContent){var a="";if(e.util.isArray(s.encryptedContent))for(var f=0;f<s.encryptedContent.length;++f){if(s.encryptedContent[f].type!==t.Type.OCTETSTRING)throw{message:"Malformed PKCS#7 message, expecting encrypted content constructed of only OCTET STRING objects."};a+=s.encryptedContent[f].value}else a=s.encryptedContent;n.encryptedContent={algorithm:t.derToOid(s.encAlgorithm),parameter:e.util.createBuffer(s.encParameter.value),content:e.util.createBuffer(a)}}if(s.content){var a="";if(e.util.isArray(s.content))for(var f=0;f<s.content.length;++f){if(s.content[f].type!==t.Type.OCTETSTRING)throw{message:"Malformed PKCS#7 message, expecting content constructed of only OCTET STRING objects."};a+=s.content[f].value}else a=s.content;n.content=e.util.createBuffer(a)}return n.version=s.version.charCodeAt(0),n.rawCapture=s,s},f=function(t){if(t.encryptedContent.key===undefined)throw{message:"Symmetric key not available."};if(t.content===undefined){var n;switch(t.encryptedContent.algorithm){case e.pki.oids["aes128-CBC"]:case e.pki.oids["aes192-CBC"]:case e.pki.oids["aes256-CBC"]:n=e.aes.createDecryptionCipher(t.encryptedContent.key);break;case e.pki.oids.desCBC:case e.pki.oids["des-EDE3-CBC"]:n=e.des.createDecryptionCipher(t.encryptedContent.key);break;default:throw{message:"Unsupported symmetric cipher, OID "+t.encryptedContent.algorithm}}n.start(t.encryptedContent.parameter),n.update(t.encryptedContent.content);if(!n.finish())throw{message:"Symmetric decryption failed."};t.content=n.output}};n.createSignedData=function(){var r=null;return r={type:e.pki.oids.signedData,version:1,certificates:[],crls:[],digestAlgorithmIdentifiers:[],contentInfo:null,signerInfos:[],fromAsn1:function(t){a(r,t,n.asn1.signedDataValidator),r.certificates=[],r.crls=[],r.digestAlgorithmIdentifiers=[],r.contentInfo=null,r.signerInfos=[];var i=r.rawCapture.certificates.value;for(var s=0;s<i.length;++s)r.certificates.push(e.pki.certificateFromAsn1(i[s]))},toAsn1:function(){if("content"in r)throw"Signing PKCS#7 content not yet implemented.";r.contentInfo||r.sign();var n=[];for(var i=0;i<r.certificates.length;++i)n.push(e.pki.certificateToAsn1(r.certificates[0]));var s=[];return t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(r.type).getBytes()),t.create(t.Class.CONTEXT_SPECIFIC,0,!0,[t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.INTEGER,!1,t.integerToDer(r.version).getBytes()),t.create(t.Class.UNIVERSAL,t.Type.SET,!0,r.digestAlgorithmIdentifiers),r.contentInfo,t.create(t.Class.CONTEXT_SPECIFIC,0,!0,n),t.create(t.Class.CONTEXT_SPECIFIC,1,!0,s),t.create(t.Class.UNIVERSAL,t.Type.SET,!0,r.signerInfos)])])])},sign:function(n){if("content"in r)throw"PKCS#7 signing not yet implemented.";typeof r.content!="object"&&(r.contentInfo=t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(e.pki.oids.data).getBytes())]),"content"in r&&r.contentInfo.value.push(t.create(t.Class.CONTEXT_SPECIFIC,0,!0,[t.create(t.Class.UNIVERSAL,t.Type.OCTETSTRING,!1,r.content)])))},verify:function(){throw"PKCS#7 signature verification not yet implemented."},addCertificate:function(t){typeof t=="string"&&(t=e.pki.certificateFromPem(t)),r.certificates.push(t)},addCertificateRevokationList:function(e){throw"PKCS#7 CRL support not yet implemented."}},r},n.createEncryptedData=function(){var t=null;return t={type:e.pki.oids.encryptedData,version:0,encryptedContent:{algorithm:e.pki.oids["aes256-CBC"]},fromAsn1:function(e){a(t,e,n.asn1.encryptedDataValidator)},decrypt:function(e){e!==undefined&&(t.encryptedContent.key=e),f(t)}},t},n.createEnvelopedData=function(){var r=null;return r={type:e.pki.oids.envelopedData,version:0,recipients:[],encryptedContent:{algorithm:e.pki.oids["aes256-CBC"]},fromAsn1:function(e){var t=a(r,e,n.asn1.envelopedDataValidator);r.recipients=s(t.recipientInfos.value)},toAsn1:function(){return t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.OID,!1,t.oidToDer(r.type).getBytes()),t.create(t.Class.CONTEXT_SPECIFIC,0,!0,[t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,[t.create(t.Class.UNIVERSAL,t.Type.INTEGER,!1,t.integerToDer(r.version).getBytes()),t.create(t.Class.UNIVERSAL,t.Type.SET,!0,o(r.recipients)),t.create(t.Class.UNIVERSAL,t.Type.SEQUENCE,!0,u(r.encryptedContent))])])])},findRecipient:function(e){var t=e.issuer.attributes;for(var n=0;n<r.recipients.length;++n){var i=r.recipients[n],s=i.issuer;if(i.serialNumber!==e.serialNumber)continue;if(s.length!==t.length)continue;var o=!0;for(var u=0;u<t.length;++u)if(s[u].type!==t[u].type||s[u].value!==t[u].value){o=!1;break}if(o)return i}return null},decrypt:function(t,n){if(r.encryptedContent.key===undefined&&t!==undefined&&n!==undefined)switch(t.encryptedContent.algorithm){case e.pki.oids.rsaEncryption:case e.pki.oids.desCBC:var i=n.decrypt(t.encryptedContent.content);r.encryptedContent.key=e.util.createBuffer(i);break;default:throw{message:"Unsupported asymmetric cipher, OID "+t.encryptedContent.algorithm}}f(r)},addRecipient:function(t){r.recipients.push({version:0,issuer:t.subject.attributes,serialNumber:t.serialNumber,encryptedContent:{algorithm:e.pki.oids.rsaEncryption,key:t.publicKey}})},encrypt:function(t,n){if(r.encryptedContent.content===undefined){n=n||r.encryptedContent.algorithm,t=t||r.encryptedContent.key;var i,s,o;switch(n){case e.pki.oids["aes128-CBC"]:i=16,s=16,o=e.aes.createEncryptionCipher;break;case e.pki.oids["aes192-CBC"]:i=24,s=16,o=e.aes.createEncryptionCipher;break;case e.pki.oids["aes256-CBC"]:i=32,s=16,o=e.aes.createEncryptionCipher;break;case e.pki.oids["des-EDE3-CBC"]:i=24,s=8,o=e.des.createEncryptionCipher;break;default:throw{message:"Unsupported symmetric cipher, OID "+n}}if(t===undefined)t=e.util.createBuffer(e.random.getBytes(i));else if(t.length()!=i)throw{message:"Symmetric key has wrong length, got "+t.length()+" bytes, expected "+i};r.encryptedContent.algorithm=n,r.encryptedContent.key=t,r.encryptedContent.parameter=e.util.createBuffer(e.random.getBytes(s));var u=o(t);u.start(r.encryptedContent.parameter.copy()),u.update(r.content);if(!u.finish())throw{message:"Symmetric encryption failed."};r.encryptedContent.content=u.output}for(var a=0;a<r.recipients.length;a++){var f=r.recipients[a];if(f.encryptedContent.content!==undefined)continue;switch(f.encryptedContent.algorithm){case e.pki.oids.rsaEncryption:f.encryptedContent.content=f.encryptedContent.key.encrypt(r.encryptedContent.key.data);break;default:throw{message:"Unsupported asymmetric cipher, OID "+f.encryptedContent.algorithm}}}}},r}}var r="pkcs7";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/pkcs7",["require","module","./aes","./asn1","./des","./oids","./pem","./pkcs7asn1","./random","./util","./x509"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){function e(e){var t="forge.task",n=0,r={},i=0;e.debug.set(t,"tasks",r);var s={};e.debug.set(t,"queues",s);var o="?",u=30,a=20,f="ready",l="running",c="blocked",h="sleeping",p="done",d="error",v="stop",m="start",g="block",y="unblock",b="sleep",w="wakeup",E="cancel",S="fail",x={};x[f]={},x[f][v]=f,x[f][m]=l,x[f][E]=p,x[f][S]=d,x[l]={},x[l][v]=f,x[l][m]=l,x[l][g]=c,x[l][y]=l,x[l][b]=h,x[l][w]=l,x[l][E]=p,x[l][S]=d,x[c]={},x[c][v]=c,x[c][m]=c,x[c][g]=c,x[c][y]=c,x[c][b]=c,x[c][w]=c,x[c][E]=p,x[c][S]=d,x[h]={},x[h][v]=h,x[h][m]=h,x[h][g]=h,x[h][y]=h,x[h][b]=h,x[h][w]=h,x[h][E]=p,x[h][S]=d,x[p]={},x[p][v]=p,x[p][m]=p,x[p][g]=p,x[p][y]=p,x[p][b]=p,x[p][w]=p,x[p][E]=p,x[p][S]=d,x[d]={},x[d][v]=d,x[d][m]=d,x[d][g]=d,x[d][y]=d,x[d][b]=d,x[d][w]=d,x[d][E]=d,x[d][S]=d;var T=function(s){this.id=-1,this.name=s.name||o,this.parent=s.parent||null,this.run=s.run,this.subtasks=[],this.error=!1,this.state=f,this.blocks=0,this.timeoutId=null,this.swapTime=null,this.userData=null,this.id=i++,r[this.id]=this,n>=1&&e.log.verbose(t,"[%s][%s] init",this.id,this.name,this)};T.prototype.debug=function(n){n=n||"",e.log.debug(t,n,"[%s][%s] task:",this.id,this.name,this,"subtasks:",this.subtasks.length,"queue:",s)},T.prototype.next=function(e,t){typeof e=="function"&&(t=e,e=this.name);var n=new T({run:t,name:e,parent:this});return n.state=l,n.type=this.type,n.successCallback=this.successCallback||null,n.failureCallback=this.failureCallback||null,this.subtasks.push(n),this},T.prototype.parallel=function(t,n){return e.util.isArray(t)&&(n=t,t=this.name),this.next(t,function(r){var i=r;i.block(n.length);var s=function(t,r){e.task.start({type:t,run:function(e){n[r](e)},success:function(e){i.unblock()},failure:function(e){i.unblock()}})};for(var o=0;o<n.length;o++){var u=t+"__parallel-"+r.id+"-"+o,a=o;s(u,a)}})},T.prototype.stop=function(){this.state=x[this.state][v]},T.prototype.start=function(){this.error=!1,this.state=x[this.state][m],this.state===l&&(this.start=new Date,this.run(this),C(this,0))},T.prototype.block=function(e){e=typeof e=="undefined"?1:e,this.blocks+=e,this.blocks>0&&(this.state=x[this.state][g])},T.prototype.unblock=function(e){return e=typeof e=="undefined"?1:e,this.blocks-=e,this.blocks===0&&this.state!==p&&(this.state=l,C(this,0)),this.blocks},T.prototype.sleep=function(e){e=typeof e=="undefined"?0:e,this.state=x[this.state][b];var t=this;this.timeoutId=setTimeout(function(){t.timeoutId=null,t.state=l,C(t,0)},e)},T.prototype.wait=function(e){e.wait(this)},T.prototype.wakeup=function(){this.state===h&&(cancelTimeout(this.timeoutId),this.timeoutId=null,this.state=l,C(this,0))},T.prototype.cancel=function(){this.state=x[this.state][E],this.permitsNeeded=0,this.timeoutId!==null&&(cancelTimeout(this.timeoutId),this.timeoutId=null),this.subtasks=[]},T.prototype.fail=function(e){this.error=!0,k(this,!0);if(e)e.error=this.error,e.swapTime=this.swapTime,e.userData=this.userData,C(e,0);else{if(this.parent!==null){var t=this.parent;while(t.parent!==null)t.error=this.error,t.swapTime=this.swapTime,t.userData=this.userData,t=t.parent;k(t,!0)}this.failureCallback&&this.failureCallback(this)}};var N=function(e){e.error=!1,e.state=x[e.state][m],setTimeout(function(){e.state===l&&(e.swapTime=+(new Date),e.run(e),C(e,0))},0)},C=function(e,t){var n=t>u||+(new Date)-e.swapTime>a,r=function(t){t++;if(e.state===l){n&&(e.swapTime=+(new Date));if(e.subtasks.length>0){var r=e.subtasks.shift();r.error=e.error,r.swapTime=e.swapTime,r.userData=e.userData,r.run(r),r.error||C(r,t)}else k(e),e.error||e.parent!==null&&(e.parent.error=e.error,e.parent.swapTime=e.swapTime,e.parent.userData=e.userData,C(e.parent,t))}};n?setTimeout(r,0):r(t)},k=function(i,o){i.state=p,delete r[i.id],n>=1&&e.log.verbose(t,"[%s][%s] finish",i.id,i.name,i),i.parent===null&&(i.type in s?s[i.type].length===0?e.log.error(t,"[%s][%s] task queue empty [%s]",i.id,i.name,i.type):s[i.type][0]!==i?e.log.error(t,"[%s][%s] task not first in queue [%s]",i.id,i.name,i.type):(s[i.type].shift(),s[i.type].length===0?(n>=1&&e.log.verbose(t,"[%s][%s] delete queue [%s]",i.id,i.name,i.type),delete s[i.type]):(n>=1&&e.log.verbose(t,"[%s][%s] queue start next [%s] remain:%s",i.id,i.name,i.type,s[i.type].length),s[i.type][0].start())):e.log.error(t,"[%s][%s] task queue missing [%s]",i.id,i.name,i.type),o||(i.error&&i.failureCallback?i.failureCallback(i):!i.error&&i.successCallback&&i.successCallback(i)))};e.task=e.task||{},e.task.start=function(r){var i=new T({run:r.run,name:r.name||o});i.type=r.type,i.successCallback=r.success||null,i.failureCallback=r.failure||null,i.type in s?s[r.type].push(i):(n>=1&&e.log.verbose(t,"[%s][%s] create queue [%s]",i.id,i.name,i.type),s[i.type]=[i],N(i))},e.task.cancel=function(e){e in s&&(s[e]=[s[e][0]])},e.task.createCondition=function(){var e={tasks:{}};return e.wait=function(t){t.id in e.tasks||(t.block(),e.tasks[t.id]=t)},e.notify=function(){var t=e.tasks;e.tasks={};for(var n in t)t[n].unblock()},e}}var r="task";if(typeof n!="function"){if(typeof module!="object"||!module.exports)return typeof forge=="undefined"&&(forge={}),e(forge);var i=!0;n=function(e,n){n(t,module)}}var s,o=function(t,n){n.exports=function(n){var i=s.map(function(e){return t(e)}).concat(e);n=n||{},n.defined=n.defined||{};if(n.defined[r])return n[r];n.defined[r]=!0;for(var o=0;o<i.length;++o)i[o](n);return n[r]}},u=n;n=function(e,t){return s=typeof e=="string"?t.slice(2):e.slice(2),i?(delete n,u.apply(null,Array.prototype.slice.call(arguments,0))):(n=u,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/task",["require","module","./debug","./log","./util"],function(){o.apply(null,Array.prototype.slice.call(arguments,0))})}(),function(){var e="forge";if(typeof n!="function"){if(typeof module!="object"||!module.exports){typeof forge=="undefined"&&(forge={disableNativeCode:!1});return}var r=!0;n=function(e,n){n(t,module)}}var i,s=function(t,n){n.exports=function(n){var r=i.map(function(e){return t(e)});n=n||{},n.defined=n.defined||{};if(n.defined[e])return n[e];n.defined[e]=!0;for(var s=0;s<r.length;++s)r[s](n);return n},n.exports.disableNativeCode=!1,n.exports(n.exports)},o=n;n=function(e,t){return i=typeof e=="string"?t.slice(2):e.slice(2),r?(delete n,o.apply(null,Array.prototype.slice.call(arguments,0))):(n=o,n.apply(null,Array.prototype.slice.call(arguments,0)))},n("js/forge",["require","module","./aes","./aesCipherSuites","./asn1","./debug","./des","./hmac","./log","./pbkdf2","./pem","./pkcs7","./pkcs1","./pkcs12","./pki","./prng","./pss","./random","./rc2","./task","./tls","./util","./md","./mgf1"],function(){s.apply(null,Array.prototype.slice.call(arguments,0))})}(),window.forge=t("js/forge")})();
}).call(this,require("/home/ryan/.local/lib/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"/home/ryan/.local/lib/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":10}],13:[function(require,module,exports){
var s =require('./forge.min.js');
var keygen = {};
var pki = forge.pki;
keygen.init = function(prefix, callback, password){
if (localStorage[prefix + '-certificate'] == undefined) {
var self = this;
console.log('generating keypair', forge)
pki.rsa.generateKeyPair({bits: 2048, workers: 2}, function(er, keys){
var cert = pki.createCertificate();
cert.publicKey = keys.publicKey;
cert.serialNumber = '01';
cert.validity.notBefore = new Date();
cert.validity.notAfter = new Date();
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1);
cert.sign(keys.privateKey);
var pem = pki.certificateToPem(cert);
var pubPem = pki.publicKeyToPem(keys.publicKey);
var priOpenPem = pki.privateKeyToPem(keys.privateKey);
localStorage[prefix + '-certificate'] = pem;
localStorage[prefix + '-publicKey'] = pubPem;
var priPem = pki.encryptRsaPrivateKey(keys.privateKey, password);
localStorage[prefix + '-privateKey'] = priPem;
callback(pem, priOpenPem, pubPem)
});
} else {
var EncryptedPriPem = localStorage[prefix + '-privateKey']
, priKey = pki.decryptRsaPrivateKey(EncryptedPriPem, password)
, priPem = pki.privateKeyToPem(priKey)
, cert = localStorage[prefix + '-certificate']
, pubPem = localStorage[prefix + '-publicKey']
callback(cert, priPem, pubPem)
}
}
module.exports = keygen.init;
},{"./forge.min.js":12}],14:[function(require,module,exports){
/*! asn1hex-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
//
// asn1hex.js - Hexadecimal represented ASN.1 string library
//
// version: 1.1 (09-May-2012)
//
// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)
//
// This software is licensed under the terms of the MIT License.
// http://kjur.github.com/jsrsasign/license/
//
// The above copyright and license notice shall be
// included in all copies or substantial portions of the Software.
//
// Depends on:
//
var BigInteger = require('jsbn')
function parseBigInt(str,r) {
return new BigInteger(str,r);
}
// MEMO:
// f('3082025b02...', 2) ... 82025b ... 3bytes
// f('020100', 2) ... 01 ... 1byte
// f('0203001...', 2) ... 03 ... 1byte
// f('02818003...', 2) ... 8180 ... 2bytes
// f('3080....0000', 2) ... 80 ... -1
//
// Requirements:
// - ASN.1 type octet length MUST be 1.
// (i.e. ASN.1 primitives like SET, SEQUENCE, INTEGER, OCTETSTRING ...)
// -
/**
* @fileOverview
* @name asn1hex-1.1.js
* @author Kenji Urushima kenji.urushima@gmail.com
* @version 1.1
* @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
*/
/**
* get byte length for ASN.1 L(length) bytes
* @name getByteLengthOfL_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return byte length for ASN.1 L(length) bytes
*/
function _asnhex_getByteLengthOfL_AtObj(s, pos) {
if (s.substring(pos + 2, pos + 3) != '8') return 1;
var i = parseInt(s.substring(pos + 3, pos + 4));
if (i == 0) return -1; // length octet '80' indefinite length
if (0 < i && i < 10) return i + 1; // including '8?' octet;
return -2; // malformed format
}
/**
* get hexadecimal string for ASN.1 L(length) bytes
* @name getHexOfL_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return {String} hexadecimal string for ASN.1 L(length) bytes
*/
function _asnhex_getHexOfL_AtObj(s, pos) {
var len = _asnhex_getByteLengthOfL_AtObj(s, pos);
if (len < 1) return '';
return s.substring(pos + 2, pos + 2 + len * 2);
}
//
// getting ASN.1 length value at the position 'idx' of
// hexa decimal string 's'.
//
// f('3082025b02...', 0) ... 82025b ... ???
// f('020100', 0) ... 01 ... 1
// f('0203001...', 0) ... 03 ... 3
// f('02818003...', 0) ... 8180 ... 128
/**
* get integer value of ASN.1 length for ASN.1 data
* @name getIntOfL_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return ASN.1 L(length) integer value
*/
function _asnhex_getIntOfL_AtObj(s, pos) {
var hLength = _asnhex_getHexOfL_AtObj(s, pos);
if (hLength == '') return -1;
var bi;
if (parseInt(hLength.substring(0, 1)) < 8) {
bi = parseBigInt(hLength, 16);
} else {
bi = parseBigInt(hLength.substring(2), 16);
}
return bi.intValue();
}
/**
* get ASN.1 value starting string position for ASN.1 object refered by index 'idx'.
* @name getStartPosOfV_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
*/
function _asnhex_getStartPosOfV_AtObj(s, pos) {
var l_len = _asnhex_getByteLengthOfL_AtObj(s, pos);
if (l_len < 0) return l_len;
return pos + (l_len + 1) * 2;
}
/**
* get hexadecimal string of ASN.1 V(value)
* @name getHexOfV_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return {String} hexadecimal string of ASN.1 value.
*/
function _asnhex_getHexOfV_AtObj(s, pos) {
var pos1 = _asnhex_getStartPosOfV_AtObj(s, pos);
var len = _asnhex_getIntOfL_AtObj(s, pos);
return s.substring(pos1, pos1 + len * 2);
}
/**
* get hexadecimal string of ASN.1 TLV at
* @name getHexOfTLV_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return {String} hexadecimal string of ASN.1 TLV.
* @since 1.1
*/
function _asnhex_getHexOfTLV_AtObj(s, pos) {
var hT = s.substr(pos, 2);
var hL = _asnhex_getHexOfL_AtObj(s, pos);
var hV = _asnhex_getHexOfV_AtObj(s, pos);
return hT + hL + hV;
}
/**
* get next sibling starting index for ASN.1 object string
* @name getPosOfNextSibling_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} pos string index
* @return next sibling starting index for ASN.1 object string
*/
function _asnhex_getPosOfNextSibling_AtObj(s, pos) {
var pos1 = _asnhex_getStartPosOfV_AtObj(s, pos);
var len = _asnhex_getIntOfL_AtObj(s, pos);
return pos1 + len * 2;
}
/**
* get array of indexes of child ASN.1 objects
* @name getPosArrayOfChildren_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} s hexadecimal string of ASN.1 DER encoded data
* @param {Number} start string index of ASN.1 object
* @return {Array of Number} array of indexes for childen of ASN.1 objects
*/
function _asnhex_getPosArrayOfChildren_AtObj(h, pos) {
var a = new Array();
var p0 = _asnhex_getStartPosOfV_AtObj(h, pos);
a.push(p0);
var len = _asnhex_getIntOfL_AtObj(h, pos);
var p = p0;
var k = 0;
while (1) {
var pNext = _asnhex_getPosOfNextSibling_AtObj(h, p);
if (pNext == null || (pNext - p0 >= (len * 2))) break;
if (k >= 200) break;
a.push(pNext);
p = pNext;
k++;
}
return a;
}
/**
* get string index of nth child object of ASN.1 object refered by h, idx
* @name getNthChildIndex_AtObj
* @memberOf ASN1HEX
* @function
* @param {String} h hexadecimal string of ASN.1 DER encoded data
* @param {Number} idx start string index of ASN.1 object
* @param {Number} nth for child
* @return {Number} string index of nth child.
* @since 1.1
*/
function _asnhex_getNthChildIndex_AtObj(h, idx, nth) {
var a = _asnhex_getPosArrayOfChildren_AtObj(h, idx);
return a[nth];
}
// ========== decendant methods ==============================
/**
* get string index of nth child object of ASN.1 object refered by h, idx
* @name getDecendantIndexByNthList
* @memberOf ASN1HEX
* @function
* @param {String} h hexadecimal string of ASN.1 DER encoded data
* @param {Number} currentIndex start string index of ASN.1 object
* @param {Array of Number} nthList array list of nth
* @return {Number} string index refered by nthList
* @since 1.1
*/
function _asnhex_getDecendantIndexByNthList(h, currentIndex, nthList) {
if (nthList.length == 0) {
return currentIndex;
}
var firstNth = nthList.shift();
var a = _asnhex_getPosArrayOfChildren_AtObj(h, currentIndex);
return _asnhex_getDecendantIndexByNthList(h, a[firstNth], nthList);
}
/**
* get hexadecimal string of ASN.1 TLV refered by current index and nth index list.
* @name getDecendantHexTLVByNthList
* @memberOf ASN1HEX
* @function
* @param {String} h hexadecimal string of ASN.1 DER encoded data
* @param {Number} currentIndex start string index of ASN.1 object
* @param {Array of Number} nthList array list of nth
* @return {Number} hexadecimal string of ASN.1 TLV refered by nthList
* @since 1.1
*/
function _asnhex_getDecendantHexTLVByNthList(h, currentIndex, nthList) {
var idx = _asnhex_getDecendantIndexByNthList(h, currentIndex, nthList);
return _asnhex_getHexOfTLV_AtObj(h, idx);
}
/**
* get hexadecimal string of ASN.1 V refered by current index and nth index list.
* @name getDecendantHexVByNthList
* @memberOf ASN1HEX
* @function
* @param {String} h hexadecimal string of ASN.1 DER encoded data
* @param {Number} currentIndex start string index of ASN.1 object
* @param {Array of Number} nthList array list of nth
* @return {Number} hexadecimal string of ASN.1 V refered by nthList
* @since 1.1
*/
function _asnhex_getDecendantHexVByNthList(h, currentIndex, nthList) {
var idx = _asnhex_getDecendantIndexByNthList(h, currentIndex, nthList);
return _asnhex_getHexOfV_AtObj(h, idx);
}
// ========== class definition ==============================
/**
* ASN.1 DER encoded hexadecimal string utility class
* @class ASN.1 DER encoded hexadecimal string utility class
* @author Kenji Urushima
* @version 1.1 (09 May 2012)
* @see <a href="http://kjur.github.com/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/</a>
* @since 1.1
*/
function ASN1HEX() {
return ASN1HEX;
}
ASN1HEX.getByteLengthOfL_AtObj = _asnhex_getByteLengthOfL_AtObj;
ASN1HEX.getHexOfL_AtObj = _asnhex_getHexOfL_AtObj;
ASN1HEX.getIntOfL_AtObj = _asnhex_getIntOfL_AtObj;
ASN1HEX.getStartPosOfV_AtObj = _asnhex_getStartPosOfV_AtObj;
ASN1HEX.getHexOfV_AtObj = _asnhex_getHexOfV_AtObj;
ASN1HEX.getHexOfTLV_AtObj = _asnhex_getHexOfTLV_AtObj;
ASN1HEX.getPosOfNextSibling_AtObj = _asnhex_getPosOfNextSibling_AtObj;
ASN1HEX.getPosArrayOfChildren_AtObj = _asnhex_getPosArrayOfChildren_AtObj;
ASN1HEX.getNthChildIndex_AtObj = _asnhex_getNthChildIndex_AtObj;
ASN1HEX.getDecendantIndexByNthList = _asnhex_getDecendantIndexByNthList;
ASN1HEX.getDecendantHexVByNthList = _asnhex_getDecendantHexVByNthList;
ASN1HEX.getDecendantHexTLVByNthList = _asnhex_getDecendantHexTLVByNthList;
module.exports = ASN1HEX;
},{"jsbn":65}],15:[function(require,module,exports){
var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var b64pad="=";
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz"
function int2char(n) { return BI_RM.charAt(n); }
function hex2b64(h) {
var i;
var c;
var ret = "";
for(i = 0; i+3 <= h.length; i+=3) {
c = parseInt(h.substring(i,i+3),16);
ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
}
if(i+1 == h.length) {
c = parseInt(h.substring(i,i+1),16);
ret += b64map.charAt(c << 2);
}
else if(i+2 == h.length) {
c = parseInt(h.substring(i,i+2),16);
ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
}
if (b64pad) while((ret.length & 3) > 0) ret += b64pad;
return ret;
}
// convert a base64 string to hex
function b64tohex(s) {
var ret = ""
var i;
var k = 0; // b64 state, 0-3
var slop;
for(i = 0; i < s.length; ++i) {
if(s.charAt(i) == b64pad) break;
v = b64map.indexOf(s.charAt(i));
if(v < 0) continue;
if(k == 0) {
ret += int2char(v >> 2);
slop = v & 3;
k = 1;
}
else if(k == 1) {
ret += int2char((slop << 2) | (v >> 4));
slop = v & 0xf;
k = 2;
}
else if(k == 2) {
ret += int2char(slop);
ret += int2char(v >> 2);
slop = v & 3;
k = 3;
}
else {
ret += int2char((slop << 2) | (v >> 4));
ret += int2char(v & 0xf);
k = 0;
}
}
if(k == 1)
ret += int2char(slop << 2);
return ret;
}
// convert a base64 string to a byte/number array
function b64toBA(s) {
//piggyback on b64tohex for now, optimize later
var h = b64tohex(s);
var i;
var a = new Array();
for(i = 0; 2*i < h.length; ++i) {
a[i] = parseInt(h.substring(2*i,2*i+2),16);
}
return a;
}
module.exports = {b64tohex: b64tohex, b64toBA: b64toBA, hex2b64: hex2b64};
},{}],16:[function(require,module,exports){
/*
CryptoJS v3.1.2
code.google.com/p/crypto-js
(c) 2009-2013 by Jeff Mott. All rights reserved.
code.google.com/p/crypto-js/wiki/License
*/
/**
* CryptoJS core components.
*/
var CryptoJS = CryptoJS || (function (Math, undefined) {
/**
* CryptoJS namespace.
*/
var C = {};
/**
* Library namespace.
*/
var C_lib = C.lib = {};
/**
* Base object for prototypal inheritance.
*/
var Base = C_lib.Base = (function () {
function F() {}
return {
/**
* Creates a new object that inherits from this object.
*
* @param {Object} overrides Properties to copy into the new object.
*
* @return {Object} The new object.
*
* @static
*
* @example
*
* var MyType = CryptoJS.lib.Base.extend({
* field: 'value',
*
* method: function () {
* }
* });
*/
extend: function (overrides) {
// Spawn
F.prototype = this;
var subtype = new F();
// Augment
if (overrides) {
subtype.mixIn(overrides);
}
// Create default initializer
if (!subtype.hasOwnProperty('init')) {
subtype.init = function () {
subtype.$super.init.apply(this, arguments);
};
}
// Initializer's prototype is the subtype object
subtype.init.prototype = subtype;
// Reference supertype
subtype.$super = this;
return subtype;
},
/**
* Extends this object and runs the init method.
* Arguments to create() will be passed to init().
*
* @return {Object} The new object.
*
* @static
*
* @example
*
* var instance = MyType.create();
*/
create: function () {
var instance = this.extend();
instance.init.apply(instance, arguments);
return instance;
},
/**
* Initializes a newly created object.
* Override this method to add some logic when your objects are created.
*
* @example
*
* var MyType = CryptoJS.lib.Base.extend({
* init: function () {
* // ...
* }
* });
*/
init: function () {
},
/**
* Copies properties into this object.
*
* @param {Object} properties The properties to mix in.
*
* @example
*
* MyType.mixIn({
* field: 'value'
* });
*/
mixIn: function (properties) {
for (var propertyName in properties) {
if (properties.hasOwnProperty(propertyName)) {
this[propertyName] = properties[propertyName];
}
}
// IE won't copy toString using the loop above
if (properties.hasOwnProperty('toString')) {
this.toString = properties.toString;
}
},
/**
* Creates a copy of this object.
*
* @return {Object} The clone.
*
* @example
*
* var clone = instance.clone();
*/
clone: function () {
return this.init.prototype.extend(this);
}
};
}());
/**
* An array of 32-bit words.
*
* @property {Array} words The array of 32-bit words.
* @property {number} sigBytes The number of significant bytes in this word array.
*/
var WordArray = C_lib.WordArray = Base.extend({
/**
* Initializes a newly created word array.
*
* @param {Array} words (Optional) An array of 32-bit words.
* @param {number} sigBytes (Optional) The number of significant bytes in the words.
*
* @example
*
* var wordArray = CryptoJS.lib.WordArray.create();
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
*/
init: function (words, sigBytes) {
words = this.words = words || [];
if (sigBytes != undefined) {
this.sigBytes = sigBytes;
} else {
this.sigBytes = words.length * 4;
}
},
/**
* Converts this word array to a string.
*
* @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
*
* @return {string} The stringified word array.
*
* @example
*
* var string = wordArray + '';
* var string = wordArray.toString();
* var string = wordArray.toString(CryptoJS.enc.Utf8);
*/
toString: function (encoder) {
return (encoder || Hex).stringify(this);
},
/**
* Concatenates a word array to this word array.
*
* @param {WordArray} wordArray The word array to append.
*
* @return {WordArray} This word array.
*
* @example
*
* wordArray1.concat(wordArray2);
*/
concat: function (wordArray) {
// Shortcuts
var thisWords = this.words;
var thatWords = wordArray.words;
var thisSigBytes = this.sigBytes;
var thatSigBytes = wordArray.sigBytes;
// Clamp excess bits
this.clamp();
// Concat
if (thisSigBytes % 4) {
// Copy one byte at a time
for (var i = 0; i < thatSigBytes; i++) {
var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
}
} else if (thatWords.length > 0xffff) {
// Copy one word at a time
for (var i = 0; i < thatSigBytes; i += 4) {
thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
}
} else {
// Copy all words at once
thisWords.push.apply(thisWords, thatWords);
}
this.sigBytes += thatSigBytes;
// Chainable
return this;
},
/**
* Removes insignificant bits.
*
* @example
*
* wordArray.clamp();
*/
clamp: function () {
// Shortcuts
var words = this.words;
var sigBytes = this.sigBytes;
// Clamp
words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
words.length = Math.ceil(sigBytes / 4);
},
/**
* Creates a copy of this word array.
*
* @return {WordArray} The clone.
*
* @example
*
* var clone = wordArray.clone();
*/
clone: function () {
var clone = Base.clone.call(this);
clone.words = this.words.slice(0);
return clone;
},
/**
* Creates a word array filled with random bytes.
*
* @param {number} nBytes The number of random bytes to generate.
*
* @return {WordArray} The random word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.lib.WordArray.random(16);
*/
random: function (nBytes) {
var words = [];
for (var i = 0; i < nBytes; i += 4) {
words.push((Math.random() * 0x100000000) | 0);
}
return new WordArray.init(words, nBytes);
}
});
/**
* Encoder namespace.
*/
var C_enc = C.enc = {};
/**
* Hex encoding strategy.
*/
var Hex = C_enc.Hex = {
/**
* Converts a word array to a hex string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The hex string.
*
* @static
*
* @example
*
* var hexString = CryptoJS.enc.Hex.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
// Convert
var hexChars = [];
for (var i = 0; i < sigBytes; i++) {
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
hexChars.push((bite >>> 4).toString(16));
hexChars.push((bite & 0x0f).toString(16));
}
return hexChars.join('');
},
/**
* Converts a hex string to a word array.
*
* @param {string} hexStr The hex string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Hex.parse(hexString);
*/
parse: function (hexStr) {
// Shortcut
var hexStrLength = hexStr.length;
// Convert
var words = [];
for (var i = 0; i < hexStrLength; i += 2) {
words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
}
return new WordArray.init(words, hexStrLength / 2);
}
};
/**
* Latin1 encoding strategy.
*/
var Latin1 = C_enc.Latin1 = {
/**
* Converts a word array to a Latin1 string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The Latin1 string.
*
* @static
*
* @example
*
* var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
// Convert
var latin1Chars = [];
for (var i = 0; i < sigBytes; i++) {
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
latin1Chars.push(String.fromCharCode(bite));
}
return latin1Chars.join('');
},
/**
* Converts a Latin1 string to a word array.
*
* @param {string} latin1Str The Latin1 string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
*/
parse: function (latin1Str) {
// Shortcut
var latin1StrLength = latin1Str.length;
// Convert
var words = [];
for (var i = 0; i < latin1StrLength; i++) {
words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
}
return new WordArray.init(words, latin1StrLength);
}
};
/**
* UTF-8 encoding strategy.
*/
var Utf8 = C_enc.Utf8 = {
/**
* Converts a word array to a UTF-8 string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The UTF-8 string.
*
* @static
*
* @example
*
* var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
*/
stringify: function (wordArray) {
try {
return decodeURIComponent(escape(Latin1.stringify(wordArray)));
} catch (e) {
throw new Error('Malformed UTF-8 data');
}
},
/**
* Converts a UTF-8 string to a word array.
*
* @param {string} utf8Str The UTF-8 string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
*/
parse: function (utf8Str) {
return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
}
};
/**
* Abstract buffered block algorithm template.
*
* The property blockSize must be implemented in a concrete subtype.
*
* @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
*/
var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
/**
* Resets this block algorithm's data buffer to its initial state.
*
* @example
*
* bufferedBlockAlgorithm.reset();
*/
reset: function () {
// Initial values
this._data = new WordArray.init();
this._nDataBytes = 0;
},
/**
* Adds new data to this block algorithm's buffer.
*
* @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
*
* @example
*
* bufferedBlockAlgorithm._append('data');
* bufferedBlockAlgorithm._append(wordArray);
*/
_append: function (data) {
// Convert string to WordArray, else assume WordArray already
if (typeof data == 'string') {
data = Utf8.parse(data);
}
// Append
this._data.concat(data);
this._nDataBytes += data.sigBytes;
},
/**
* Processes available data blocks.
*
* This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
*
* @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
*
* @return {WordArray} The processed data.
*
* @example
*
* var processedData = bufferedBlockAlgorithm._process();
* var processedData = bufferedBlockAlgorithm._process(!!'flush');
*/
_process: function (doFlush) {
// Shortcuts
var data = this._data;
var dataWords = data.words;
var dataSigBytes = data.sigBytes;
var blockSize = this.blockSize;
var blockSizeBytes = blockSize * 4;
// Count blocks ready
var nBlocksReady = dataSigBytes / blockSizeBytes;
if (doFlush) {
// Round up to include partial blocks
nBlocksReady = Math.ceil(nBlocksReady);
} else {
// Round down to include only full blocks,
// less the number of blocks that must remain in the buffer
nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
}
// Count words ready
var nWordsReady = nBlocksReady * blockSize;
// Count bytes ready
var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
// Process blocks
if (nWordsReady) {
for (var offset = 0; offset < nWordsReady; offset += blockSize) {
// Perform concrete-algorithm logic
this._doProcessBlock(dataWords, offset);
}
// Remove processed words
var processedWords = dataWords.splice(0, nWordsReady);
data.sigBytes -= nBytesReady;
}
// Return processed words
return new WordArray.init(processedWords, nBytesReady);
},
/**
* Creates a copy of this object.
*
* @return {Object} The clone.
*
* @example
*
* var clone = bufferedBlockAlgorithm.clone();
*/
clone: function () {
var clone = Base.clone.call(this);
clone._data = this._data.clone();
return clone;
},
_minBufferSize: 0
});
/**
* Abstract hasher template.
*
* @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
*/
var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
/**
* Configuration options.
*/
cfg: Base.extend(),
/**
* Initializes a newly created hasher.
*
* @param {Object} cfg (Optional) The configuration options to use for this hash computation.
*
* @example
*
* var hasher = CryptoJS.algo.SHA256.create();
*/
init: function (cfg) {
// Apply config defaults
this.cfg = this.cfg.extend(cfg);
// Set initial values
this.reset();
},
/**
* Resets this hasher to its initial state.
*
* @example
*
* hasher.reset();
*/
reset: function () {
// Reset data buffer
BufferedBlockAlgorithm.reset.call(this);
// Perform concrete-hasher logic
this._doReset();
},
/**
* Updates this hasher with a message.
*
* @param {WordArray|string} messageUpdate The message to append.
*
* @return {Hasher} This hasher.
*
* @example
*
* hasher.update('message');
* hasher.update(wordArray);
*/
update: function (messageUpdate) {
// Append
this._append(messageUpdate);
// Update the hash
this._process();
// Chainable
return this;
},
/**
* Finalizes the hash computation.
* Note that the finalize operation is effectively a destructive, read-once operation.
*
* @param {WordArray|string} messageUpdate (Optional) A final message update.
*
* @return {WordArray} The hash.
*
* @example
*
* var hash = hasher.finalize();
* var hash = hasher.finalize('message');
* var hash = hasher.finalize(wordArray);
*/
finalize: function (messageUpdate) {
// Final message update
if (messageUpdate) {
this._append(messageUpdate);
}
// Perform concrete-hasher logic
var hash = this._doFinalize();
return hash;
},
blockSize: 512/32,
/**
* Creates a shortcut function to a hasher's object interface.
*
* @param {Hasher} hasher The hasher to create a helper for.
*
* @return {Function} The shortcut function.
*
* @static
*
* @example
*
* var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
*/
_createHelper: function (hasher) {
return function (message, cfg) {
return new hasher.init(cfg).finalize(message);
};
},
/**
* Creates a shortcut function to the HMAC's object interface.
*
* @param {Hasher} hasher The hasher to use in this HMAC helper.
*
* @return {Function} The shortcut function.
*
* @static
*
* @example
*
* var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
*/
_createHmacHelper: function (hasher) {
return function (message, key) {
return new C_algo.HMAC.init(hasher, key).finalize(message);
};
}
});
/**
* Algorithm namespace.
*/
var C_algo = C.algo = {};
return C;
}(Math));
module.exports = CryptoJS
},{}],17:[function(require,module,exports){
/*! crypto-1.0.4.js (c) 2013 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
/*
* crypto.js - Cryptographic Algorithm Provider class
*
* Copyright (c) 2013 Kenji Urushima (kenji.urushima@gmail.com)
*
* This software is licensed under the terms of the MIT License.
* http://kjur.github.com/jsrsasign/license
*
* The above copyright and license notice shall be
* included in all copies or substantial portions of the Software.
*/
/**
* @fileOverview
* @name crypto-1.0.js
* @author Kenji Urushima kenji.urushima@gmail.com
* @version 1.0.4 (2013-Mar-28)
* @since 2.2
* @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
*/
var CryptoJS = require('./sha256.js')
var BigInteger = require('jsbn')
function parseBigInt(str,r) {
return new BigInteger(str,r);
}
/**
* kjur's class library name space
* @name KJUR
* @namespace kjur's class library name space
*/
if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
/**
* kjur's cryptographic algorithm provider library name space
* <p>
* This namespace privides following crytpgrahic classes.
* <ul>
* <li>{@link KJUR.crypto.MessageDigest} - Java JCE(cryptograhic extension) style MessageDigest class</li>
* <li>{@link KJUR.crypto.Signature} - Java JCE(cryptograhic extension) style Signature class</li>
* <li>{@link KJUR.crypto.Util} - cryptographic utility functions and properties</li>
* </ul>
* NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2.
* </p>
* @name KJUR.crypto
* @namespace
*/
if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) KJUR.crypto = {};
/**
* static object for cryptographic function utilities
* @name KJUR.crypto.Util
* @class static object for cryptographic function utilities
* @property {Array} DIGESTINFOHEAD PKCS#1 DigestInfo heading hexadecimal bytes for each hash algorithms
* @description
*/
KJUR.crypto.Util = new function() {
this.DIGESTINFOHEAD = {
'sha1': "3021300906052b0e03021a05000414",
'sha224': "302d300d06096086480165030402040500041c",
'sha256': "3031300d060960864801650304020105000420",
'sha384': "3041300d060960864801650304020205000430",
'sha512': "3051300d060960864801650304020305000440",
'md2': "3020300c06082a864886f70d020205000410",
'md5': "3020300c06082a864886f70d020505000410",
'ripemd160': "3021300906052b2403020105000414"
};
/**
* get hexadecimal DigestInfo
* @name getDigestInfoHex
* @memberOf KJUR.crypto.Util
* @function
* @param {String} hHash hexadecimal hash value
* @param {String} alg hash algorithm name (ex. 'sha1')
* @return {String} hexadecimal string DigestInfo ASN.1 structure
*/
this.getDigestInfoHex = function(hHash, alg) {
if (typeof this.DIGESTINFOHEAD[alg] == "undefined")
throw "alg not supported in Util.DIGESTINFOHEAD: " + alg;
return this.DIGESTINFOHEAD[alg] + hHash;
};
/**
* get PKCS#1 padded hexadecimal DigestInfo
* @name getPaddedDigestInfoHex
* @memberOf KJUR.crypto.Util
* @function
* @param {String} hHash hexadecimal hash value
* @param {String} alg hash algorithm name (ex. 'sha1')
* @param {Integer} keySize key bit length (ex. 1024)
* @return {String} hexadecimal string of PKCS#1 padded DigestInfo
*/
this.getPaddedDigestInfoHex = function(hHash, alg, keySize) {
var hDigestInfo = this.getDigestInfoHex(hHash, alg);
var pmStrLen = keySize / 4; // minimum PM length
if (hDigestInfo.length + 22 > pmStrLen) // len(0001+ff(*8)+00+hDigestInfo)=22
throw "key is too short for SigAlg: keylen=" + keySize + "," + alg;
var hHead = "0001";
var hTail = "00" + hDigestInfo;
var hMid = "";
var fLen = pmStrLen - hHead.length - hTail.length;
for (var i = 0; i < fLen; i += 2) {
hMid += "ff";
}
var hPaddedMessage = hHead + hMid + hTail;
return hPaddedMessage;
};
/**
* get hexadecimal SHA1 hash of string
* @name sha1
* @memberOf KJUR.crypto.Util
* @function
* @param {String} s input string to be hashed
* @return {String} hexadecimal string of hash value
* @since 1.0.3
*/
this.sha1 = function(s) {
var md = new KJUR.crypto.MessageDigest({'alg':'sha1', 'prov':'cryptojs'});
return md.digestString(s);
};
/**
* get hexadecimal SHA256 hash of string
* @name sha256
* @memberOf KJUR.crypto.Util
* @function
* @param {String} s input string to be hashed
* @return {String} hexadecimal string of hash value
* @since 1.0.3
*/
this.sha256 = function(s) {
var md = new KJUR.crypto.MessageDigest({'alg':'sha256', 'prov':'cryptojs'});
return md.digestString(s);
};
/**
* get hexadecimal SHA512 hash of string
* @name sha512
* @memberOf KJUR.crypto.Util
* @function
* @param {String} s input string to be hashed
* @return {String} hexadecimal string of hash value
* @since 1.0.3
*/
this.sha512 = function(s) {
var md = new KJUR.crypto.MessageDigest({'alg':'sha512', 'prov':'cryptojs'});
return md.digestString(s);
};
/**
* get hexadecimal MD5 hash of string
* @name md5
* @memberOf KJUR.crypto.Util
* @function
* @param {String} s input string to be hashed
* @return {String} hexadecimal string of hash value
* @since 1.0.3
*/
this.md5 = function(s) {
var md = new KJUR.crypto.MessageDigest({'alg':'md5', 'prov':'cryptojs'});
return md.digestString(s);
};
/**
* get hexadecimal RIPEMD160 hash of string
* @name ripemd160
* @memberOf KJUR.crypto.Util
* @function
* @param {String} s input string to be hashed
* @return {String} hexadecimal string of hash value
* @since 1.0.3
*/
this.ripemd160 = function(s) {
var md = new KJUR.crypto.MessageDigest({'alg':'ripemd160', 'prov':'cryptojs'});
return md.digestString(s);
};
};
/**
* MessageDigest class which is very similar to java.security.MessageDigest class
* @name KJUR.crypto.MessageDigest
* @class MessageDigest class which is very similar to java.security.MessageDigest class
* @param {Array} params parameters for constructor
* @description
* <br/>
* Currently this supports following algorithm and providers combination:
* <ul>
* <li>md5 - cryptojs</li>
* <li>sha1 - cryptojs</li>
* <li>sha224 - cryptojs</li>
* <li>sha256 - cryptojs</li>
* <li>sha384 - cryptojs</li>
* <li>sha512 - cryptojs</li>
* <li>ripemd160 - cryptojs</li>
* <li>sha256 - sjcl (NEW from crypto.js 1.0.4)</li>
* </ul>
* @example
* // CryptoJS provider sample
* <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/core.js"></script>
* <script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/sha1.js"></script>
* <script src="crypto-1.0.js"></script>
* var md = new KJUR.crypto.MessageDigest({alg: "sha1", prov: "cryptojs"});
* md.updateString('aaa')
* var mdHex = md.digest()
*
* // SJCL(Stanford JavaScript Crypto Library) provider sample
* <script src="http://bitwiseshiftleft.github.io/sjcl/sjcl.js"></script>
* <script src="crypto-1.0.js"></script>
* var md = new KJUR.crypto.MessageDigest({alg: "sha256", prov: "sjcl"}); // sjcl supports sha256 only
* md.updateString('aaa')
* var mdHex = md.digest()
*/
KJUR.crypto.MessageDigest = function(params) {
var md = null;
var algName = null;
var provName = null;
var _CryptoJSMdName = {
'md5': 'CryptoJS.algo.MD5',
'sha1': 'CryptoJS.algo.SHA1',
'sha224': 'CryptoJS.algo.SHA224',
'sha256': 'CryptoJS.algo.SHA256',
'sha384': 'CryptoJS.algo.SHA384',
'sha512': 'CryptoJS.algo.SHA512',
'ripemd160': 'CryptoJS.algo.RIPEMD160'
};
/**
* set hash algorithm and provider
* @name setAlgAndProvider
* @memberOf KJUR.crypto.MessageDigest
* @function
* @param {String} alg hash algorithm name
* @param {String} prov provider name
* @description
* @example
* // for SHA1
* md.setAlgAndProvider('sha1', 'cryptojs');
* // for RIPEMD160
* md.setAlgAndProvider('ripemd160', 'cryptojs');
*/
this.setAlgAndProvider = function(alg, prov) {
if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(alg) != -1 &&
prov == 'cryptojs') {
try {
this.md = eval(_CryptoJSMdName[alg]).create();
} catch (ex) {
throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex;
}
this.updateString = function(str) {
this.md.update(str);
};
this.updateHex = function(hex) {
var wHex = CryptoJS.enc.Hex.parse(hex);
this.md.update(wHex);
};
this.digest = function() {
var hash = this.md.finalize();
return hash.toString(CryptoJS.enc.Hex);
};
this.digestString = function(str) {
this.updateString(str);
return this.digest();
};
this.digestHex = function(hex) {
this.updateHex(hex);
return this.digest();
};
}
if (':sha256:'.indexOf(alg) != -1 &&
prov == 'sjcl') {
try {
this.md = new sjcl.hash.sha256();
} catch (ex) {
throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex;
}
this.updateString = function(str) {
this.md.update(str);
};
this.updateHex = function(hex) {
var baHex = sjcl.codec.hex.toBits(hex);
this.md.update(baHex);
};
this.digest = function() {
var hash = this.md.finalize();
return sjcl.codec.hex.fromBits(hash);
};
this.digestString = function(str) {
this.updateString(str);
return this.digest();
};
this.digestHex = function(hex) {
this.updateHex(hex);
return this.digest();
};
}
};
/**
* update digest by specified string
* @name updateString
* @memberOf KJUR.crypto.MessageDigest
* @function
* @param {String} str string to update
* @description
* @example
* md.updateString('New York');
*/
this.updateString = function(str) {
throw "updateString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName;
};
/**
* update digest by specified hexadecimal string
* @name updateHex
* @memberOf KJUR.crypto.MessageDigest
* @function
* @param {String} hex hexadecimal string to update
* @description
* @example
* md.updateHex('0afe36');
*/
this.updateHex = function(hex) {
throw "updateHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName;
};
/**
* completes hash calculation and returns hash result
* @name digest
* @memberOf KJUR.crypto.MessageDigest
* @function
* @description
* @example
* md.digest()
*/
this.digest = function() {
throw "digest() not supported for this alg/prov: " + this.algName + "/" + this.provName;
};
/**
* performs final update on the digest using string, then completes the digest computation
* @name digestString
* @memberOf KJUR.crypto.MessageDigest
* @function
* @param {String} str string to final update
* @description
* @example
* md.digestString('aaa')
*/
this.digestString = function(str) {
throw "digestString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName;
};
/**
* performs final update on the digest using hexadecimal string, then completes the digest computation
* @name digestHex
* @memberOf KJUR.crypto.MessageDigest
* @function
* @param {String} hex hexadecimal string to final update
* @description
* @example
* md.digestHex('0f2abd')
*/
this.digestHex = function(hex) {
throw "digestHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName;
};
if (typeof params != "undefined") {
if (typeof params['alg'] != "undefined") {
this.algName = params['alg'];
this.provName = params['prov'];
this.setAlgAndProvider(params['alg'], params['prov']);
}
}
};
/**
* Signature class which is very similar to java.security.Signature class
* @name KJUR.crypto.Signature
* @class Signature class which is very similar to java.security.Signature class
* @param {Array} params parameters for constructor
* @property {String} state Current state of this signature object whether 'SIGN', 'VERIFY' or null
* @description
* <br/>
* As for params of constructor's argument, it can be specify following attributes:
* <ul>
* <li>alg - signature algorithm name (ex. {MD5,SHA1,SHA224,SHA256,SHA384,SHA512,RIPEMD160}withRSA)</li>
* <li>provider - currently 'cryptojs/jsrsa' only</li>
* <li>prvkeypem - PEM string of signer's private key. If this specified, no need to call initSign(prvKey).</li>
* </ul>
* <h4>SUPPORTED ALGORITHMS AND PROVIDERS</h4>
* Signature class supports {MD5,SHA1,SHA224,SHA256,SHA384,SHA512,RIPEMD160}
* withRSA algorithm in 'cryptojs/jsrsa' provider.
* <h4>EXAMPLES</h4>
* @example
* // signature generation
* var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA", "prov": "cryptojs/jsrsa"});
* sig.initSign(prvKey);
* sig.updateString('aaa');
* var hSigVal = sig.sign();
*
* // signature validation
* var sig2 = new KJUR.crypto.Signature({"alg": "SHA1withRSA", "prov": "cryptojs/jsrsa"});
* sig2.initVerifyByCertificatePEM(cert)
* sig.updateString('aaa');
* var isValid = sig2.verify(hSigVal);
*/
KJUR.crypto.Signature = function(params) {
var prvKey = null; // RSAKey for signing
var pubKey = null; // RSAKey for verifying
var md = null; // KJUR.crypto.MessageDigest object
var sig = null;
var algName = null;
var provName = null;
var algProvName = null;
var mdAlgName = null;
var pubkeyAlgName = null;
var state = null;
var sHashHex = null; // hex hash value for hex
var hDigestInfo = null;
var hPaddedDigestInfo = null;
var hSign = null;
this._setAlgNames = function() {
if (this.algName.match(/^(.+)with(.+)$/)) {
this.mdAlgName = RegExp.$1.toLowerCase();
this.pubkeyAlgName = RegExp.$2.toLowerCase();
}
};
this._zeroPaddingOfSignature = function(hex, bitLength) {
var s = "";
var nZero = bitLength / 4 - hex.length;
for (var i = 0; i < nZero; i++) {
s = s + "0";
}
return s + hex;
};
/**
* set signature algorithm and provider
* @name setAlgAndProvider
* @memberOf KJUR.crypto.Signature
* @function
* @param {String} alg signature algorithm name
* @param {String} prov provider name
* @description
* @example
* md.setAlgAndProvider('SHA1withRSA', 'cryptojs/jsrsa');
*/
this.setAlgAndProvider = function(alg, prov) {
this._setAlgNames();
if (prov != 'cryptojs/jsrsa')
throw "provider not supported: " + prov;
if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(this.mdAlgName) != -1) {
try {
this.md = new KJUR.crypto.MessageDigest({'alg':this.mdAlgName,'prov':'cryptojs'});
} catch (ex) {
throw "setAlgAndProvider hash alg set fail alg=" + this.mdAlgName + "/" + ex;
}
this.initSign = function(prvKey) {
this.prvKey = prvKey;
this.state = "SIGN";
};
this.initVerifyByPublicKey = function(rsaPubKey) {
this.pubKey = rsaPubKey;
this.state = "VERIFY";
};
this.initVerifyByCertificatePEM = function(certPEM) {
var x509 = new X509();
x509.readCertPEM(certPEM);
this.pubKey = x509.subjectPublicKeyRSA;
this.state = "VERIFY";
};
this.updateString = function(str) {
this.md.updateString(str);
};
this.updateHex = function(hex) {
this.md.updateHex(hex);
};
this.sign = function() {
var util = KJUR.crypto.Util;
var keyLen = this.prvKey.n.bitLength();
this.sHashHex = this.md.digest();
this.hDigestInfo = util.getDigestInfoHex(this.sHashHex, this.mdAlgName);
this.hPaddedDigestInfo =
util.getPaddedDigestInfoHex(this.sHashHex, this.mdAlgName, keyLen);
var biPaddedDigestInfo = parseBigInt(this.hPaddedDigestInfo, 16);
this.hoge = biPaddedDigestInfo.toString(16);
var biSign = this.prvKey.doPrivate(biPaddedDigestInfo);
this.hSign = this._zeroPaddingOfSignature(biSign.toString(16), keyLen);
return this.hSign;
};
this.signString = function(str) {
this.updateString(str);
this.sign();
};
this.signHex = function(hex) {
this.updateHex(hex);
this.sign();
};
this.verify = function(hSigVal) {
var util = KJUR.crypto.Util;
var keyLen = this.pubKey.n.bitLength();
this.sHashHex = this.md.digest();
var biSigVal = parseBigInt(hSigVal, 16);
var biPaddedDigestInfo = this.pubKey.doPublic(biSigVal);
this.hPaddedDigestInfo = biPaddedDigestInfo.toString(16);
var s = this.hPaddedDigestInfo;
s = s.replace(/^1ff+00/, '');
var hDIHEAD = KJUR.crypto.Util.DIGESTINFOHEAD[this.mdAlgName];
if (s.indexOf(hDIHEAD) != 0) {
return false;
}
var hHashFromDI = s.substr(hDIHEAD.length);
//alert(hHashFromDI + "\n" + this.sHashHex);
return (hHashFromDI == this.sHashHex);
};
}
};
/**
* Initialize this object for verifying with a public key
* @name initVerifyByPublicKey
* @memberOf KJUR.crypto.Signature
* @function
* @param {RSAKey} rsaPubKey RSAKey object of public key
* @since 1.0.2
* @description
* @example
* sig.initVerifyByPublicKey(prvKey)
*/
this.initVerifyByPublicKey = function(rsaPubKey) {
throw "initVerifyByPublicKey(rsaPubKeyy) not supported for this alg:prov=" + this.algProvName;
};
/**
* Initialize this object for verifying with a certficate
* @name initVerifyByCertificatePEM
* @memberOf KJUR.crypto.Signature
* @function
* @param {String} certPEM PEM formatted string of certificate
* @since 1.0.2
* @description
* @example
* sig.initVerifyByCertificatePEM(certPEM)
*/
this.initVerifyByCertificatePEM = function(certPEM) {
throw "initVerifyByCertificatePEM(certPEM) not supported for this alg:prov=" + this.algProvName;
};
/**
* Initialize this object for signing
* @name initSign
* @memberOf KJUR.crypto.Signature
* @function
* @param {RSAKey} prvKey RSAKey object of private key
* @description
* @example
* sig.initSign(prvKey)
*/
this.initSign = function(prvKey) {
throw "initSign(prvKey) not supported for this alg:prov=" + this.algProvName;
};
/**
* Updates the data to be signed or verified by a string
* @name updateString
* @memberOf KJUR.crypto.Signature
* @function
* @param {String} str string to use for the update
* @description
* @example
* sig.updateString('aaa')
*/
this.updateString = function(str) {
throw "updateString(str) not supported for this alg:prov=" + this.algProvName;
};
/**
* Updates the data to be signed or verified by a hexadecimal string
* @name updateHex
* @memberOf KJUR.crypto.Signature
* @function
* @param {String} hex hexadecimal string to use for the update
* @description
* @example
* sig.updateHex('1f2f3f')
*/
this.updateHex = function(hex) {
throw "updateHex(hex) not supported for this alg:prov=" + this.algProvName;
};
/**
* Returns the signature bytes of all data updates as a hexadecimal string
* @name sign
* @memberOf KJUR.crypto.Signature
* @function
* @return the signature bytes as a hexadecimal string
* @description
* @example
* var hSigValue = sig.sign()
*/
this.sign = function() {
throw "sign() not supported for this alg:prov=" + this.algProvName;
};
/**
* performs final update on the sign using string, then returns the signature bytes of all data updates as a hexadecimal string
* @name signString
* @memberOf KJUR.crypto.Signature
* @function
* @param {String} str string to final update
* @return the signature bytes of a hexadecimal string
* @description
* @example
* var hSigValue = sig.signString('aaa')
*/
this.signString = function(str) {
throw "digestString(str) not supported for this alg:prov=" + this.algProvName;
};
/**
* performs final update on the sign using hexadecimal string, then returns the signature bytes of all data updates as a hexadecimal string
* @name signHex
* @memberOf KJUR.crypto.Signature
* @function
* @param {String} hex hexadecimal string to final update
* @return the signature bytes of a hexadecimal string
* @description
* @example
* var hSigValue = sig.signHex('1fdc33')
*/
this.signHex = function(hex) {
throw "digestHex(hex) not supported for this alg:prov=" + this.algProvName;
};
/**
* verifies the passed-in signature.
* @name verify
* @memberOf KJUR.crypto.Signature
* @function
* @param {String} str string to final update
* @return {Boolean} true if the signature was verified, otherwise false
* @description
* @example
* var isValid = sig.verify('1fbcefdca4823a7(snip)')
*/
this.verify = function(hSigVal) {
throw "verify(hSigVal) not supported for this alg:prov=" + this.algProvName;
};
if (typeof params != "undefined") {
if (typeof params['alg'] != "undefined") {
this.algName = params['alg'];
this.provName = params['prov'];
this.algProvName = params['alg'] + ":" + params['prov'];
this.setAlgAndProvider(params['alg'], params['prov']);
this._setAlgNames();
}
if (typeof params['prvkeypem'] != "undefined") {
if (typeof params['prvkeypas'] != "undefined") {
throw "both prvkeypem and prvkeypas parameters not supported";
} else {
try {
var prvKey = new RSAKey();
prvKey.readPrivateKeyFromPEMString(params['prvkeypem']);
this.initSign(prvKey);
} catch (ex) {
throw "fatal error to load pem private key: " + ex;
}
}
}
}
};
module.exports = KJUR
},{"./sha256.js":22,"jsbn":65}],18:[function(require,module,exports){
// Depends on jsbn.js and rng.js
var BigInteger = require('jsbn')
// Version 1.1: support utf-8 encoding in pkcs1pad2
// convert a (hex) string to a bignum object
function parseBigInt(str,r) {
return new BigInteger(str,r);
}
function linebrk(s,n) {
var ret = "";
var i = 0;
while(i + n < s.length) {
ret += s.substring(i,i+n) + "\n";
i += n;
}
return ret + s.substring(i,s.length);
}
function byte2Hex(b) {
if(b < 0x10)
return "0" + b.toString(16);
else
return b.toString(16);
}
// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
function pkcs1pad2(s,n) {
if(n < s.length + 11) { // TODO: fix for utf-8
alert("Message too long for RSA");
return null;
}
var ba = new Array();
var i = s.length - 1;
while(i >= 0 && n > 0) {
var c = s.charCodeAt(i--);
if(c < 128) { // encode using utf-8
ba[--n] = c;
}
else if((c > 127) && (c < 2048)) {
ba[--n] = (c & 63) | 128;
ba[--n] = (c >> 6) | 192;
}
else {
ba[--n] = (c & 63) | 128;
ba[--n] = ((c >> 6) & 63) | 128;
ba[--n] = (c >> 12) | 224;
}
}
ba[--n] = 0;
var rng = new SecureRandom();
var x = new Array();
while(n > 2) { // random non-zero pad
x[0] = 0;
while(x[0] == 0) rng.nextBytes(x);
ba[--n] = x[0];
}
ba[--n] = 2;
ba[--n] = 0;
return new BigInteger(ba);
}
// PKCS#1 (OAEP) mask generation function
function oaep_mgf1_arr(seed, len, hash)
{
var mask = '', i = 0;
while (mask.length < len)
{
mask += hash(String.fromCharCode.apply(String, seed.concat([
(i & 0xff000000) >> 24,
(i & 0x00ff0000) >> 16,
(i & 0x0000ff00) >> 8,
i & 0x000000ff])));
i += 1;
}
return mask;
}
var SHA1_SIZE = 20;
// PKCS#1 (OAEP) pad input string s to n bytes, and return a bigint
function oaep_pad(s, n, hash)
{
if (s.length + 2 * SHA1_SIZE + 2 > n)
{
throw "Message too long for RSA";
}
var PS = '', i;
for (i = 0; i < n - s.length - 2 * SHA1_SIZE - 2; i += 1)
{
PS += '\x00';
}
var DB = rstr_sha1('') + PS + '\x01' + s;
var seed = new Array(SHA1_SIZE);
new SecureRandom().nextBytes(seed);
var dbMask = oaep_mgf1_arr(seed, DB.length, hash || rstr_sha1);
var maskedDB = [];
for (i = 0; i < DB.length; i += 1)
{
maskedDB[i] = DB.charCodeAt(i) ^ dbMask.charCodeAt(i);
}
var seedMask = oaep_mgf1_arr(maskedDB, seed.length, rstr_sha1);
var maskedSeed = [0];
for (i = 0; i < seed.length; i += 1)
{
maskedSeed[i + 1] = seed[i] ^ seedMask.charCodeAt(i);
}
return new BigInteger(maskedSeed.concat(maskedDB));
}
// "empty" RSA key constructor
function RSAKey() {
this.n = null;
this.e = 0;
this.d = null;
this.p = null;
this.q = null;
this.dmp1 = null;
this.dmq1 = null;
this.coeff = null;
}
// Set the public key fields N and e from hex strings
function RSASetPublic(N,E) {
if (typeof N !== "string")
{
this.n = N;
this.e = E;
}
else if(N != null && E != null && N.length > 0 && E.length > 0) {
this.n = parseBigInt(N,16);
this.e = parseInt(E,16);
}
else
alert("Invalid RSA public key");
}
// Perform raw public operation on "x": return x^e (mod n)
function RSADoPublic(x) {
return x.modPowInt(this.e, this.n);
}
// Return the PKCS#1 RSA encryption of "text" as an even-length hex string
function RSAEncrypt(text) {
var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
if(m == null) return null;
var c = this.doPublic(m);
if(c == null) return null;
var h = c.toString(16);
if((h.length & 1) == 0) return h; else return "0" + h;
}
// Return the PKCS#1 OAEP RSA encryption of "text" as an even-length hex string
function RSAEncryptOAEP(text, hash) {
var m = oaep_pad(text, (this.n.bitLength()+7)>>3, hash);
if(m == null) return null;
var c = this.doPublic(m);
if(c == null) return null;
var h = c.toString(16);
if((h.length & 1) == 0) return h; else return "0" + h;
}
// Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
//function RSAEncryptB64(text) {
// var h = this.encrypt(text);
// if(h) return hex2b64(h); else return null;
//}
// protected
RSAKey.prototype.doPublic = RSADoPublic;
// public
RSAKey.prototype.setPublic = RSASetPublic;
RSAKey.prototype.encrypt = RSAEncrypt;
RSAKey.prototype.encryptOAEP = RSAEncryptOAEP;
module.exports = RSAKey
//RSAKey.prototype.encrypt_b64 = RSAEncryptB64;
},{"jsbn":65}],19:[function(require,module,exports){
// Depends on rsa.js and jsbn2.js
var BigInteger = require('jsbn')
var RSAKey = require('./rsa.js')
// Version 1.1: support utf-8 decoding in pkcs1unpad2
function parseBigInt(str,r) {
return new BigInteger(str,r);
}
// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
function pkcs1unpad2(d,n) {
var b = d.toByteArray();
var i = 0;
while(i < b.length && b[i] == 0) ++i;
if(b.length-i != n-1 || b[i] != 2)
return null;
++i;
while(b[i] != 0)
if(++i >= b.length) return null;
var ret = "";
while(++i < b.length) {
var c = b[i] & 255;
if(c < 128) { // utf-8 decode
ret += String.fromCharCode(c);
}
else if((c > 191) && (c < 224)) {
ret += String.fromCharCode(((c & 31) << 6) | (b[i+1] & 63));
++i;
}
else {
ret += String.fromCharCode(((c & 15) << 12) | ((b[i+1] & 63) << 6) | (b[i+2] & 63));
i += 2;
}
}
return ret;
}
// PKCS#1 (OAEP) mask generation function
function oaep_mgf1_str(seed, len, hash)
{
var mask = '', i = 0;
while (mask.length < len)
{
mask += hash(seed + String.fromCharCode.apply(String, [
(i & 0xff000000) >> 24,
(i & 0x00ff0000) >> 16,
(i & 0x0000ff00) >> 8,
i & 0x000000ff]));
i += 1;
}
return mask;
}
var SHA1_SIZE = 20;
// Undo PKCS#1 (OAEP) padding and, if valid, return the plaintext
function oaep_unpad(d, n, hash)
{
d = d.toByteArray();
var i;
for (i = 0; i < d.length; i += 1)
{
d[i] &= 0xff;
}
while (d.length < n)
{
d.unshift(0);
}
d = String.fromCharCode.apply(String, d);
if (d.length < 2 * SHA1_SIZE + 2)
{
throw "Cipher too short";
}
var maskedSeed = d.substr(1, SHA1_SIZE)
var maskedDB = d.substr(SHA1_SIZE + 1);
var seedMask = oaep_mgf1_str(maskedDB, SHA1_SIZE, hash || rstr_sha1);
var seed = [], i;
for (i = 0; i < maskedSeed.length; i += 1)
{
seed[i] = maskedSeed.charCodeAt(i) ^ seedMask.charCodeAt(i);
}
var dbMask = oaep_mgf1_str(String.fromCharCode.apply(String, seed),
d.length - SHA1_SIZE, rstr_sha1);
var DB = [];
for (i = 0; i < maskedDB.length; i += 1)
{
DB[i] = maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i);
}
DB = String.fromCharCode.apply(String, DB);
if (DB.substr(0, SHA1_SIZE) !== rstr_sha1(''))
{
throw "Hash mismatch";
}
DB = DB.substr(SHA1_SIZE);
var first_one = DB.indexOf('\x01');
var last_zero = (first_one != -1) ? DB.substr(0, first_one).lastIndexOf('\x00') : -1;
if (last_zero + 1 != first_one)
{
throw "Malformed data";
}
return DB.substr(first_one + 1);
}
// Set the private key fields N, e, and d from hex strings
function RSASetPrivate(N,E,D) {
if (typeof N !== "string")
{
this.n = N;
this.e = E;
this.d = D;
}
else if(N != null && E != null && N.length > 0 && E.length > 0) {
this.n = parseBigInt(N,16);
this.e = parseInt(E,16);
this.d = parseBigInt(D,16);
}
else
alert("Invalid RSA private key");
}
// Set the private key fields N, e, d and CRT params from hex strings
function RSASetPrivateEx(N,E,D,P,Q,DP,DQ,C) {
//alert("RSASetPrivateEx called");
if (N == null) throw "RSASetPrivateEx N == null";
if (E == null) throw "RSASetPrivateEx E == null";
if (N.length == 0) throw "RSASetPrivateEx N.length == 0";
if (E.length == 0) throw "RSASetPrivateEx E.length == 0";
if (N != null && E != null && N.length > 0 && E.length > 0) {
this.n = parseBigInt(N,16);
this.e = parseInt(E,16);
this.d = parseBigInt(D,16);
this.p = parseBigInt(P,16);
this.q = parseBigInt(Q,16);
this.dmp1 = parseBigInt(DP,16);
this.dmq1 = parseBigInt(DQ,16);
this.coeff = parseBigInt(C,16);
} else {
alert("Invalid RSA private key in RSASetPrivateEx");
}
}
// Generate a new random private key B bits long, using public expt E
function RSAGenerate(B,E) {
var rng = new SecureRandom();
var qs = B>>1;
this.e = parseInt(E,16);
var ee = new BigInteger(E,16);
for(;;) {
for(;;) {
this.p = new BigInteger(B-qs,1,rng);
if(this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) break;
}
for(;;) {
this.q = new BigInteger(qs,1,rng);
if(this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) break;
}
if(this.p.compareTo(this.q) <= 0) {
var t = this.p;
this.p = this.q;
this.q = t;
}
var p1 = this.p.subtract(BigInteger.ONE); // p1 = p - 1
var q1 = this.q.subtract(BigInteger.ONE); // q1 = q - 1
var phi = p1.multiply(q1);
if(phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
this.n = this.p.multiply(this.q); // this.n = p * q
this.d = ee.modInverse(phi); // this.d =
this.dmp1 = this.d.mod(p1); // this.dmp1 = d mod (p - 1)
this.dmq1 = this.d.mod(q1); // this.dmq1 = d mod (q - 1)
this.coeff = this.q.modInverse(this.p); // this.coeff = (q ^ -1) mod p
break;
}
}
}
// Perform raw private operation on "x": return x^d (mod n)
function RSADoPrivate(x) {
if(this.p == null || this.q == null)
return x.modPow(this.d, this.n);
// TODO: re-calculate any missing CRT params
var xp = x.mod(this.p).modPow(this.dmp1, this.p); // xp=cp?
var xq = x.mod(this.q).modPow(this.dmq1, this.q); // xq=cq?
while(xp.compareTo(xq) < 0)
xp = xp.add(this.p);
// NOTE:
// xp.subtract(xq) => cp -cq
// xp.subtract(xq).multiply(this.coeff).mod(this.p) => (cp - cq) * u mod p = h
// xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq) => cq + (h * q) = M
return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq);
}
// Return the PKCS#1 RSA decryption of "ctext".
// "ctext" is an even-length hex string and the output is a plain string.
function RSADecrypt(ctext) {
var c = parseBigInt(ctext, 16);
var m = this.doPrivate(c);
if(m == null) return null;
return pkcs1unpad2(m, (this.n.bitLength()+7)>>3);
}
// Return the PKCS#1 OAEP RSA decryption of "ctext".
// "ctext" is an even-length hex string and the output is a plain string.
function RSADecryptOAEP(ctext, hash) {
var c = parseBigInt(ctext, 16);
var m = this.doPrivate(c);
if(m == null) return null;
return oaep_unpad(m, (this.n.bitLength()+7)>>3, hash);
}
// Return the PKCS#1 RSA decryption of "ctext".
// "ctext" is a Base64-encoded string and the output is a plain string.
//function RSAB64Decrypt(ctext) {
// var h = b64tohex(ctext);
// if(h) return this.decrypt(h); else return null;
//}
// protected
RSAKey.prototype.doPrivate = RSADoPrivate;
// public
RSAKey.prototype.setPrivate = RSASetPrivate;
RSAKey.prototype.setPrivateEx = RSASetPrivateEx;
RSAKey.prototype.generate = RSAGenerate;
RSAKey.prototype.decrypt = RSADecrypt;
RSAKey.prototype.decryptOAEP = RSADecryptOAEP;
//RSAKey.prototype.b64_decrypt = RSAB64Decrypt;
module.exports = RSAKey
},{"./rsa.js":18,"jsbn":65}],20:[function(require,module,exports){
/*! rsapem-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
//
// rsa-pem.js - adding function for reading/writing PKCS#1 PEM private key
// to RSAKey class.
//
// version: 1.1.1 (2013-Apr-12)
//
// Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
//
// This software is licensed under the terms of the MIT License.
// http://kjur.github.com/jsrsasign/license/
//
// The above copyright and license notice shall be
// included in all copies or substantial portions of the Software.
//
//
// Depends on:
//
//
//
// _RSApem_pemToBase64(sPEM)
//
// removing PEM header, PEM footer and space characters including
// new lines from PEM formatted RSA private key string.
//
var ASN1HEX = require('./asn1hex-1.1.js')
var b64tohex = require('./base64.js').b64tohex
var RSAKey = require('./rsa2.js')
/**
* @fileOverview
* @name rsapem-1.1.js
* @author Kenji Urushima kenji.urushima@gmail.com
* @version 1.1
* @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
*/
function _rsapem_pemToBase64(sPEMPrivateKey) {
var s = sPEMPrivateKey;
s = s.replace("-----BEGIN RSA PRIVATE KEY-----", "");
s = s.replace("-----END RSA PRIVATE KEY-----", "");
s = s.replace(/[ \n]+/g, "");
return s;
}
function _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey) {
var a = new Array();
var v1 = ASN1HEX.getStartPosOfV_AtObj(hPrivateKey, 0);
var n1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, v1);
var e1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, n1);
var d1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, e1);
var p1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, d1);
var q1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, p1);
var dp1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, q1);
var dq1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, dp1);
var co1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, dq1);
a.push(v1, n1, e1, d1, p1, q1, dp1, dq1, co1);
return a;
}
function _rsapem_getHexValueArrayOfChildrenFromHex(hPrivateKey) {
var posArray = _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey);
var v = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[0]);
var n = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[1]);
var e = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[2]);
var d = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[3]);
var p = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[4]);
var q = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[5]);
var dp = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[6]);
var dq = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[7]);
var co = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[8]);
var a = new Array();
a.push(v, n, e, d, p, q, dp, dq, co);
return a;
}
/**
* read RSA private key from a ASN.1 hexadecimal string
* @name readPrivateKeyFromASN1HexString
* @memberOf RSAKey#
* @function
* @param {String} keyHex ASN.1 hexadecimal string of PKCS#1 private key.
* @since 1.1.1
*/
function _rsapem_readPrivateKeyFromASN1HexString(keyHex) {
var a = _rsapem_getHexValueArrayOfChildrenFromHex(keyHex);
this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
}
/**
* read PKCS#1 private key from a string
* @name readPrivateKeyFromPEMString
* @memberOf RSAKey#
* @function
* @param {String} keyPEM string of PKCS#1 private key.
*/
function _rsapem_readPrivateKeyFromPEMString(keyPEM) {
var keyB64 = _rsapem_pemToBase64(keyPEM);
var keyHex = b64tohex(keyB64) // depends base64.js
var a = _rsapem_getHexValueArrayOfChildrenFromHex(keyHex);
this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
}
RSAKey.prototype.readPrivateKeyFromPEMString = _rsapem_readPrivateKeyFromPEMString;
RSAKey.prototype.readPrivateKeyFromASN1HexString = _rsapem_readPrivateKeyFromASN1HexString;
module.exports = RSAKey
},{"./asn1hex-1.1.js":14,"./base64.js":15,"./rsa2.js":19}],21:[function(require,module,exports){
/*! rsasign-1.2.2.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
*/
//
// rsa-sign.js - adding signing functions to RSAKey class.
//
//
// version: 1.2.2 (13 May 2013)
//
// Copyright (c) 2010-2013 Kenji Urushima (kenji.urushima@gmail.com)
//
// This software is licensed under the terms of the MIT License.
// http://kjur.github.com/jsrsasign/license/
//
// The above copyright and license notice shall be
// included in all copies or substantial portions of the Software.
//
// Depends on:
// function sha1.hex(s) of sha1.js
// jsbn.js
// jsbn2.js
// rsa.js
// rsa2.js
//
var BigInteger = require('jsbn')
var RSAKey= require('./rsapem-1.1.js')
function parseBigInt(str,r) {
return new BigInteger(str,r);
}
// keysize / pmstrlen
// 512 / 128
// 1024 / 256
// 2048 / 512
// 4096 / 1024
/**
* @fileOverview
* @name rsasign-1.2.js
* @author Kenji Urushima kenji.urushima@gmail.com
* @version 1.2.2
* @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
*/
/**
* @property {Dictionary} _RSASIGN_DIHEAD
* @description Array of head part of hexadecimal DigestInfo value for hash algorithms.
* You can add any DigestInfo hash algorith for signing.
* See PKCS#1 v2.1 spec (p38).
*/
var _RSASIGN_DIHEAD = [];
_RSASIGN_DIHEAD['sha1'] = "3021300906052b0e03021a05000414";
_RSASIGN_DIHEAD['sha256'] = "3031300d060960864801650304020105000420";
_RSASIGN_DIHEAD['sha384'] = "3041300d060960864801650304020205000430";
_RSASIGN_DIHEAD['sha512'] = "3051300d060960864801650304020305000440";
_RSASIGN_DIHEAD['md2'] = "3020300c06082a864886f70d020205000410";
_RSASIGN_DIHEAD['md5'] = "3020300c06082a864886f70d020505000410";
_RSASIGN_DIHEAD['ripemd160'] = "3021300906052b2403020105000414";
/**
* @property {Dictionary} _RSASIGN_HASHHEXFUNC
* @description Array of functions which calculate hash and returns it as hexadecimal.
* You can add any hash algorithm implementations.
*/
var _RSASIGN_HASHHEXFUNC = [];
_RSASIGN_HASHHEXFUNC['sha1'] = function(s){return KJUR.crypto.Util.sha1(s);};
_RSASIGN_HASHHEXFUNC['sha256'] = function(s){return KJUR.crypto.Util.sha256(s);}
_RSASIGN_HASHHEXFUNC['sha512'] = function(s){return KJUR.crypto.Util.sha512(s);}
_RSASIGN_HASHHEXFUNC['md5'] = function(s){return KJUR.crypto.Util.md5(s);};
_RSASIGN_HASHHEXFUNC['ripemd160'] = function(s){return KJUR.crypto.Util.ripemd160(s);};
//_RSASIGN_HASHHEXFUNC['sha1'] = function(s){return sha1.hex(s);} // http://user1.matsumoto.ne.jp/~goma/js/hash.html
//_RSASIGN_HASHHEXFUNC['sha256'] = function(s){return sha256.hex;} // http://user1.matsumoto.ne.jp/~goma/js/hash.html
var _RE_HEXDECONLY = new RegExp("");
_RE_HEXDECONLY.compile("[^0-9a-f]", "gi");
// ========================================================================
// Signature Generation
// ========================================================================
function _rsasign_getHexPaddedDigestInfoForString(s, keySize, hashAlg) {
var pmStrLen = keySize / 4;
var hashFunc = _RSASIGN_HASHHEXFUNC[hashAlg];
var sHashHex = hashFunc(s);
var sHead = "0001";
var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
var sMid = "";
var fLen = pmStrLen - sHead.length - sTail.length;
for (var i = 0; i < fLen; i += 2) {
sMid += "ff";
}
sPaddedMessageHex = sHead + sMid + sTail;
return sPaddedMessageHex;
}
function _zeroPaddingOfSignature(hex, bitLength) {
var s = "";
var nZero = bitLength / 4 - hex.length;
for (var i = 0; i < nZero; i++) {
s = s + "0";
}
return s + hex;
}
/**
* sign for a message string with RSA private key.<br/>
* @name signString
* @memberOf RSAKey#
* @function
* @param {String} s message string to be signed.
* @param {String} hashAlg hash algorithm name for signing.<br/>
* @return returns hexadecimal string of signature value.
*/
function _rsasign_signString(s, hashAlg) {
//alert("this.n.bitLength() = " + this.n.bitLength());
var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), hashAlg);
var biPaddedMessage = parseBigInt(hPM, 16);
var biSign = this.doPrivate(biPaddedMessage);
var hexSign = biSign.toString(16);
return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
}
function _rsasign_signStringWithSHA1(s) {
return _rsasign_signString.call(this, s, 'sha1');
}
function _rsasign_signStringWithSHA256(s) {
return _rsasign_signString.call(this, s, 'sha256');
}
// PKCS#1 (PSS) mask generation function
function pss_mgf1_str(seed, len, hash) {
var mask = '', i = 0;
while (mask.length < len) {
mask += hash(seed + String.fromCharCode.apply(String, [
(i & 0xff000000) >> 24,
(i & 0x00ff0000) >> 16,
(i & 0x0000ff00) >> 8,
i & 0x000000ff]));
i += 1;
}
return mask;
}
/**
* sign for a message string with RSA private key by PKCS#1 PSS signing.<br/>
* @name signStringPSS
* @memberOf RSAKey#
* @function
* @param {String} s message string to be signed.
* @param {String} hashAlg hash algorithm name for signing.<br/>
* @return returns hexadecimal string of signature value.
*/
function _rsasign_signStringPSS(s, hashAlg, sLen) {
var hashFunc = _RSASIGN_HASHRAWFUNC[hashAlg];
var mHash = hashFunc(s);
var hLen = mHash.length;
var emBits = this.n.bitLength() - 1;
var emLen = Math.ceil(emBits / 8);
var i;
if (sLen === -1) {
sLen = hLen; // same has hash length
} else if ((sLen === -2) || (sLen === undefined)) {
sLen = emLen - hLen - 2; // maximum
} else if (sLen < -2) {
throw "invalid salt length";
}
if (emLen < (hLen + sLen + 2)) {
throw "data too long";
}
var salt = '';
if (sLen > 0) {
salt = new Array(sLen);
new SecureRandom().nextBytes(salt);
salt = String.fromCharCode.apply(String, salt);
}
var H = hashFunc('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash + salt);
var PS = [];
for (i = 0; i < emLen - sLen - hLen - 2; i += 1) {
PS[i] = 0x00;
}
var DB = String.fromCharCode.apply(String, PS) + '\x01' + salt;
var dbMask = pss_mgf1_str(H, DB.length, hashFunc);
var maskedDB = [];
for (i = 0; i < DB.length; i += 1) {
maskedDB[i] = DB.charCodeAt(i) ^ dbMask.charCodeAt(i);
}
var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;
maskedDB[0] &= ~mask;
for (i = 0; i < hLen; i++) {
maskedDB.push(H.charCodeAt(i));
}
maskedDB.push(0xbc);
return _zeroPaddingOfSignature(
this.doPrivate(new BigInteger(maskedDB)).toString(16),
this.n.bitLength());
}
// ========================================================================
// Signature Verification
// ========================================================================
function _rsasign_getDecryptSignatureBI(biSig, hN, hE) {
var rsa = new RSAKey();
rsa.setPublic(hN, hE);
var biDecryptedSig = rsa.doPublic(biSig);
return biDecryptedSig;
}
function _rsasign_getHexDigestInfoFromSig(biSig, hN, hE) {
var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE);
var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
return hDigestInfo;
}
function _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo) {
for (var algName in _RSASIGN_DIHEAD) {
var head = _RSASIGN_DIHEAD[algName];
var len = head.length;
if (hDigestInfo.substring(0, len) == head) {
var a = [algName, hDigestInfo.substring(len)];
return a;
}
}
return [];
}
function _rsasign_verifySignatureWithArgs(sMsg, biSig, hN, hE) {
var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE);
var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
if (digestInfoAry.length == 0) return false;
var algName = digestInfoAry[0];
var diHashValue = digestInfoAry[1];
var ff = _RSASIGN_HASHHEXFUNC[algName];
var msgHashValue = ff(sMsg);
return (diHashValue == msgHashValue);
}
function _rsasign_verifyHexSignatureForMessage(hSig, sMsg) {
var biSig = parseBigInt(hSig, 16);
var result = _rsasign_verifySignatureWithArgs(sMsg, biSig,
this.n.toString(16),
this.e.toString(16));
return result;
}
/**
* verifies a sigature for a message string with RSA public key.<br/>
* @name verifyString
* @memberOf RSAKey#
* @function
* @param {String} sMsg message string to be verified.
* @param {String} hSig hexadecimal string of siganture.<br/>
* non-hexadecimal charactors including new lines will be ignored.
* @return returns 1 if valid, otherwise 0
*/
function _rsasign_verifyString(sMsg, hSig) {
hSig = hSig.replace(_RE_HEXDECONLY, '');
if (hSig.length != this.n.bitLength() / 4) return 0;
hSig = hSig.replace(/[ \n]+/g, "");
var biSig = parseBigInt(hSig, 16);
var biDecryptedSig = this.doPublic(biSig);
var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
if (digestInfoAry.length == 0) return false;
var algName = digestInfoAry[0];
var diHashValue = digestInfoAry[1];
var ff = _RSASIGN_HASHHEXFUNC[algName];
var msgHashValue = ff(sMsg);
return (diHashValue == msgHashValue);
}
/**
* verifies a sigature for a message string with RSA public key by PKCS#1 PSS sign.<br/>
* @name verifyStringPSS
* @memberOf RSAKey#
* @function
* @param {String} sMsg message string to be verified.
* @param {String} hSig hexadecimal string of siganture.<br/>
* non-hexadecimal charactors including new lines will be ignored.
* @return returns 1 if valid, otherwise 0
*/
function _rsasign_verifyStringPSS(sMsg, hSig, hashAlg, sLen) {
if (hSig.length !== this.n.bitLength() / 4) {
return false;
}
var hashFunc = _RSASIGN_HASHRAWFUNC[hashAlg];
var mHash = hashFunc(sMsg);
var hLen = mHash.length;
var emBits = this.n.bitLength() - 1;
var emLen = Math.ceil(emBits / 8);
var i;
if (sLen === -1) {
sLen = hLen; // same has hash length
} else if ((sLen === -2) || (sLen === undefined)) {
sLen = emLen - hLen - 2; // maximum
} else if (sLen < -2) {
throw "invalid salt length";
}
if (emLen < (hLen + sLen + 2)) {
throw "data too long";
}
var em = this.doPublic(parseBigInt(hSig, 16)).toByteArray();
for (i = 0; i < em.length; i += 1) {
em[i] &= 0xff;
}
while (em.length < emLen) {
em.unshift(0);
}
if (em[emLen -1] !== 0xbc) {
throw "encoded message does not end in 0xbc";
}
em = String.fromCharCode.apply(String, em);
var maskedDB = em.substr(0, emLen - hLen - 1);
var H = em.substr(maskedDB.length, hLen);
var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;
if ((maskedDB.charCodeAt(0) & mask) !== 0) {
throw "bits beyond keysize not zero";
}
var dbMask = pss_mgf1_str(H, maskedDB.length, hashFunc);
var DB = [];
for (i = 0; i < maskedDB.length; i += 1) {
DB[i] = maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i);
}
DB[0] &= ~mask;
var checkLen = emLen - hLen - sLen - 2;
for (i = 0; i < checkLen; i += 1) {
if (DB[i] !== 0x00) {
throw "leftmost octets not zero";
}
}
if (DB[checkLen] !== 0x01) {
throw "0x01 marker not found";
}
return H === hashFunc('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash +
String.fromCharCode.apply(String, DB.slice(-sLen)));
}
RSAKey.prototype.signString = _rsasign_signString;
RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1;
RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256;
RSAKey.prototype.sign = _rsasign_signString;
RSAKey.prototype.signWithSHA1 = _rsasign_signStringWithSHA1;
RSAKey.prototype.signWithSHA256 = _rsasign_signStringWithSHA256;
RSAKey.prototype.signStringPSS = _rsasign_signStringPSS;
RSAKey.prototype.signPSS = _rsasign_signStringPSS;
RSAKey.SALT_LEN_HLEN = -1;
RSAKey.SALT_LEN_MAX = -2;
RSAKey.prototype.verifyString = _rsasign_verifyString;
RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage;
RSAKey.prototype.verify = _rsasign_verifyString;
RSAKey.prototype.verifyHexSignatureForByteArrayMessage = _rsasign_verifyHexSignatureForMessage;
RSAKey.prototype.verifyStringPSS = _rsasign_verifyStringPSS;
RSAKey.prototype.verifyPSS = _rsasign_verifyStringPSS;
RSAKey.SALT_LEN_RECOVER = -2;
/**
* @name RSAKey
* @class key of RSA public key algorithm
* @description Tom Wu's RSA Key class and extension
*/
module.exports = RSAKey
},{"./rsapem-1.1.js":20,"jsbn":65}],22:[function(require,module,exports){
/*
CryptoJS v3.1.2
code.google.com/p/crypto-js
(c) 2009-2013 by Jeff Mott. All rights reserved.
code.google.com/p/crypto-js/wiki/License
*/
// Shortcuts
var C = require('./core.js');
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var Hasher = C_lib.Hasher;
var C_algo = C.algo;
// Initialization and round constants tables
var H = [];
var K = [];
// Compute constants
(function () {
function isPrime(n) {
var sqrtN = Math.sqrt(n);
for (var factor = 2; factor <= sqrtN; factor++) {
if (!(n % factor)) {
return false;
}
}
return true;
}
function getFractionalBits(n) {
return ((n - (n | 0)) * 0x100000000) | 0;
}
var n = 2;
var nPrime = 0;
while (nPrime < 64) {
if (isPrime(n)) {
if (nPrime < 8) {
H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2));
}
K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3));
nPrime++;
}
n++;
}
}());
// Reusable object
var W = [];
/**
* SHA-256 hash algorithm.
*/
var SHA256 = C_algo.SHA256 = Hasher.extend({
_doReset: function () {
this._hash = new WordArray.init(H.slice(0));
},
_doProcessBlock: function (M, offset) {
// Shortcut
var H = this._hash.words;
// Working variables
var a = H[0];
var b = H[1];
var c = H[2];
var d = H[3];
var e = H[4];
var f = H[5];
var g = H[6];
var h = H[7];
// Computation
for (var i = 0; i < 64; i++) {
if (i < 16) {
W[i] = M[offset + i] | 0;
} else {
var gamma0x = W[i - 15];
var gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^
((gamma0x << 14) | (gamma0x >>> 18)) ^
(gamma0x >>> 3);
var gamma1x = W[i - 2];
var gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^
((gamma1x << 13) | (gamma1x >>> 19)) ^
(gamma1x >>> 10);
W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
}
var ch = (e & f) ^ (~e & g);
var maj = (a & b) ^ (a & c) ^ (b & c);
var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22));
var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25));
var t1 = h + sigma1 + ch + K[i] + W[i];
var t2 = sigma0 + maj;
h = g;
g = f;
f = e;
e = (d + t1) | 0;
d = c;
c = b;
b = a;
a = (t1 + t2) | 0;
}
// Intermediate hash value
H[0] = (H[0] + a) | 0;
H[1] = (H[1] + b) | 0;
H[2] = (H[2] + c) | 0;
H[3] = (H[3] + d) | 0;
H[4] = (H[4] + e) | 0;
H[5] = (H[5] + f) | 0;
H[6] = (H[6] + g) | 0;
H[7] = (H[7] + h) | 0;
},
_doFinalize: function () {
// Shortcuts
var data = this._data;
var dataWords = data.words;
var nBitsTotal = this._nDataBytes * 8;
var nBitsLeft = data.sigBytes * 8;
// Add padding
dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
data.sigBytes = dataWords.length * 4;
// Hash final blocks
this._process();
// Return final computed hash
return this._hash;
},
clone: function () {
var clone = Hasher.clone.call(this);
clone._hash = this._hash.clone();
return clone;
}
});
/**
* Shortcut function to the hasher's object interface.
*
* @param {WordArray|string} message The message to hash.
*
* @return {WordArray} The hash.
*
* @static
*
* @example
*
* var hash = CryptoJS.SHA256('message');
* var hash = CryptoJS.SHA256(wordArray);
*/
C.SHA256 = Hasher._createHelper(SHA256);
/**
* Shortcut function to the HMAC's object interface.
*
* @param {WordArray|string} message The message to hash.
* @param {WordArray|string} key The secret key.
*
* @return {WordArray} The HMAC.
*
* @static
*
* @example
*
* var hmac = CryptoJS.HmacSHA256(message, key);
*/
C.HmacSHA256 = Hasher._createHmacHelper(SHA256);
module.exports = C
},{"./core.js":16}],23:[function(require,module,exports){
exports.Face = require('./js/face.js').Face;
exports.NDN = require('./js/face.js').NDN; // deprecated
exports.Closure = require('./js/closure.js').Closure;
exports.Name = require('./js/name.js').Name;
exports.ForwardingFlags = require('./js/forwarding-flags.js').ForwardingFlags;
exports.Interest = require('./js/interest.js').Interest;
exports.Exclude = require('./js/exclude.js').Exclude;
exports.Data = require('./js/data.js').Data;
exports.ContentObject = require('./js/data.js').ContentObject; // deprecated
exports.ContentType = require('./js/meta-info.js').ContentType;
exports.MetaInfo = require('./js/meta-info.js').MetaInfo;
exports.SignedInfo = require('./js/meta-info.js').SignedInfo; // deprecated
exports.Key = require('./js/key.js').Key;
exports.KeyLocator = require('./js/key-locator.js').KeyLocator;
exports.KeyName = require('./js/key-locator.js').KeyName;
exports.KeyLocatorType = require('./js/key-locator.js').KeyLocatorType;
exports.PublisherPublicKeyDigest = require('./js/publisher-public-key-digest.js').PublisherPublicKeyDigest;
exports.WireFormat = require('./js/encoding/wire-format.js').WireFormat;
exports.BinaryXmlWireFormat = require('./js/encoding/binary-xml-wire-format.js').BinaryXmlWireFormat;
exports.TlvWireFormat = require('./js/encoding/tlv-wire-format.js').TlvWireFormat;
exports.TlvDecoder = require('./js/encoding/tlv/tlv-decoder.js').TlvDecoder;
exports.Tlv = require('./js/encoding/tlv/tlv.js').Tlv
exports.DataUtils = require('./js/encoding/data-utils.js').DataUtils;
exports.EncodingUtils = require('./js/encoding/encoding-utils.js').EncodingUtils;
exports.Blob = require('./js/util/blob.js').Blob;
exports.NameEnumeration = require('./js/util/name-enumeration.js').NameEnumeration;
exports.NDNTime = require('./js/util/ndn-time.js').NDNTime;
exports.globalKeyManager = require('./js/security/key-manager.js').globalKeyManager;
exports.ElementReader = require('./js/encoding/element-reader.js').ElementReader;
exports.customBuffer = require('./js/browserify.js').Buffer
},{"./js/browserify.js":25,"./js/closure.js":26,"./js/data.js":27,"./js/encoding/binary-xml-wire-format.js":31,"./js/encoding/data-utils.js":32,"./js/encoding/element-reader.js":34,"./js/encoding/encoding-utils.js":35,"./js/encoding/tlv-wire-format.js":37,"./js/encoding/tlv/tlv-decoder.js":38,"./js/encoding/tlv/tlv.js":41,"./js/encoding/wire-format.js":42,"./js/exclude.js":43,"./js/face.js":45,"./js/forwarding-flags.js":47,"./js/interest.js":48,"./js/key-locator.js":49,"./js/key.js":50,"./js/meta-info.js":52,"./js/name.js":53,"./js/publisher-public-key-digest.js":55,"./js/security/key-manager.js":56,"./js/util/blob.js":59,"./js/util/name-enumeration.js":61,"./js/util/ndn-time.js":63}],24:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
// The Face constructor uses TcpTransport by default which is not available in the browser, so override to WebSocketTransport.
exports.TcpTransport = require('./transport/web-socket-transport.js').WebSocketTransport;
},{"./transport/web-socket-transport.js":58}],25:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Wentao Shang
* See COPYING for copyright and distribution information.
*/
// Library namespace
var ndn = ndn || {};
var exports = ndn;
var ASN1HEX = require('../contrib/securityLib/asn1hex-1.1.js')
var KJUR = require('../contrib/securityLib/crypto-1.0.js')
var RSAKey = require('../contrib/securityLib/rsasign-1.2.js')
var b64tohex = require('../contrib/securityLib/base64.js').b64tohex
// Factory method to create node.js compatible buffer objects
var customBuf = function customBuf(data, format)
{
var obj;
if (typeof data == 'number')
obj = new Uint8Array(data);
else if (typeof data == 'string') {
if (format == null || format == 'utf8') {
var utf8 = customBuf.str2rstr_utf8(data);
obj = new Uint8Array(utf8.length);
for (var i = 0; i < utf8.length; i++)
obj[i] = utf8.charCodeAt(i);
}
else if (format == 'binary') {
obj = new Uint8Array(data.length);
for (var i = 0; i < data.length; i++)
obj[i] = data.charCodeAt(i);
}
else if (format == 'hex') {
obj = new Uint8Array(Math.floor(data.length / 2));
var i = 0;
data.replace(/(..)/g, function(ss) {
obj[i++] = parseInt(ss, 16);
});
}
else if (format == 'base64') {
var hex = b64tohex(data);
obj = new Uint8Array(Math.floor(hex.length / 2));
var i = 0;
hex.replace(/(..)/g, function(ss) {
obj[i++] = parseInt(ss, 16);
});
}
else
throw new Error('Buffer: unknown encoding format ' + format);
}
else if (typeof data == 'object' && (data instanceof Uint8Array || data instanceof customBuf)) {
// The second argument is a boolean for "copy", default true.
if (format == false)
obj = data.subarray(0);
else
obj = new Uint8Array(data);
}
else if (typeof data == 'object' && data instanceof ArrayBuffer)
// Copy.
obj = new Uint8Array(data);
else if (typeof data == 'object')
// Assume component is a byte array. We can't check instanceof Array because
// this doesn't work in JavaScript if the array comes from a different module.
obj = new Uint8Array(data);
else
throw new Error('Buffer: unknown data type.');
try {
obj.__proto__ = customBuf.prototype;
} catch(ex) {
throw new Error("Buffer: Set obj.__proto__ exception: " + ex);
}
obj.__proto__.toString = function(encoding) {
if (encoding == null) {
var ret = "";
for (var i = 0; i < this.length; i++)
ret += String.fromCharCode(this[i]);
return ret;
}
var ret = "";
for (var i = 0; i < this.length; i++)
ret += (this[i] < 16 ? "0" : "") + this[i].toString(16);
if (encoding == 'hex')
return ret;
else if (encoding == 'base64')
return hex2b64(ret);
else
throw new Error('Buffer.toString: unknown encoding format ' + encoding);
};
obj.__proto__.slice = function(begin, end) {
if (end !== undefined)
return new customBuf(this.subarray(begin, end), false);
else
return new customBuf(this.subarray(begin), false);
};
obj.__proto__.copy = function(target, targetStart) {
if (targetStart !== undefined)
target.set(this, targetStart);
else
target.set(this);
};
return obj;
};
customBuf.prototype = Uint8Array.prototype;
customBuf.concat = function(arrays)
{
var totalLength = 0;
for (var i = 0; i < arrays.length; ++i)
totalLength += arrays[i].length;
var result = new customBuf(totalLength);
var offset = 0;
for (var i = 0; i < arrays.length; ++i) {
result.set(arrays[i], offset);
offset += arrays[i].length;
}
return result;
};
customBuf.str2rstr_utf8 = function(input)
{
var output = "";
var i = -1;
var x, y;
while (++i < input.length)
{
// Decode utf-16 surrogate pairs
x = input.charCodeAt(i);
y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
{
x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
i++;
}
// Encode output as utf-8
if (x <= 0x7F)
output += String.fromCharCode(x);
else if (x <= 0x7FF)
output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
0x80 | ( x & 0x3F));
else if (x <= 0xFFFF)
output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
0x80 | ((x >>> 6 ) & 0x3F),
0x80 | ( x & 0x3F));
else if (x <= 0x1FFFFF)
output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
0x80 | ((x >>> 12) & 0x3F),
0x80 | ((x >>> 6 ) & 0x3F),
0x80 | ( x & 0x3F));
}
return output;
};
// Factory method to create hasher objects
exports.createHash = function(alg)
{
if (alg != 'sha256')
throw new Error('createHash: unsupported algorithm.');
var obj = {};
obj.md = new KJUR.crypto.MessageDigest({alg: "sha256", prov: "cryptojs"});
obj.update = function(buf) {
this.md.updateHex(buf.toString('hex'));
};
obj.digest = function() {
return new customBuf(this.md.digest(), 'hex');
};
return obj;
};
// Factory method to create RSA signer objects
exports.createSign = function(alg)
{
if (alg != 'RSA-SHA256')
throw new Error('createSign: unsupported algorithm.');
var obj = {};
obj.arr = [];
obj.update = function(buf) {
this.arr.push(buf);
};
obj.sign = function(keypem) {
var rsa = new RSAKey();
rsa.readPrivateKeyFromPEMString(keypem);
var signer = new KJUR.crypto.Signature({alg: "SHA256withRSA", prov: "cryptojs/jsrsa"});
signer.initSign(rsa);
for (var i = 0; i < this.arr.length; ++i)
signer.updateHex(this.arr[i].toString('hex'));
return new customBuf(signer.sign(), 'hex');
};
return obj;
};
// Factory method to create RSA verifier objects
exports.createVerify = function(alg)
{
if (alg != 'RSA-SHA256')
throw new Error('createSign: unsupported algorithm.');
var obj = {};
obj.arr = [];
obj.update = function(buf) {
this.arr.push(buf);
};
var getSubjectPublicKeyPosFromHex = function(hPub) {
var a = ASN1HEX.getPosArrayOfChildren_AtObj(hPub, 0);
if (a.length != 2)
return -1;
var pBitString = a[1];
if (hPub.substring(pBitString, pBitString + 2) != '03')
return -1;
var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hPub, pBitString);
if (hPub.substring(pBitStringV, pBitStringV + 2) != '00')
return -1;
return pBitStringV + 2;
};
var readPublicDER = function(pub_der) {
var hex = pub_der.toString('hex');
var p = getSubjectPublicKeyPosFromHex(hex);
var a = ASN1HEX.getPosArrayOfChildren_AtObj(hex, p);
if (a.length != 2)
return null;
var hN = ASN1HEX.getHexOfV_AtObj(hex, a[0]);
var hE = ASN1HEX.getHexOfV_AtObj(hex, a[1]);
var rsaKey = new RSAKey();
rsaKey.setPublic(hN, hE);
return rsaKey;
};
obj.verify = function(keypem, sig) {
var key = new ndn.Key();
key.fromPemString(keypem);
var rsa = readPublicDER(key.publicToDER());
var signer = new KJUR.crypto.Signature({alg: "SHA256withRSA", prov: "cryptojs/jsrsa"});
signer.initVerifyByPublicKey(rsa);
for (var i = 0; i < this.arr.length; i++)
signer.updateHex(this.arr[i].toString('hex'));
var hSig = sig.toString('hex');
return signer.verify(hSig);
};
return obj;
};
exports.randomBytes = function(size)
{
// TODO: Use a cryptographic random number generator.
var result = new customBuf(size);
for (var i = 0; i < size; ++i)
result[i] = Math.floor(Math.random() * 256);
return result;
};
exports.Buffer = customBuf;
module.exports = exports;
},{"../contrib/securityLib/asn1hex-1.1.js":14,"../contrib/securityLib/base64.js":15,"../contrib/securityLib/crypto-1.0.js":17,"../contrib/securityLib/rsasign-1.2.js":21}],26:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
* Provide the callback closure for the async communication methods in the Face class.
* This is a port of Closure.py from PyNDN, written by:
* Derek Kulinski <takeda@takeda.tk>
* Jeff Burke <jburke@ucla.edu>
*/
/**
* A subclass of Closure is passed to expressInterest and registerPrefix.
* @deprecated You should use the forms of expressInterest and registerPrefix which use callbacks instead of Closure.
* @constructor
*/
var Closure = function Closure()
{
// I don't think storing Face's closure is needed
// and it creates a reference loop, as of now both
// of those variables are never set -- Derek
//
// Use instance variables to return data to callback
this.ndn_data = null; // this holds the ndn_closure
this.ndn_data_dirty = false;
};
exports.Closure = Closure;
// Upcall result
Closure.RESULT_ERR = -1; // upcall detected an error
Closure.RESULT_OK = 0; // normal upcall return
Closure.RESULT_REEXPRESS = 1; // reexpress the same interest again
Closure.RESULT_INTEREST_CONSUMED = 2; // upcall claims to consume interest
Closure.RESULT_VERIFY = 3; // force an unverified result to be verified
Closure.RESULT_FETCHKEY = 4; // get the key in the key locator and re-call the interest
// with the key available in the local storage
// Upcall kind
Closure.UPCALL_FINAL = 0; // handler is about to be deregistered
Closure.UPCALL_INTEREST = 1; // incoming interest
Closure.UPCALL_CONSUMED_INTEREST = 2; // incoming interest, someone has answered
Closure.UPCALL_CONTENT = 3; // incoming verified content
Closure.UPCALL_INTEREST_TIMED_OUT = 4; // interest timed out
Closure.UPCALL_CONTENT_UNVERIFIED = 5; // content that has not been verified
Closure.UPCALL_CONTENT_BAD = 6; // verification failed
/**
* Override this in your subclass.
* If you're getting strange errors in upcall()
* check your code whether you're returning a value.
*/
Closure.prototype.upcall = function(kind, upcallInfo)
{
//dump('upcall ' + this + " " + kind + " " + upcallInfo + "\n");
return Closure.RESULT_OK;
};
/**
* An UpcallInfo is passed to Closure.upcall.
* @constructor
*/
var UpcallInfo = function UpcallInfo(face, interest, matchedComps, data)
{
this.face = face; // Face object (not used)
this.ndn = face; // deprecated
this.interest = interest; // Interest object
this.matchedComps = matchedComps; // int
this.data = data; // Data
this.contentObject = data; // deprecated. Include for backward compatibility.
};
UpcallInfo.prototype.toString = function()
{
var ret = "face = " + this.face;
ret += "\nInterest = " + this.interest;
ret += "\nmatchedComps = " + this.matchedComps;
ret += "\nData: " + this.data;
return ret;
};
exports.UpcallInfo = UpcallInfo;
},{}],27:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Meki Cheraoui
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
* This class represents an NDN Data object.
*/
var Blob = require('./util/blob.js').Blob;
var SignedBlob = require('./util/signed-blob.js').SignedBlob;
var BinaryXMLEncoder = require('./encoding/binary-xml-encoder.js').BinaryXMLEncoder;
var NDNProtocolDTags = require('./util/ndn-protoco-id-tags.js').NDNProtocolDTags;
var DataUtils = require('./encoding/data-utils.js').DataUtils;
var Name = require('./name.js').Name;
var Signature = require('./signature.js').Signature;
var MetaInfo = require('./meta-info.js').MetaInfo;
var KeyLocator = require('./key-locator.js').KeyLocator;
var globalKeyManager = require('./security/key-manager.js').globalKeyManager;
var WireFormat = require('./encoding/wire-format.js').WireFormat;
var customBuf = require('./buffer.js').Buffer
/**
* Create a new Data with the optional values. There are 2 forms of constructor:
* new Data([name] [, content]);
* new Data(name, metaInfo [, content]);
*
* @constructor
* @param {Name} name
* @param {MetaInfo} metaInfo
* @param {Buffer} content
*/
var Data = function Data(name, metaInfoOrContent, arg3)
{
if (typeof name === 'string')
this.name = new Name(name);
else
this.name = typeof name === 'object' && name instanceof Name ?
new Name(name) : new Name();
var metaInfo;
var content;
if (typeof metaInfoOrContent === 'object' &&
metaInfoOrContent instanceof MetaInfo) {
metaInfo = metaInfoOrContent;
content = arg3;
}
else {
metaInfo = null;
content = metaInfoOrContent;
}
// Use signedInfo instead of metaInfo for backward compatibility.
this.signedInfo = typeof metaInfo === 'object' && metaInfo instanceof MetaInfo ?
new MetaInfo(metaInfo) : new MetaInfo();
if (typeof content === 'string')
this.content = DataUtils.toNumbersFromString(content);
else if (typeof content === 'object' && content instanceof Blob)
this.content = content.buf();
else
this.content = content;
this.signature = new Signature();
this.wireEncoding = SignedBlob();
};
exports.Data = Data;
/**
* Get the data packet's name.
* @returns {Name} The name.
*/
Data.prototype.getName = function()
{
return this.name;
};
/**
* Get the data packet's meta info.
* @returns {MetaInfo} The meta info.
*/
Data.prototype.getMetaInfo = function()
{
return this.signedInfo;
};
/**
* Get the data packet's signature object.
* @returns {Signature} The signature object.
*/
Data.prototype.getSignature = function()
{
return this.signature;
};
/**
* Get the data packet's content.
* @returns {Buffer} The content as a customBuf, which is null if unspecified.
*/
Data.prototype.getContent = function()
{
return this.content;
};
/**
* Set name to a copy of the given Name.
* @param {Name} name The Name which is copied.
* @returns {Data} This Data so that you can chain calls to update values.
*/
Data.prototype.setName = function(name)
{
this.name = typeof name === 'object' && name instanceof Name ?
new Name(name) : new Name();
// The object has changed, so the wireEncoding is invalid.
this.wireEncoding = SignedBlob();
return this;
};
/**
* Set metaInfo to a copy of the given MetaInfo.
* @param {MetaInfo} metaInfo The MetaInfo which is copied.
* @returns {Data} This Data so that you can chain calls to update values.
*/
Data.prototype.setMetaInfo = function(metaInfo)
{
this.signedInfo = typeof metaInfo === 'object' && metaInfo instanceof MetaInfo ?
new MetaInfo(metaInfo) : new MetaInfo();
// The object has changed, so the wireEncoding is invalid.
this.wireEncoding = SignedBlob();
return this;
};
/**
* Set the signature to a copy of the given signature.
* @param {Signature} signature The signature object which is cloned.
* @returns {Data} This Data so that you can chain calls to update values.
*/
Data.prototype.setSignature = function(signature)
{
this.signature = typeof signature === 'object' && signature instanceof Signature ?
signature.clone() : new Signature();
// The object has changed, so the wireEncoding is invalid.
this.wireEncoding = SignedBlob();
return this;
};
/**
* Set the content to the given value.
* @param {type} content The array this is copied.
* @returns {Data} This Data so that you can chain calls to update values.
*/
Data.prototype.setContent = function(content)
{
if (typeof content === 'string')
this.content = DataUtils.toNumbersFromString(content);
else if (typeof content === 'object' && content instanceof Blob)
this.content = content.buf();
else
this.content = new customBuf(content);
// The object has changed, so the wireEncoding is invalid.
this.wireEncoding = SignedBlob();
return this;
};
Data.prototype.sign = function(wireFormat)
{
var rs = require('buffer')
var ss = require('./crypto.js')
wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
if (this.getSignatureOrMetaInfoKeyLocator() == null ||
this.getSignatureOrMetaInfoKeyLocator().getType() == null)
this.getMetaInfo().setFields();
if (this.wireEncoding == null || this.wireEncoding.isNull()) {
// Need to encode to set wireEncoding.
// Set an initial empty signature so that we can encode.
this.getSignature().setSignature(new customBuf(128));
this.wireEncode(wireFormat);
}
var rsa = require("./crypto.js").createSign('RSA-SHA256');
rsa.update(this.wireEncoding.signedBuf());
var sig = new customBuf(rsa.sign(globalKeyManager.privateKey));
this.signature.signature = sig;
};
Data.prototype.verify = function(/*Key*/ key)
{
if (key == null || key.publicKeyPem == null)
throw new Error('Cannot verify Data without a public key.');
if (this.wireEncoding == null || this.wireEncoding.isNull())
// Need to encode to set wireEncoding.
this.wireEncode();
var verifier = require('./crypto.js').createVerify('RSA-SHA256');
verifier.update(this.wireEncoding.signedBuf());
return verifier.verify(key.publicKeyPem, this.signature.signature);
};
Data.prototype.getElementLabel = function() { return NDNProtocolDTags.Data; };
/**
* Encode this Data for a particular wire format.
* @param {a subclass of WireFormat} wireFormat (optional) A WireFormat object
* used to encode this object. If omitted, use WireFormat.getDefaultWireFormat().
* @returns {SignedBlob} The encoded buffer in a SignedBlob object.
*/
Data.prototype.wireEncode = function(wireFormat)
{
var wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
var result = wireFormat.encodeData(this);
// TODO: Implement setDefaultWireEncoding with getChangeCount support.
this.wireEncoding = new SignedBlob
(result.encoding, result.signedPortionBeginOffset,
result.signedPortionEndOffset);
return this.wireEncoding;
};
/**
* Decode the input using a particular wire format and update this Data.
* @param {Blob|Buffer} input The buffer with the bytes to decode.
* @param {a subclass of WireFormat} wireFormat (optional) A WireFormat object
* used to decode this object. If omitted, use WireFormat.getDefaultWireFormat().
*/
Data.prototype.wireDecode = function(input, wireFormat)
{
var wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
// If input is a blob, get its buf().
var decodeBuffer = typeof input === 'object' && input instanceof Blob ?
input.buf() : input;
var result = wireFormat.decodeData(this, decodeBuffer);
// TODO: Implement setDefaultWireEncoding with getChangeCount support.
// In the Blob constructor, set copy true, but if input is already a Blob, it
// won't copy.
this.wireEncoding = new SignedBlob
(new Blob(input, true), result.signedPortionBeginOffset,
result.signedPortionEndOffset);
};
/**
* If getSignature() has a key locator, return it. Otherwise, use
* the key locator from getMetaInfo() for backward compatibility and print
* a warning to console.log that the key locator has moved to the Signature
* object. If neither has a key locator, return an empty key locator.
* When we stop supporting the key locator in MetaInfo, this function is not
* necessary and we will just use the key locator in the Signature.
* @returns {KeyLocator} The key locator to use.
*/
Data.prototype.getSignatureOrMetaInfoKeyLocator = function()
{
if (this.signature != null && this.signature.getKeyLocator() != null &&
this.signature.getKeyLocator().getType() != null &&
this.signature.getKeyLocator().getType() >= 0)
// The application is using the key locator in the correct object.
return this.signature.getKeyLocator();
if (this.signedInfo != null && this.signedInfo.locator != null &&
this.signedInfo.locator.type != null &&
this.signedInfo.locator.type >= 0) {
//console.log("WARNING: Temporarily using the key locator found in the MetaInfo - expected it in the Signature object.");
//console.log("WARNING: In the future, the key locator in the Signature object will not be supported.");
return this.signedInfo.locator;
}
// Return the empty key locator from the Signature object if possible.
if (this.signature != null && this.signature.getKeyLocator() != null)
return this.signature.getKeyLocator();
else
return new KeyLocator();
}
// Since binary-xml-wire-format.js includes this file, put these at the bottom to avoid problems with cycles of require.
var BinaryXmlWireFormat = require('./encoding/binary-xml-wire-format.js').BinaryXmlWireFormat;
/**
* @deprecated Use BinaryXmlWireFormat.decodeData.
*/
Data.prototype.from_ndnb = function(/*XMLDecoder*/ decoder)
{
BinaryXmlWireFormat.decodeData(this, decoder);
};
/**
* @deprecated Use BinaryXmlWireFormat.encodeData.
*/
Data.prototype.to_ndnb = function(/*XMLEncoder*/ encoder)
{
BinaryXmlWireFormat.encodeData(this, encoder);
};
/**
* @deprecated Use wireEncode. If you need binary XML, use
* wireEncode(BinaryXmlWireFormat.get()).
*/
Data.prototype.encode = function(wireFormat)
{
wireFormat = (wireFormat || BinaryXmlWireFormat.get());
return wireFormat.encodeData(this).buf();
};
/**
* @deprecated Use wireDecode. If you need binary XML, use
* wireDecode(input, BinaryXmlWireFormat.get()).
*/
Data.prototype.decode = function(input, wireFormat)
{
wireFormat = (wireFormat || BinaryXmlWireFormat.get());
wireFormat.decodeData(this, input);
};
/**
* @deprecated Use new Data.
*/
var ContentObject = function ContentObject(name, signedInfo, content)
{
// Call the base constructor.
Data.call(this, name, signedInfo, content);
}
ContentObject.prototype = new Data();
exports.ContentObject = ContentObject;
},{"./buffer.js":25,"./crypto.js":25,"./encoding/binary-xml-encoder.js":29,"./encoding/binary-xml-wire-format.js":31,"./encoding/data-utils.js":32,"./encoding/wire-format.js":42,"./key-locator.js":49,"./meta-info.js":52,"./name.js":53,"./security/key-manager.js":56,"./signature.js":57,"./util/blob.js":59,"./util/ndn-protoco-id-tags.js":62,"./util/signed-blob.js":64,"buffer":1}],28:[function(require,module,exports){
/**
* This class is used to decode ndnb binary elements (blob, type/value pairs).
*
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Meki Cheraoui
* See COPYING for copyright and distribution information.
*/
var customBuf = require('../buffer.js').Buffer
var NDNProtocolDTags = require('../util/ndn-protoco-id-tags.js').NDNProtocolDTags;
var NDNTime = require('../util/ndn-time.js').NDNTime;
var DataUtils = require('./data-utils.js').DataUtils;
var DecodingException = require('./decoding-exception.js').DecodingException;
var LOG = require('../log.js').Log.LOG;
var XML_EXT = 0x00;
var XML_TAG = 0x01;
var XML_DTAG = 0x02;
var XML_ATTR = 0x03;
var XML_DATTR = 0x04;
var XML_BLOB = 0x05;
var XML_UDATA = 0x06;
var XML_CLOSE = 0x0;
var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16;
var XML_TT_BITS = 3;
var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
var XML_TT_VAL_BITS = XML_TT_BITS + 1;
var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
var XML_REG_VAL_BITS = 7;
var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
var BYTE_MASK = 0xFF;
var LONG_BYTES = 8;
var LONG_BITS = 64;
var bits_11 = 0x0000007FF;
var bits_18 = 0x00003FFFF;
var bits_32 = 0x0FFFFFFFF;
//returns a string
tagToString = function(/*long*/ tagVal)
{
if (tagVal >= 0 && tagVal < NDNProtocolDTagsStrings.length) {
return NDNProtocolDTagsStrings[tagVal];
}
else if (tagVal == NDNProtocolDTags.NDNProtocolDataUnit) {
return NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT;
}
return null;
};
//returns a Long
stringToTag = function(/*String*/ tagName)
{
// the slow way, but right now we don't care.... want a static lookup for the forward direction
for (var i=0; i < NDNProtocolDTagsStrings.length; ++i) {
if (null != NDNProtocolDTagsStrings[i] && NDNProtocolDTagsStrings[i] == tagName)
return i;
}
if (NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT == tagName) {
return NDNProtocolDTags.NDNProtocolDataUnit;
}
return null;
};
/**
* @constructor
*/
var BinaryXMLDecoder = function BinaryXMLDecoder(input)
{
var MARK_LEN=512;
var DEBUG_MAX_LEN = 32768;
this.input = input;
this.offset = 0;
// peekDTag sets and checks this, and readElementStartDTag uses it to avoid reading again.
this.previouslyPeekedDTagStartOffset = -1;
};
exports.BinaryXMLDecoder = BinaryXMLDecoder;
/**
* Decode the header from the input starting at its position, expecting the type to be DTAG and the value to be expectedTag.
* Update the input's offset.
* @param {number} expectedTag The expected value for DTAG.
*/
BinaryXMLDecoder.prototype.readElementStartDTag = function(expectedTag)
{
if (this.offset == this.previouslyPeekedDTagStartOffset) {
// peekDTag already decoded this DTag.
if (this.previouslyPeekedDTag != expectedTag)
throw new DecodingException(new Error("Did not get the expected DTAG " + expectedTag + ", got " + this.previouslyPeekedDTag));
// Fast forward past the header.
this.offset = this.previouslyPeekedDTagEndOffset;
}
else {
var typeAndValue = this.decodeTypeAndVal();
if (typeAndValue == null || typeAndValue.type() != XML_DTAG)
throw new DecodingException(new Error("Header type is not a DTAG"));
if (typeAndValue.val() != expectedTag)
throw new DecodingException(new Error("Expected start element: " + expectedTag + " got: " + typeAndValue.val()));
}
};
/**
* @deprecated Use readElementStartDTag. Binary XML string tags and attributes are not used by any NDN encodings and
* support is not maintained in the code base.
*/
BinaryXMLDecoder.prototype.readStartElement = function(
//String
startTag,
//TreeMap<String, String>
attributes)
{
//TypeAndVal
var tv = this.decodeTypeAndVal();
if (null == tv)
throw new DecodingException(new Error("Expected start element: " + startTag + " got something not a tag."));
//String
var decodedTag = null;
if (tv.type() == XML_TAG) {
// Tag value represents length-1 as tags can never be empty.
var valval;
if (typeof tv.val() == 'string')
valval = (parseInt(tv.val())) + 1;
else
valval = (tv.val())+ 1;
decodedTag = this.decodeUString(valval);
}
else if (tv.type() == XML_DTAG)
decodedTag = tv.val();
if (null == decodedTag || decodedTag != startTag) {
console.log('expecting '+ startTag + ' but got '+ decodedTag);
throw new DecodingException(new Error("Expected start element: " + startTag + " got: " + decodedTag + "(" + tv.val() + ")"));
}
// DKS: does not read attributes out of stream if caller doesn't
// ask for them. Should possibly peek and skip over them regardless.
// TODO: fix this
if (null != attributes)
readAttributes(attributes);
};
/**
* @deprecated Binary XML string tags and attributes are not used by any NDN encodings and support is not maintained in the code base.
*/
BinaryXMLDecoder.prototype.readAttributes = function(
// array of [attributeName, attributeValue]
attributes)
{
if (null == attributes)
return;
try {
// Now need to get attributes.
//TypeAndVal
var nextTV = this.peekTypeAndVal();
while (null != nextTV && (XML_ATTR == nextTV.type() || XML_DATTR == nextTV.type())) {
// Decode this attribute. First, really read the type and value.
//this.TypeAndVal
var thisTV = this.decodeTypeAndVal();
//String
var attributeName = null;
if (XML_ATTR == thisTV.type()) {
// Tag value represents length-1 as attribute names cannot be empty.
var valval ;
if (typeof thisTV.val() == 'string')
valval = (parseInt(thisTV.val())) + 1;
else
valval = (thisTV.val())+ 1;
attributeName = this.decodeUString(valval);
}
else if (XML_DATTR == thisTV.type()) {
// DKS TODO are attributes same or different dictionary?
attributeName = tagToString(thisTV.val());
if (null == attributeName)
throw new DecodingException(new Error("Unknown DATTR value" + thisTV.val()));
}
// Attribute values are always UDATA
//String
var attributeValue = this.decodeUString();
attributes.push([attributeName, attributeValue]);
nextTV = this.peekTypeAndVal();
}
}
catch (e) {
throw new DecodingException(new Error("readStartElement", e));
}
};
/**
* @deprecated Use peekDTag. Binary XML string tags and attributes are not used by any NDN encodings and
* support is not maintained in the code base.
*/
BinaryXMLDecoder.prototype.peekStartElementAsString = function()
{
//String
var decodedTag = null;
var previousOffset = this.offset;
try {
// Have to distinguish genuine errors from wrong tags. Could either use
// a special exception subtype, or redo the work here.
//this.TypeAndVal
var tv = this.decodeTypeAndVal();
if (null != tv) {
if (tv.type() == XML_TAG) {
// Tag value represents length-1 as tags can never be empty.
var valval ;
if (typeof tv.val() == 'string')
valval = (parseInt(tv.val())) + 1;
else
valval = (tv.val())+ 1;
decodedTag = this.decodeUString(valval);
}
else if (tv.type() == XML_DTAG)
decodedTag = tagToString(tv.val());
} // else, not a type and val, probably an end element. rewind and return false.
}
catch (e) {
}
finally {
try {
this.offset = previousOffset;
}
catch (e) {
Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
throw new DecodingException(new Error("Cannot reset stream! " + e.getMessage(), e));
}
}
return decodedTag;
};
/**
* Decode the header from the input starting at its position, and if it is a DTAG where the value is the expectedTag,
* then set return true. Do not update the input's offset.
* @param {number} expectedTag The expected value for DTAG.
* @returns {boolean} True if the tag is the expected tag, otherwise false.
*/
BinaryXMLDecoder.prototype.peekDTag = function(expectedTag)
{
if (this.offset == this.previouslyPeekedDTagStartOffset)
// We already decoded this DTag.
return this.previouslyPeekedDTag == expectedTag;
else {
// First check if it is an element close (which cannot be the expected tag).
if (this.input[this.offset] == XML_CLOSE)
return false;
var saveOffset = this.offset;
var typeAndValue = this.decodeTypeAndVal();
// readElementStartDTag will use this to fast forward.
this.previouslyPeekedDTagEndOffset = this.offset;
// Restore the position.
this.offset = saveOffset;
if (typeAndValue != null && typeAndValue.type() == XML_DTAG) {
this.previouslyPeekedDTagStartOffset = saveOffset;
this.previouslyPeekedDTag = typeAndValue.val();
return typeAndValue.val() == expectedTag;
}
else
return false;
}
};
/**
* @deprecated Use peekDTag. Binary XML string tags and attributes are not used by any NDN encodings and
* support is not maintained in the code base.
*/
BinaryXMLDecoder.prototype.peekStartElement = function(
//String
startTag)
{
//String
if (typeof startTag == 'string') {
var decodedTag = this.peekStartElementAsString();
if (null != decodedTag && decodedTag == startTag)
return true;
return false;
}
else if (typeof startTag == 'number') {
var decodedTag = this.peekStartElementAsLong();
if (null != decodedTag && decodedTag == startTag)
return true;
return false;
}
else
throw new DecodingException(new Error("SHOULD BE STRING OR NUMBER"));
};
/**
* @deprecated Use peekDTag. Binary XML string tags and attributes are not used by any NDN encodings and
* support is not maintained in the code base.
*/
BinaryXMLDecoder.prototype.peekStartElementAsLong = function()
{
//Long
var decodedTag = null;
var previousOffset = this.offset;
try {
// Have to distinguish genuine errors from wrong tags. Could either use
// a special exception subtype, or redo the work here.
//this.TypeAndVal
var tv = this.decodeTypeAndVal();
if (null != tv) {
if (tv.type() == XML_TAG) {
if (tv.val() + 1 > DEBUG_MAX_LEN)
throw new DecodingException(new Error("Decoding error: length " + tv.val()+1 + " longer than expected maximum length!"));
var valval;
if (typeof tv.val() == 'string')
valval = (parseInt(tv.val())) + 1;
else
valval = (tv.val())+ 1;
// Tag value represents length-1 as tags can never be empty.
//String
var strTag = this.decodeUString(valval);
decodedTag = stringToTag(strTag);
}
else if (tv.type() == XML_DTAG)
decodedTag = tv.val();
} // else, not a type and val, probably an end element. rewind and return false.
}
catch (e) {
}
finally {
try {
//this.input.reset();
this.offset = previousOffset;
} catch (e) {
Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
throw new Error("Cannot reset stream! " + e.getMessage(), e);
}
}
return decodedTag;
};
/**
* Decode the header from the input starting its offset, expecting the type to be DTAG and the value to be expectedTag.
* Then read one item of any type (presumably BLOB, UDATA, TAG or ATTR) and return a
* customBuf. However, if allowNull is true, then the item may be absent.
* Finally, read the element close. Update the input's offset.
* @param {number} expectedTag The expected value for DTAG.
* @param {boolean} allowNull True if the binary item may be missing.
* @returns {Buffer} A customBuf which is a slice on the data inside the input buffer. However,
* if allowNull is true and the binary data item is absent, then return null.
*/
BinaryXMLDecoder.prototype.readBinaryDTagElement = function(expectedTag, allowNull)
{
this.readElementStartDTag(expectedTag);
return this.readBlob(allowNull);
};
/**
* @deprecated Use readBinaryDTagElement. Binary XML string tags and attributes are not used by any NDN encodings and
* support is not maintained in the code base.
*/
BinaryXMLDecoder.prototype.readBinaryElement = function(
//long
startTag,
//TreeMap<String, String>
attributes,
//boolean
allowNull)
{
this.readStartElement(startTag, attributes);
return this.readBlob(allowNull);
};
/**
* Read one byte from the input starting at its offset, expecting it to be the element close.
* Update the input's offset.
*/
BinaryXMLDecoder.prototype.readElementClose = function()
{
var next = this.input[this.offset++];
if (next != XML_CLOSE)
throw new DecodingException(new Error("Expected end element, got: " + next));
};
/**
* @deprecated Use readElementClose.
*/
BinaryXMLDecoder.prototype.readEndElement = function()
{
if (LOG > 4) console.log('this.offset is '+this.offset);
var next = this.input[this.offset];
this.offset++;
if (LOG > 4) console.log('XML_CLOSE IS '+XML_CLOSE);
if (LOG > 4) console.log('next is '+next);
if (next != XML_CLOSE) {
console.log("Expected end element, got: " + next);
throw new DecodingException(new Error("Expected end element, got: " + next));
}
};
//String
BinaryXMLDecoder.prototype.readUString = function()
{
//String
var ustring = this.decodeUString();
this.readElementClose();
return ustring;
};
/**
* Read a blob as well as the end element. Returns a customBuf (or null for missing blob).
* If the blob is missing and allowNull is false (default), throw an exception. Otherwise,
* just read the end element and return null.
*/
BinaryXMLDecoder.prototype.readBlob = function(allowNull)
{
if (this.input[this.offset] == XML_CLOSE && allowNull) {
this.readElementClose();
return null;
}
var blob = this.decodeBlob();
this.readElementClose();
return blob;
};
/**
* Decode the header from the input starting at its offset, expecting the type to be
* DTAG and the value to be expectedTag. Then read one item, parse it as an unsigned
* big endian integer in 4096 ticks per second, and convert it to and NDNTime object.
* Finally, read the element close. Update the input's offset.
* @param {number} expectedTag The expected value for DTAG.
* @returns {NDNTime} The dateTime value.
*/
BinaryXMLDecoder.prototype.readDateTimeDTagElement = function(expectedTag)
{
var byteTimestamp = this.readBinaryDTagElement(expectedTag);
byteTimestamp = DataUtils.toHex(byteTimestamp);
byteTimestamp = parseInt(byteTimestamp, 16);
var lontimestamp = (byteTimestamp/ 4096) * 1000;
var timestamp = new NDNTime(lontimestamp);
if (null == timestamp)
throw new DecodingException(new Error("Cannot parse timestamp: " + DataUtils.printHexBytes(byteTimestamp)));
return timestamp;
};
/**
* @deprecated Use readDateTimeDTagElement. Binary XML string tags and attributes are not used by any NDN encodings and
* support is not maintained in the code base.
*/
BinaryXMLDecoder.prototype.readDateTime = function(
//long
startTag)
{
var byteTimestamp = this.readBinaryElement(startTag);
byteTimestamp = DataUtils.toHex(byteTimestamp);
byteTimestamp = parseInt(byteTimestamp, 16);
var lontimestamp = (byteTimestamp/ 4096) * 1000;
if (LOG > 4) console.log('DECODED DATE WITH VALUE');
if (LOG > 4) console.log(lontimestamp);
//NDNTime
var timestamp = new NDNTime(lontimestamp);
if (null == timestamp)
throw new DecodingException(new Error("Cannot parse timestamp: " + DataUtils.printHexBytes(byteTimestamp)));
return timestamp;
};
BinaryXMLDecoder.prototype.decodeTypeAndVal = function()
{
/*int*/ var type = -1;
/*long*/ var val = 0;
/*boolean*/ var more = true;
do {
var next = this.input[this.offset ];
if (next == null)
// Quit the loop.
return null;
if (next < 0)
return null;
if (0 == next && 0 == val)
return null;
more = (0 == (next & XML_TT_NO_MORE));
if (more) {
val = val << XML_REG_VAL_BITS;
val |= (next & XML_REG_VAL_MASK);
}
else {
type = next & XML_TT_MASK;
val = val << XML_TT_VAL_BITS;
val |= ((next >>> XML_TT_BITS) & XML_TT_VAL_MASK);
}
this.offset++;
} while (more);
if (LOG > 4) console.log('TYPE is '+ type + ' VAL is '+ val);
return new TypeAndVal(type, val);
};
//TypeAndVal
BinaryXMLDecoder.prototype.peekTypeAndVal = function()
{
//TypeAndVal
var tv = null;
var previousOffset = this.offset;
try {
tv = this.decodeTypeAndVal();
}
finally {
this.offset = previousOffset;
}
return tv;
};
//Buffer
BinaryXMLDecoder.prototype.decodeBlob = function(
//int
blobLength)
{
if (null == blobLength) {
//TypeAndVal
var tv = this.decodeTypeAndVal();
var valval ;
if (typeof tv.val() == 'string')
valval = (parseInt(tv.val()));
else
valval = (tv.val());
return this.decodeBlob(valval);
}
//Buffer
var bytes = new customBuf(this.input.slice(this.offset, this.offset+ blobLength));
this.offset += blobLength;
return bytes;
};
//String
BinaryXMLDecoder.prototype.decodeUString = function(
//int
byteLength)
{
if (null == byteLength) {
var tempStreamPosition = this.offset;
//TypeAndVal
var tv = this.decodeTypeAndVal();
if (LOG > 4) console.log('TV is '+tv);
if (LOG > 4) console.log(tv);
if (LOG > 4) console.log('Type of TV is '+typeof tv);
// if we just have closers left, will get back null
if (null == tv || XML_UDATA != tv.type()) {
this.offset = tempStreamPosition;
return "";
}
return this.decodeUString(tv.val());
}
else {
//Buffer
var stringBytes = this.decodeBlob(byteLength);
// TODO: Should this parse as UTF8?
return DataUtils.toString(stringBytes);
}
};
//OBject containg a pair of type and value
var TypeAndVal = function TypeAndVal(_type,_val)
{
this.t = _type;
this.v = _val;
};
TypeAndVal.prototype.type = function()
{
return this.t;
};
TypeAndVal.prototype.val = function()
{
return this.v;
};
/**
* Decode the header from the input starting its offset, expecting the type to be DTAG and the value to be expectedTag.
* Then read one UDATA item, parse it as a decimal integer and return the integer. Finally, read the element close. Update the input's offset.
* @param {number} expectedTag The expected value for DTAG.
* @returns {number} The parsed integer.
*/
BinaryXMLDecoder.prototype.readIntegerDTagElement = function(expectedTag)
{
return parseInt(this.readUTF8DTagElement(expectedTag));
};
/**
* @deprecated Use readIntegerDTagElement. Binary XML string tags and attributes are not used by any NDN encodings and
* support is not maintained in the code base.
*/
BinaryXMLDecoder.prototype.readIntegerElement = function(
//String
startTag)
{
//String
if (LOG > 4) console.log('READING INTEGER '+ startTag);
if (LOG > 4) console.log('TYPE OF '+ typeof startTag);
var strVal = this.readUTF8Element(startTag);
return parseInt(strVal);
};
/**
* Decode the header from the input starting its offset, expecting the type to be DTAG and the value to be expectedTag.
* Then read one UDATA item and return a string. Finally, read the element close. Update the input's offset.
* @param {number} expectedTag The expected value for DTAG.
* @returns {string} The UDATA string.
*/
BinaryXMLDecoder.prototype.readUTF8DTagElement = function(expectedTag)
{
this.readElementStartDTag(expectedTag);
return this.readUString();;
};
/**
* @deprecated Use readUTF8DTagElement. Binary XML string tags and attributes are not used by any NDN encodings and
* support is not maintained in the code base.
*/
BinaryXMLDecoder.prototype.readUTF8Element = function(
//String
startTag,
//TreeMap<String, String>
attributes)
{
//throws Error where name == "DecodingException"
// can't use getElementText, can't get attributes
this.readStartElement(startTag, attributes);
//String
var strElementText = this.readUString();
return strElementText;
};
/**
* Set the offset into the input, used for the next read.
* @param {number} offset The new offset.
*/
BinaryXMLDecoder.prototype.seek = function(offset)
{
this.offset = offset;
};
},{"../buffer.js":25,"../log.js":51,"../util/ndn-protoco-id-tags.js":62,"../util/ndn-time.js":63,"./data-utils.js":32,"./decoding-exception.js":33}],29:[function(require,module,exports){
/**
* This class is used to encode ndnb binary elements (blob, type/value pairs).
*
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Meki Cheraoui
* See COPYING for copyright and distribution information.
*/
var LOG = require('../log.js').Log.LOG;
var customBuf = require('../buffer.js').Buffer
var NDNProtocolDTags = require('../util/ndn-protoco-id-tags.js').NDNProtocolDTags;
var DynamicBuffer = require('../util/dynamic-buffer.js').DynamicBuffer;
var DataUtils = require('./data-utils.js').DataUtils;
var LOG = require('../log.js').Log.LOG;
var XML_EXT = 0x00;
var XML_TAG = 0x01;
var XML_DTAG = 0x02;
var XML_ATTR = 0x03;
var XML_DATTR = 0x04;
var XML_BLOB = 0x05;
var XML_UDATA = 0x06;
var XML_CLOSE = 0x0;
var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16;
var XML_TT_BITS = 3;
var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
var XML_TT_VAL_BITS = XML_TT_BITS + 1;
var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
var XML_REG_VAL_BITS = 7;
var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
var BYTE_MASK = 0xFF;
var LONG_BYTES = 8;
var LONG_BITS = 64;
var bits_11 = 0x0000007FF;
var bits_18 = 0x00003FFFF;
var bits_32 = 0x0FFFFFFFF;
/**
* @constructor
*/
var BinaryXMLEncoder = function BinaryXMLEncoder(initiaLength)
{
if (!initiaLength)
initiaLength = 16;
this.ostream = new DynamicBuffer(initiaLength);
this.offset = 0;
this.CODEC_NAME = "Binary";
};
exports.BinaryXMLEncoder = BinaryXMLEncoder;
/**
* Encode utf8Content as utf8 and write to the output buffer as a UDATA.
* @param {string} utf8Content The string to convert to utf8.
*/
BinaryXMLEncoder.prototype.writeUString = function(utf8Content)
{
this.encodeUString(utf8Content, XML_UDATA);
};
BinaryXMLEncoder.prototype.writeBlob = function(
/*Buffer*/ binaryContent)
{
if (LOG >3) console.log(binaryContent);
this.encodeBlob(binaryContent, binaryContent.length);
};
/**
* Write an element start header using DTAG with the tag to the output buffer.
* @param {number} tag The DTAG tag.
*/
BinaryXMLEncoder.prototype.writeElementStartDTag = function(tag)
{
this.encodeTypeAndVal(XML_DTAG, tag);
};
/**
* @deprecated Use writeElementStartDTag. Binary XML string tags and attributes are not used by any NDN encodings and
* support is not maintained in the code base.
*/
BinaryXMLEncoder.prototype.writeStartElement = function(
/*String*/ tag,
/*TreeMap<String,String>*/ attributes)
{
/*Long*/ var dictionaryVal = tag; //stringToTag(tag);
if (null == dictionaryVal)
this.encodeUString(tag, XML_TAG);
else
this.encodeTypeAndVal(XML_DTAG, dictionaryVal);
if (null != attributes)
this.writeAttributes(attributes);
};
/**
* Write an element close to the output buffer.
*/
BinaryXMLEncoder.prototype.writeElementClose = function()
{
this.ostream.ensureLength(this.offset + 1);
this.ostream.array[this.offset] = XML_CLOSE;
this.offset += 1;
};
/**
* @deprecated Use writeElementClose.
*/
BinaryXMLEncoder.prototype.writeEndElement = function()
{
this.writeElementClose();
};
/**
* @deprecated Binary XML string tags and attributes are not used by any NDN encodings and support is not maintained in the code base.
*/
BinaryXMLEncoder.prototype.writeAttributes = function(/*TreeMap<String,String>*/ attributes)
{
if (null == attributes)
return;
// the keySet of a TreeMap is sorted.
for (var i = 0; i< attributes.length;i++) {
var strAttr = attributes[i].k;
var strValue = attributes[i].v;
var dictionaryAttr = stringToTag(strAttr);
if (null == dictionaryAttr)
// not in dictionary, encode as attr
// compressed format wants length of tag represented as length-1
// to save that extra bit, as tag cannot be 0 length.
// encodeUString knows to do that.
this.encodeUString(strAttr, XML_ATTR);
else
this.encodeTypeAndVal(XML_DATTR, dictionaryAttr);
// Write value
this.encodeUString(strValue);
}
};
//returns a string
stringToTag = function(/*long*/ tagVal)
{
if (tagVal >= 0 && tagVal < NDNProtocolDTagsStrings.length)
return NDNProtocolDTagsStrings[tagVal];
else if (tagVal == NDNProtocolDTags.NDNProtocolDataUnit)
return NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT;
return null;
};
//returns a Long
tagToString = function(/*String*/ tagName)
{
// the slow way, but right now we don't care.... want a static lookup for the forward direction
for (var i = 0; i < NDNProtocolDTagsStrings.length; ++i) {
if (null != NDNProtocolDTagsStrings[i] && NDNProtocolDTagsStrings[i] == tagName)
return i;
}
if (NDNProtocolDTags.NDNPROTOCOL_DATA_UNIT == tagName)
return NDNProtocolDTags.NDNProtocolDataUnit;
return null;
};
/**
* Write an element start header using DTAG with the tag to the output buffer, then the content as explained below,
* then an element close.
* @param {number} tag The DTAG tag.
* @param {number|string|Buffer} content If contentis a number, convert it to a string and call writeUString. If content is a string,
* call writeUString. Otherwise, call writeBlob.
*/
BinaryXMLEncoder.prototype.writeDTagElement = function(tag, content)
{
this.writeElementStartDTag(tag);
if (typeof content === 'number')
this.writeUString(content.toString());
else if (typeof content === 'string')
this.writeUString(content);
else
this.writeBlob(content);
this.writeElementClose();
};
/**
* @deprecated Use writeDTagElement. Binary XML string tags and attributes are not used by any NDN encodings and
* support is not maintained in the code base.
* If Content is a string, then encode as utf8 and write UDATA.
*/
BinaryXMLEncoder.prototype.writeElement = function(
//long
tag,
//byte[]
Content,
//TreeMap<String, String>
attributes)
{
this.writeStartElement(tag, attributes);
// Will omit if 0-length
if (typeof Content === 'number') {
if (LOG > 4) console.log('GOING TO WRITE THE NUMBER .charCodeAt(0) ' + Content.toString().charCodeAt(0));
if (LOG > 4) console.log('GOING TO WRITE THE NUMBER ' + Content.toString());
if (LOG > 4) console.log('type of number is ' + typeof Content.toString());
this.writeUString(Content.toString());
}
else if (typeof Content === 'string') {
if (LOG > 4) console.log('GOING TO WRITE THE STRING ' + Content);
if (LOG > 4) console.log('type of STRING is ' + typeof Content);
this.writeUString(Content);
}
else {
if (LOG > 4) console.log('GOING TO WRITE A BLOB ' + Content);
this.writeBlob(Content);
}
this.writeElementClose();
};
var TypeAndVal = function TypeAndVal(_type,_val)
{
this.type = _type;
this.val = _val;
};
BinaryXMLEncoder.prototype.encodeTypeAndVal = function(
//int
type,
//long
val)
{
if (LOG > 4) console.log('Encoding type '+ type+ ' and value '+ val);
if (LOG > 4) console.log('OFFSET IS ' + this.offset);
if (type > XML_UDATA || type < 0 || val < 0)
throw new Error("Tag and value must be positive, and tag valid.");
// Encode backwards. Calculate how many bytes we need:
var numEncodingBytes = this.numEncodingBytes(val);
this.ostream.ensureLength(this.offset + numEncodingBytes);
// Bottom 4 bits of val go in last byte with tag.
this.ostream.array[this.offset + numEncodingBytes - 1] =
//(byte)
(BYTE_MASK &
(((XML_TT_MASK & type) |
((XML_TT_VAL_MASK & val) << XML_TT_BITS))) |
XML_TT_NO_MORE); // set top bit for last byte
val = val >>> XML_TT_VAL_BITS;
// Rest of val goes into preceding bytes, 7 bits per byte, top bit
// is "more" flag.
var i = this.offset + numEncodingBytes - 2;
while (0 != val && i >= this.offset) {
this.ostream.array[i] = //(byte)
(BYTE_MASK & (val & XML_REG_VAL_MASK)); // leave top bit unset
val = val >>> XML_REG_VAL_BITS;
--i;
}
if (val != 0)
throw new Error("This should not happen: miscalculated encoding");
this.offset+= numEncodingBytes;
return numEncodingBytes;
};
/**
* Encode ustring as utf8.
*/
BinaryXMLEncoder.prototype.encodeUString = function(
//String
ustring,
//byte
type)
{
if (null == ustring)
return;
if (type == XML_TAG || type == XML_ATTR && ustring.length == 0)
return;
if (LOG > 3) console.log("The string to write is ");
if (LOG > 3) console.log(ustring);
var strBytes = DataUtils.stringToUtf8Array(ustring);
this.encodeTypeAndVal(type,
(((type == XML_TAG) || (type == XML_ATTR)) ?
(strBytes.length-1) :
strBytes.length));
if (LOG > 3) console.log("THE string to write is ");
if (LOG > 3) console.log(strBytes);
this.writeString(strBytes);
this.offset+= strBytes.length;
};
BinaryXMLEncoder.prototype.encodeBlob = function(
//Buffer
blob,
//int
length)
{
if (null == blob)
return;
if (LOG > 4) console.log('LENGTH OF XML_BLOB IS '+length);
this.encodeTypeAndVal(XML_BLOB, length);
this.writeBlobArray(blob);
this.offset += length;
};
var ENCODING_LIMIT_1_BYTE = ((1 << (XML_TT_VAL_BITS)) - 1);
var ENCODING_LIMIT_2_BYTES = ((1 << (XML_TT_VAL_BITS + XML_REG_VAL_BITS)) - 1);
var ENCODING_LIMIT_3_BYTES = ((1 << (XML_TT_VAL_BITS + 2 * XML_REG_VAL_BITS)) - 1);
BinaryXMLEncoder.prototype.numEncodingBytes = function(
//long
x)
{
if (x <= ENCODING_LIMIT_1_BYTE) return (1);
if (x <= ENCODING_LIMIT_2_BYTES) return (2);
if (x <= ENCODING_LIMIT_3_BYTES) return (3);
var numbytes = 1;
// Last byte gives you XML_TT_VAL_BITS
// Remainder each give you XML_REG_VAL_BITS
x = x >>> XML_TT_VAL_BITS;
while (x != 0) {
numbytes++;
x = x >>> XML_REG_VAL_BITS;
}
return (numbytes);
};
/**
* Write an element start header using DTAG with the tag to the output buffer, then the dateTime
* as a big endian BLOB converted to 4096 ticks per second, then an element close.
* @param {number} tag The DTAG tag.
* @param {NDNTime} dateTime
*/
BinaryXMLEncoder.prototype.writeDateTimeDTagElement = function(tag, dateTime)
{
//parse to hex
var binarydate = Math.round((dateTime.msec/1000) * 4096).toString(16) ;
if (binarydate.length % 2 == 1)
binarydate = '0' + binarydate;
this.writeDTagElement(tag, DataUtils.toNumbers(binarydate));
};
/**
* @deprecated Use writeDateTimeDTagElement. Binary XML string tags and attributes are not used by any NDN encodings and
* support is not maintained in the code base.
*/
BinaryXMLEncoder.prototype.writeDateTime = function(
//String
tag,
//NDNTime
dateTime)
{
//parse to hex
var binarydate = Math.round((dateTime.msec/1000) * 4096).toString(16) ;
if (binarydate.length % 2 == 1)
binarydate = '0' + binarydate;
this.writeElement(tag, DataUtils.toNumbers(binarydate));
};
// This does not update this.offset.
BinaryXMLEncoder.prototype.writeString = function(input)
{
if (typeof input === 'string') {
if (LOG > 4) console.log('GOING TO WRITE A STRING');
if (LOG > 4) console.log(input);
this.ostream.ensureLength(this.offset + input.length);
for (var i = 0; i < input.length; i++) {
if (LOG > 4) console.log('input.charCodeAt(i)=' + input.charCodeAt(i));
this.ostream.array[this.offset + i] = (input.charCodeAt(i));
}
}
else
{
if (LOG > 4) console.log('GOING TO WRITE A STRING IN BINARY FORM');
if (LOG > 4) console.log(input);
this.writeBlobArray(input);
}
};
BinaryXMLEncoder.prototype.writeBlobArray = function(
//Buffer
blob)
{
if (LOG > 4) console.log('GOING TO WRITE A BLOB');
this.ostream.copy(blob, this.offset);
};
BinaryXMLEncoder.prototype.getReducedOstream = function()
{
return this.ostream.slice(0, this.offset);
};
},{"../buffer.js":25,"../log.js":51,"../util/dynamic-buffer.js":60,"../util/ndn-protoco-id-tags.js":62,"./data-utils.js":32}],30:[function(require,module,exports){
/**
* This class uses BinaryXMLDecoder to follow the structure of a ndnb binary element to
* determine its end.
*
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
var BinaryXMLDecoder = require('./binary-xml-decoder.js').BinaryXMLDecoder;
var DynamicBuffer = require('../util/dynamic-buffer.js').DynamicBuffer;
var XML_EXT = 0x00;
var XML_TAG = 0x01;
var XML_DTAG = 0x02;
var XML_ATTR = 0x03;
var XML_DATTR = 0x04;
var XML_BLOB = 0x05;
var XML_UDATA = 0x06;
var XML_CLOSE = 0x0;
var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16;
var XML_TT_BITS = 3;
var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
var XML_TT_VAL_BITS = XML_TT_BITS + 1;
var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
var XML_REG_VAL_BITS = 7;
var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
/**
* @constructor
*/
var BinaryXMLStructureDecoder = function BinaryXMLDecoder()
{
this.gotElementEnd = false;
this.offset = 0;
this.level = 0;
this.state = BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE;
this.headerLength = 0;
this.useHeaderBuffer = false;
this.headerBuffer = new DynamicBuffer(5);
this.nBytesToRead = 0;
};
exports.BinaryXMLStructureDecoder = BinaryXMLStructureDecoder;
BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE = 0;
BinaryXMLStructureDecoder.READ_BYTES = 1;
/**
* Continue scanning input starting from this.offset. If found the end of the element
* which started at offset 0 then return true, else false.
* If this returns false, you should read more into input and call again.
* You have to pass in input each time because the array could be reallocated.
* This throws an exception for badly formed ndnb.
*/
BinaryXMLStructureDecoder.prototype.findElementEnd = function(
// customBuf
input)
{
if (this.gotElementEnd)
// Someone is calling when we already got the end.
return true;
var decoder = new BinaryXMLDecoder(input);
while (true) {
if (this.offset >= input.length)
// All the cases assume we have some input.
return false;
switch (this.state) {
case BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE:
// First check for XML_CLOSE.
if (this.headerLength == 0 && input[this.offset] == XML_CLOSE) {
++this.offset;
// Close the level.
--this.level;
if (this.level == 0) {
// Finished.
this.gotElementEnd = true;
return true;
}
if (this.level < 0)
throw new Error("BinaryXMLStructureDecoder: Unexpected close tag at offset " + (this.offset - 1));
// Get ready for the next header.
this.startHeader();
break;
}
var startingHeaderLength = this.headerLength;
while (true) {
if (this.offset >= input.length) {
// We can't get all of the header bytes from this input. Save in headerBuffer.
this.useHeaderBuffer = true;
var nNewBytes = this.headerLength - startingHeaderLength;
this.headerBuffer.copy(input.slice(this.offset - nNewBytes, nNewBytes), startingHeaderLength);
return false;
}
var headerByte = input[this.offset++];
++this.headerLength;
if (headerByte & XML_TT_NO_MORE)
// Break and read the header.
break;
}
var typeAndVal;
if (this.useHeaderBuffer) {
// Copy the remaining bytes into headerBuffer.
nNewBytes = this.headerLength - startingHeaderLength;
this.headerBuffer.copy(input.slice(this.offset - nNewBytes, nNewBytes), startingHeaderLength);
typeAndVal = new BinaryXMLDecoder(this.headerBuffer.array).decodeTypeAndVal();
}
else {
// We didn't have to use the headerBuffer.
decoder.seek(this.offset - this.headerLength);
typeAndVal = decoder.decodeTypeAndVal();
}
if (typeAndVal == null)
throw new Error("BinaryXMLStructureDecoder: Can't read header starting at offset " +
(this.offset - this.headerLength));
// Set the next state based on the type.
var type = typeAndVal.t;
if (type == XML_DATTR)
// We already consumed the item. READ_HEADER_OR_CLOSE again.
// ndnb has rules about what must follow an attribute, but we are just scanning.
this.startHeader();
else if (type == XML_DTAG || type == XML_EXT) {
// Start a new level and READ_HEADER_OR_CLOSE again.
++this.level;
this.startHeader();
}
else if (type == XML_TAG || type == XML_ATTR) {
if (type == XML_TAG)
// Start a new level and read the tag.
++this.level;
// Minimum tag or attribute length is 1.
this.nBytesToRead = typeAndVal.v + 1;
this.state = BinaryXMLStructureDecoder.READ_BYTES;
// ndnb has rules about what must follow an attribute, but we are just scanning.
}
else if (type == XML_BLOB || type == XML_UDATA) {
this.nBytesToRead = typeAndVal.v;
this.state = BinaryXMLStructureDecoder.READ_BYTES;
}
else
throw new Error("BinaryXMLStructureDecoder: Unrecognized header type " + type);
break;
case BinaryXMLStructureDecoder.READ_BYTES:
var nRemainingBytes = input.length - this.offset;
if (nRemainingBytes < this.nBytesToRead) {
// Need more.
this.offset += nRemainingBytes;
this.nBytesToRead -= nRemainingBytes;
return false;
}
// Got the bytes. Read a new header or close.
this.offset += this.nBytesToRead;
this.startHeader();
break;
default:
// We don't expect this to happen.
throw new Error("BinaryXMLStructureDecoder: Unrecognized state " + this.state);
}
}
};
/**
* Set the state to READ_HEADER_OR_CLOSE and set up to start reading the header
*/
BinaryXMLStructureDecoder.prototype.startHeader = function()
{
this.headerLength = 0;
this.useHeaderBuffer = false;
this.state = BinaryXMLStructureDecoder.READ_HEADER_OR_CLOSE;
};
/**
* Set the offset into the input, used for the next read.
*/
BinaryXMLStructureDecoder.prototype.seek = function(offset)
{
this.offset = offset;
};
},{"../util/dynamic-buffer.js":60,"./binary-xml-decoder.js":28}],31:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
var Blob = require('../util/blob.js').Blob;
var NDNProtocolDTags = require('../util/ndn-protoco-id-tags.js').NDNProtocolDTags;
var BinaryXMLEncoder = require('./binary-xml-encoder.js').BinaryXMLEncoder;
var BinaryXMLDecoder = require('./binary-xml-decoder.js').BinaryXMLDecoder;
var WireFormat = require('./wire-format.js').WireFormat;
var Name = require('../name.js').Name;
var Exclude = require('../exclude.js').Exclude;
var Signature = require('../signature.js').Signature;
var MetaInfo = require('../meta-info.js').MetaInfo;
var PublisherPublicKeyDigest = require('../publisher-public-key-digest.js').PublisherPublicKeyDigest;
var DataUtils = require('./data-utils.js').DataUtils;
var KeyLocatorType = require('../key-locator.js').KeyLocatorType;
/**
* A BinaryXmlWireFormat implements the WireFormat interface for encoding and decoding in binary XML.
* @constructor
*/
var BinaryXmlWireFormat = function BinaryXmlWireFormat()
{
// Inherit from WireFormat.
WireFormat.call(this);
};
exports.BinaryXmlWireFormat = BinaryXmlWireFormat;
// Default object.
BinaryXmlWireFormat.instance = null;
/**
* Encode interest as Binary XML and return the encoding.
* @param {Interest} interest The Interest to encode.
* @returns {Blob} A Blob containing the encoding.
*/
BinaryXmlWireFormat.prototype.encodeInterest = function(interest)
{
var encoder = new BinaryXMLEncoder();
BinaryXmlWireFormat.encodeInterest(interest, encoder);
return new Blob(encoder.getReducedOstream(), false);
};
/**
* Decode input as a Binary XML interest and set the fields of the interest object.
* @param {Interest} interest The Interest object whose fields are updated.
* @param {Buffer} input The buffer with the bytes to decode.
*/
BinaryXmlWireFormat.prototype.decodeInterest = function(interest, input)
{
var decoder = new BinaryXMLDecoder(input);
BinaryXmlWireFormat.decodeInterest(interest, decoder);
};
/**
* Encode data as Binary XML and return the encoding and signed offsets.
* @param {Data} data The Data object to encode.
* @returns {object with (Blob, int, int)} An associative array with fields
* (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
* is a Blob containing the encoding, signedPortionBeginOffset is the offset in
* the encoding of the beginning of the signed portion, and
* signedPortionEndOffset is the offset in the encoding of the end of the
* signed portion.
*/
BinaryXmlWireFormat.prototype.encodeData = function(data)
{
var encoder = new BinaryXMLEncoder(1500);
var result = BinaryXmlWireFormat.encodeData(data, encoder);
result.encoding = new Blob(encoder.getReducedOstream(), false);
return result;
};
/**
* @deprecated Use encodeData(data).
*/
BinaryXmlWireFormat.prototype.encodeContentObject = function(data)
{
return this.encodeData(data);
};
/**
* Decode input as a Binary XML data packet, set the fields in the data object, and return
* the signed offsets.
* @param {Data} data The Data object whose fields are updated.
* @param {Buffer} input The buffer with the bytes to decode.
* @returns {object with (int, int)} An associative array with fields
* (signedPortionBeginOffset, signedPortionEndOffset) where
* signedPortionBeginOffset is the offset in the encoding of the beginning of
* the signed portion, and signedPortionEndOffset is the offset in the encoding
* of the end of the signed portion.
*/
BinaryXmlWireFormat.prototype.decodeData = function(data, input)
{
var decoder = new BinaryXMLDecoder(input);
return BinaryXmlWireFormat.decodeData(data, decoder);
};
/**
* @deprecated Use decodeData(data, input).
*/
BinaryXmlWireFormat.prototype.decodeContentObject = function(data, input)
{
this.decodeData(data, input);
};
/**
* Get a singleton instance of a BinaryXmlWireFormat. Assuming that the default
* wire format was set with
* WireFormat.setDefaultWireFormat(BinaryXmlWireFormat.get()), you can check if
* this is the default wire encoding with
* if WireFormat.getDefaultWireFormat() == BinaryXmlWireFormat.get().
* @returns {BinaryXmlWireFormat} The singleton instance.
*/
BinaryXmlWireFormat.get = function()
{
if (BinaryXmlWireFormat.instance === null)
BinaryXmlWireFormat.instance = new BinaryXmlWireFormat();
return BinaryXmlWireFormat.instance;
};
/**
* Encode the interest by calling the operations on the encoder.
* @param {Interest} interest
* @param {BinaryXMLEncoder} encoder
*/
BinaryXmlWireFormat.encodeInterest = function(interest, encoder)
{
encoder.writeElementStartDTag(NDNProtocolDTags.Interest);
interest.name.to_ndnb(encoder);
if (null != interest.minSuffixComponents)
encoder.writeDTagElement(NDNProtocolDTags.MinSuffixComponents, interest.minSuffixComponents);
if (null != interest.maxSuffixComponents)
encoder.writeDTagElement(NDNProtocolDTags.MaxSuffixComponents, interest.maxSuffixComponents);
if (interest.getKeyLocator().getType() == KeyLocatorType.KEY_LOCATOR_DIGEST &&
interest.getKeyLocator().getKeyData() != null &&
interest.getKeyLocator().getKeyData().length > 0)
// There is a KEY_LOCATOR_DIGEST. Use this instead of the publisherPublicKeyDigest.
encoder.writeDTagElement
(NDNProtocolDTags.PublisherPublicKeyDigest,
interest.getKeyLocator().getKeyData());
else {
if (null != interest.publisherPublicKeyDigest)
interest.publisherPublicKeyDigest.to_ndnb(encoder);
}
if (null != interest.exclude)
interest.exclude.to_ndnb(encoder);
if (null != interest.childSelector)
encoder.writeDTagElement(NDNProtocolDTags.ChildSelector, interest.childSelector);
if (interest.DEFAULT_ANSWER_ORIGIN_KIND != interest.answerOriginKind && interest.answerOriginKind!=null)
encoder.writeDTagElement(NDNProtocolDTags.AnswerOriginKind, interest.answerOriginKind);
if (null != interest.scope)
encoder.writeDTagElement(NDNProtocolDTags.Scope, interest.scope);
if (null != interest.interestLifetime)
encoder.writeDTagElement(NDNProtocolDTags.InterestLifetime,
DataUtils.nonNegativeIntToBigEndian((interest.interestLifetime / 1000.0) * 4096));
if (null != interest.nonce)
encoder.writeDTagElement(NDNProtocolDTags.Nonce, interest.nonce);
encoder.writeElementClose();
};
/**
* Use the decoder to place the result in interest.
* @param {Interest} interest
* @param {BinaryXMLDecoder} decoder
*/
BinaryXmlWireFormat.decodeInterest = function(interest, decoder)
{
decoder.readElementStartDTag(NDNProtocolDTags.Interest);
interest.name = new Name();
interest.name.from_ndnb(decoder);
if (decoder.peekDTag(NDNProtocolDTags.MinSuffixComponents))
interest.minSuffixComponents = decoder.readIntegerDTagElement(NDNProtocolDTags.MinSuffixComponents);
else
interest.minSuffixComponents = null;
if (decoder.peekDTag(NDNProtocolDTags.MaxSuffixComponents))
interest.maxSuffixComponents = decoder.readIntegerDTagElement(NDNProtocolDTags.MaxSuffixComponents);
else
interest.maxSuffixComponents = null;
// Initially clear the keyLocator.
interest.getKeyLocator().clear();
if (decoder.peekDTag(NDNProtocolDTags.PublisherPublicKeyDigest)) {
interest.publisherPublicKeyDigest = new PublisherPublicKeyDigest();
interest.publisherPublicKeyDigest.from_ndnb(decoder);
}
else
interest.publisherPublicKeyDigest = null;
if (interest.publisherPublicKeyDigest != null &&
interest.publisherPublicKeyDigest.publisherPublicKeyDigest != null &&
interest.publisherPublicKeyDigest.publisherPublicKeyDigest.length > 0) {
// We keep the deprecated publisherPublicKeyDigest for backwards
// compatibility. Also set the key locator.
interest.getKeyLocator().setType(KeyLocatorType.KEY_LOCATOR_DIGEST);
interest.getKeyLocator().setKeyData
(interest.publisherPublicKeyDigest.publisherPublicKeyDigest);
}
if (decoder.peekDTag(NDNProtocolDTags.Exclude)) {
interest.exclude = new Exclude();
interest.exclude.from_ndnb(decoder);
}
else
interest.exclude = null;
if (decoder.peekDTag(NDNProtocolDTags.ChildSelector))
interest.childSelector = decoder.readIntegerDTagElement(NDNProtocolDTags.ChildSelector);
else
interest.childSelector = null;
if (decoder.peekDTag(NDNProtocolDTags.AnswerOriginKind))
interest.answerOriginKind = decoder.readIntegerDTagElement(NDNProtocolDTags.AnswerOriginKind);
else
interest.answerOriginKind = null;
if (decoder.peekDTag(NDNProtocolDTags.Scope))
interest.scope = decoder.readIntegerDTagElement(NDNProtocolDTags.Scope);
else
interest.scope = null;
if (decoder.peekDTag(NDNProtocolDTags.InterestLifetime))
interest.interestLifetime = 1000.0 * DataUtils.bigEndianToUnsignedInt
(decoder.readBinaryDTagElement(NDNProtocolDTags.InterestLifetime)) / 4096;
else
interest.interestLifetime = null;
if (decoder.peekDTag(NDNProtocolDTags.Nonce))
interest.nonce = decoder.readBinaryDTagElement(NDNProtocolDTags.Nonce);
else
interest.nonce = null;
decoder.readElementClose();
};
/**
* Encode the data by calling the operations on the encoder.
* @param {Data} data
* @param {BinaryXMLEncoder} encoder
* @returns {object with (int, int)} An associative array with fields
* (signedPortionBeginOffset, signedPortionEndOffset) where
* signedPortionBeginOffset is the offset in the encoding of the beginning of
* the signed portion, and signedPortionEndOffset is the offset in the encoding
* of the end of the signed portion.
*/
BinaryXmlWireFormat.encodeData = function(data, encoder)
{
//TODO verify name, MetaInfo and Signature is present
encoder.writeElementStartDTag(data.getElementLabel());
if (null != data.signature)
data.signature.to_ndnb(encoder);
var signedPortionBeginOffset = encoder.offset;
if (null != data.name)
data.name.to_ndnb(encoder);
if (null != data.signedInfo)
// Use getSignatureOrMetaInfoKeyLocator for the transition of moving
// the key locator from the MetaInfo to the Signauture object.
data.signedInfo.to_ndnb(encoder, data.getSignatureOrMetaInfoKeyLocator());
encoder.writeDTagElement(NDNProtocolDTags.Content, data.content);
var signedPortionEndOffset = encoder.offset;
encoder.writeElementClose();
return { signedPortionBeginOffset: signedPortionBeginOffset,
signedPortionEndOffset: signedPortionEndOffset };
};
/**
* Use the decoder to place the result in data.
* @param {Data} data
* @param {BinaryXMLDecoder} decoder
* @returns {object with (int, int)} An associative array with fields
* (signedPortionBeginOffset, signedPortionEndOffset) where
* signedPortionBeginOffset is the offset in the encoding of the beginning of
* the signed portion, and signedPortionEndOffset is the offset in the encoding
* of the end of the signed portion.
*/
BinaryXmlWireFormat.decodeData = function(data, decoder)
{
// TODO VALIDATE THAT ALL FIELDS EXCEPT SIGNATURE ARE PRESENT
decoder.readElementStartDTag(data.getElementLabel());
if (decoder.peekDTag(NDNProtocolDTags.Signature)) {
data.signature = new Signature();
data.signature.from_ndnb(decoder);
}
else
data.signature = null;
var signedPortionBeginOffset = decoder.offset;
data.name = new Name();
data.name.from_ndnb(decoder);
if (decoder.peekDTag(NDNProtocolDTags.SignedInfo)) {
data.signedInfo = new MetaInfo();
data.signedInfo.from_ndnb(decoder);
if (data.signedInfo.locator != null && data.getSignature() != null)
// Copy the key locator pointer to the Signature object for the transition
// of moving the key locator from the MetaInfo to the Signature object.
data.getSignature().keyLocator = data.signedInfo.locator;
}
else
data.signedInfo = null;
data.content = decoder.readBinaryDTagElement(NDNProtocolDTags.Content, true);
var signedPortionEndOffset = decoder.offset;
decoder.readElementClose();
return { signedPortionBeginOffset: signedPortionBeginOffset,
signedPortionEndOffset: signedPortionEndOffset };
};
},{"../exclude.js":43,"../key-locator.js":49,"../meta-info.js":52,"../name.js":53,"../publisher-public-key-digest.js":55,"../signature.js":57,"../util/blob.js":59,"../util/ndn-protoco-id-tags.js":62,"./binary-xml-decoder.js":28,"./binary-xml-encoder.js":29,"./data-utils.js":32,"./wire-format.js":42}],32:[function(require,module,exports){
/**
* This class contains utilities to help parse the data
*
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Meki Cheraoui
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
var customBuf = require('../buffer.js').Buffer
/**
* A DataUtils has static methods for converting data.
* @constructor
*/
var DataUtils = function()
{
};
exports.DataUtils = new DataUtils();
/*
* NOTE THIS IS CURRENTLY NOT BEING USED
*
*/
DataUtils.prototype.keyStr = "ABCDEFGHIJKLMNOP" +
"QRSTUVWXYZabcdef" +
"ghijklmnopqrstuv" +
"wxyz0123456789+/" +
"=";
/**
* Raw String to Base 64
*/
DataUtils.prototype.stringtoBase64 = function stringtoBase64(input)
{
//input = escape(input);
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
do {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2))
enc3 = enc4 = 64;
else if (isNaN(chr3))
enc4 = 64;
output = output +
DataUtils.keyStr.charAt(enc1) +
DataUtils.keyStr.charAt(enc2) +
DataUtils.keyStr.charAt(enc3) +
DataUtils.keyStr.charAt(enc4);
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
return output;
};
/**
* Base 64 to Raw String
*/
DataUtils.prototype.base64toString = function base64toString(input)
{
var output = "";
var chr1, chr2, chr3 = "";
var enc1, enc2, enc3, enc4 = "";
var i = 0;
// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
var base64test = /[^A-Za-z0-9\+\/\=]/g;
/* Test for invalid characters. */
if (base64test.exec(input)) {
alert("There were invalid base64 characters in the input text.\n" +
"Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
"Expect errors in decoding.");
}
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
do {
enc1 = DataUtils.keyStr.indexOf(input.charAt(i++));
enc2 = DataUtils.keyStr.indexOf(input.charAt(i++));
enc3 = DataUtils.keyStr.indexOf(input.charAt(i++));
enc4 = DataUtils.keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64)
output = output + String.fromCharCode(chr2);
if (enc4 != 64)
output = output + String.fromCharCode(chr3);
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < input.length);
return output;
};
/**
* customBuf to Hex String
*/
DataUtils.prototype.toHex = function(buffer)
{
return buffer.toString('hex');
};
/**
* Raw string to hex string.
*/
DataUtils.prototype.stringToHex = function(args)
{
var ret = "";
for (var i = 0; i < args.length; ++i) {
var value = args.charCodeAt(i);
ret += (value < 16 ? "0" : "") + value.toString(16);
}
return ret;
};
/**
* customBuf to raw string.
*/
DataUtils.prototype.toString = function(buffer)
{
return buffer.toString();
};
/**
* Hex String to customBuf.
*/
DataUtils.prototype.toNumbers = function(str)
{
return new customBuf(str, 'hex');
};
/**
* Hex String to raw string.
*/
DataUtils.prototype.hexToRawString = function(str)
{
if (typeof str =='string') {
var ret = "";
str.replace(/(..)/g, function(s) {
ret += String.fromCharCode(parseInt(s, 16));
});
return ret;
}
};
/**
* Raw String to customBuf.
*/
DataUtils.prototype.toNumbersFromString = function(str)
{
return new customBuf(str, 'binary');
};
/**
* Encode str as utf8 and return as customBuf.
*/
DataUtils.prototype.stringToUtf8Array = function(str)
{
return new customBuf(str, 'utf8');
};
/**
* arrays is an array of customBuf. Return a new customBuf which is the concatenation of all.
*/
DataUtils.prototype.concatArrays = function(arrays)
{
return customBuf.concat(arrays);
};
// TODO: Take customBuf and use TextDecoder when available.
DataUtils.prototype.decodeUtf8 = function(utftext)
{
var string = "";
var i = 0;
var c = 0;
var c1 = 0;
var c2 = 0;
while (i < utftext.length) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if (c > 191 && c < 224) {
c2 = utftext.charCodeAt(i + 1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
var c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
};
/**
* Return true if a1 and a2 are the same length with equal elements.
*/
DataUtils.prototype.arraysEqual = function(a1, a2)
{
// A simple sanity check that it is an array.
if (!a1.slice)
throw new Error("DataUtils.arraysEqual: a1 is not an array");
if (!a2.slice)
throw new Error("DataUtils.arraysEqual: a2 is not an array");
if (a1.length != a2.length)
return false;
for (var i = 0; i < a1.length; ++i) {
if (a1[i] != a2[i])
return false;
}
return true;
};
/**
* Convert the big endian customBuf to an unsigned int.
* Don't check for overflow.
*/
DataUtils.prototype.bigEndianToUnsignedInt = function(bytes)
{
var result = 0;
for (var i = 0; i < bytes.length; ++i) {
result <<= 8;
result += bytes[i];
}
return result;
};
/**
* Convert the int value to a new big endian customBuf and return.
* If value is 0 or negative, return new customBuf(0).
*/
DataUtils.prototype.nonNegativeIntToBigEndian = function(value)
{
value = Math.round(value);
if (value <= 0)
return new customBuf(0);
// Assume value is not over 64 bits.
var size = 8;
var result = new customBuf(size);
var i = 0;
while (value != 0) {
++i;
result[size - i] = value & 0xff;
value >>= 8;
}
return result.slice(size - i, size);
};
/**
* Modify array to randomly shuffle the elements.
*/
DataUtils.prototype.shuffle = function(array)
{
for (var i = array.length - 1; i >= 1; --i) {
// j is from 0 to i.
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
};
},{"../buffer.js":25}],33:[function(require,module,exports){
/**
* Copyright (C) 2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
/**
* Create a new DecodingException wrapping the given error object.
* Call with: throw new DecodingException(new Error("message")).
* @constructor
* @param {string} error The exception created with new Error.
*/
function DecodingException(error)
{
this.message = error.message;
// Copy lineNumber, etc. from where new Error was called.
for (var prop in error)
this[prop] = error[prop];
}
DecodingException.prototype = new Error();
DecodingException.prototype.name = "DecodingException";
exports.DecodingException = DecodingException;
},{}],34:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
var customBuf = require('../buffer.js').Buffer
var DataUtils = require('./data-utils.js').DataUtils;
var BinaryXMLStructureDecoder = require('./binary-xml-structure-decoder.js').BinaryXMLStructureDecoder;
var Tlv = require('./tlv/tlv.js').Tlv;
var TlvStructureDecoder = require('./tlv/tlv-structure-decoder.js').TlvStructureDecoder;
var LOG = require('../log.js').Log.LOG;
/**
* A ElementReader lets you call onReceivedData multiple times which uses a
* BinaryXMLStructureDecoder or TlvStructureDecoder to detect the end of a
* binary XML or TLV element and calls elementListener.onReceivedElement(element)
* with the element. This handles the case where a single call to
* onReceivedData may contain multiple elements.
* @constructor
* @param {{onReceivedElement:function}} elementListener
*/
var ElementReader = function ElementReader(elementListener)
{
this.elementListener = elementListener;
this.dataParts = [];
this.binaryXmlStructureDecoder = new BinaryXMLStructureDecoder();
this.tlvStructureDecoder = new TlvStructureDecoder();
this.useTlv = null;
};
exports.ElementReader = ElementReader;
ElementReader.prototype.onReceivedData = function(/* customBuf */ data)
{
// Process multiple objects in the data.
while (true) {
if (this.dataParts.length == 0) {
// This is the beginning of an element. Check whether it is binaryXML or TLV.
if (data.length <= 0)
// Wait for more data.
return;
// The type codes for TLV Interest and Data packets are chosen to not
// conflict with the first byte of a binary XML packet, so we can
// just look at the first byte.
if (data[0] == Tlv.Interest || data[0] == Tlv.Data || data[0] == 0x80)
this.useTlv = true;
else
// Binary XML.
this.useTlv = false;
}
var gotElementEnd;
var offset;
if (this.useTlv) {
// Scan the input to check if a whole TLV object has been read.
this.tlvStructureDecoder.seek(0);
gotElementEnd = this.tlvStructureDecoder.findElementEnd(data);
offset = this.tlvStructureDecoder.getOffset();
}
else {
// Scan the input to check if a whole Binary XML object has been read.
this.binaryXmlStructureDecoder.seek(0);
gotElementEnd = this.binaryXmlStructureDecoder.findElementEnd(data);
offset = this.binaryXmlStructureDecoder.offset;
}
if (gotElementEnd) {
// Got the remainder of an object. Report to the caller.
this.dataParts.push(data.slice(0, offset));
var element = DataUtils.concatArrays(this.dataParts);
this.dataParts = [];
try {
this.elementListener.onReceivedElement(element);
} catch (ex) {
console.log("ElementReader: ignoring exception from onReceivedElement: " , ex);
}
// Need to read a new object.
data = data.slice(offset, data.length);
this.binaryXmlStructureDecoder = new BinaryXMLStructureDecoder();
this.tlvStructureDecoder = new TlvStructureDecoder();
if (data.length == 0)
// No more data in the packet.
return;
// else loop back to decode.
}
else {
// Save for a later call to concatArrays so that we only copy data once.
this.dataParts.push(data);
if (LOG > 3) console.log('Incomplete packet received. Length ' + data.length + '. Wait for more input.');
return;
}
}
};
},{"../buffer.js":25,"../log.js":51,"./binary-xml-structure-decoder.js":30,"./data-utils.js":32,"./tlv/tlv-structure-decoder.js":40,"./tlv/tlv.js":41}],35:[function(require,module,exports){
/**
* This file contains utilities to help encode and decode NDN objects.
* Copyright (C) 2013-2014 Regents of the University of California.
* author: Meki Cheraoui
* See COPYING for copyright and distribution information.
*/
var DataUtils = require('./data-utils.js').DataUtils;
var BinaryXMLEncoder = require('./binary-xml-encoder.js').BinaryXMLEncoder;
var BinaryXMLDecoder = require('./binary-xml-decoder.js').BinaryXMLDecoder;
var Key = require('../key.js').Key;
var KeyLocatorType = require('../key-locator.js').KeyLocatorType;
var Interest = require('../interest.js').Interest;
var Data = require('../data.js').Data;
var FaceInstance = require('../face-instance.js').FaceInstance;
var ForwardingEntry = require('../forwarding-entry.js').ForwardingEntry;
var WireFormat = require('./wire-format.js').WireFormat;
var LOG = require('../log.js').Log.LOG;
/**
* An EncodingUtils has static methods for encoding data.
* @constructor
*/
var EncodingUtils = function EncodingUtils()
{
};
exports.EncodingUtils = EncodingUtils;
EncodingUtils.encodeToHexInterest = function(interest, wireFormat)
{
wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
return DataUtils.toHex(interest.wireEncode(wireFormat).buf());
};
EncodingUtils.encodeToHexData = function(data, wireFormat)
{
wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
return DataUtils.toHex(data.wireEncode(wireFormat).buf());
};
/**
* @deprecated Use EncodingUtils.encodeToHexData(data).
*/
EncodingUtils.encodeToHexContentObject = function(data, wireFormat)
{
return EncodingUtils.encodeToHexData(data, wireFormat);
}
EncodingUtils.encodeForwardingEntry = function(data)
{
var enc = new BinaryXMLEncoder();
data.to_ndnb(enc);
var bytes = enc.getReducedOstream();
return bytes;
};
EncodingUtils.decodeHexFaceInstance = function(result)
{
var numbers = DataUtils.toNumbers(result);
var decoder = new BinaryXMLDecoder(numbers);
if (LOG > 3) console.log('DECODING HEX FACE INSTANCE \n'+numbers);
var faceInstance = new FaceInstance();
faceInstance.from_ndnb(decoder);
return faceInstance;
};
EncodingUtils.decodeHexInterest = function(input, wireFormat)
{
wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
var interest = new Interest();
interest.wireDecode(DataUtils.toNumbers(input), wireFormat);
return interest;
};
EncodingUtils.decodeHexData = function(input, wireFormat)
{
wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
var data = new Data();
data.wireDecode(DataUtils.toNumbers(input), wireFormat);
return data;
};
/**
* @deprecated Use EncodingUtils.decodeHexData(input).
*/
EncodingUtils.decodeHexContentObject = function(input, wireFormat)
{
return EncodingUtils.decodeHexData(input, wireFormat);
}
EncodingUtils.decodeHexForwardingEntry = function(result)
{
var numbers = DataUtils.toNumbers(result);
var decoder = new BinaryXMLDecoder(numbers);
if (LOG > 3) console.log('DECODED HEX FORWARDING ENTRY \n'+numbers);
var forwardingEntry = new ForwardingEntry();
forwardingEntry.from_ndnb(decoder);
return forwardingEntry;
};
/**
* Decode the customBuf array which holds SubjectPublicKeyInfo and return an RSAKey.
*/
EncodingUtils.decodeSubjectPublicKeyInfo = function(array)
{
var hex = DataUtils.toHex(array).toLowerCase();
var a = _x509_getPublicKeyHexArrayFromCertHex(hex, _x509_getSubjectPublicKeyPosFromCertHex(hex, 0));
var rsaKey = new RSAKey();
rsaKey.setPublic(a[0], a[1]);
return rsaKey;
}
/**
* Return a user friendly HTML string with the contents of data.
* This also outputs to console.log.
*/
EncodingUtils.dataToHtml = function(/* Data */ data)
{
var output ="";
if (data == -1)
output+= "NO CONTENT FOUND"
else if (data == -2)
output+= "CONTENT NAME IS EMPTY"
else {
if (data.name != null && data.name.components != null) {
output+= "NAME: " + data.name.toUri();
output+= "<br />";
output+= "<br />";
}
if (data.content != null) {
output += "CONTENT(ASCII): "+ DataUtils.toString(data.content);
output+= "<br />";
output+= "<br />";
}
if (data.content != null) {
output += "CONTENT(hex): "+ DataUtils.toHex(data.content);
output+= "<br />";
output+= "<br />";
}
if (data.signature != null && data.signature.digestAlgorithm != null) {
output += "DigestAlgorithm (hex): "+ DataUtils.toHex(data.signature.digestAlgorithm);
output+= "<br />";
output+= "<br />";
}
if (data.signature != null && data.signature.witness != null) {
output += "Witness (hex): "+ DataUtils.toHex(data.signature.witness);
output+= "<br />";
output+= "<br />";
}
if (data.signature != null && data.signature.signature != null) {
output += "Signature(hex): "+ DataUtils.toHex(data.signature.signature);
output+= "<br />";
output+= "<br />";
}
if (data.signedInfo != null && data.signedInfo.publisher != null && data.signedInfo.publisher.publisherPublicKeyDigest != null) {
output += "Publisher Public Key Digest(hex): "+ DataUtils.toHex(data.signedInfo.publisher.publisherPublicKeyDigest);
output+= "<br />";
output+= "<br />";
}
if (data.signedInfo != null && data.signedInfo.timestamp != null) {
var d = new Date();
d.setTime(data.signedInfo.timestamp.msec);
var bytes = [217, 185, 12, 225, 217, 185, 12, 225];
output += "TimeStamp: "+d;
output+= "<br />";
output += "TimeStamp(number): "+ data.signedInfo.timestamp.msec;
output+= "<br />";
}
if (data.signedInfo != null && data.signedInfo.finalBlockID != null) {
output += "FinalBlockID: "+ DataUtils.toHex(data.signedInfo.finalBlockID);
output+= "<br />";
}
if (data.signedInfo != null && data.signedInfo.locator != null && data.signedInfo.locator.type) {
output += "keyLocator: ";
if (data.signedInfo.locator.type == KeyLocatorType.KEY)
output += "Key: " + DataUtils.toHex(data.signedInfo.locator.publicKey).toLowerCase() + "<br />";
else if (data.signedInfo.locator.type == KeyLocatorType.KEY_LOCATOR_DIGEST)
output += "KeyLocatorDigest: " + DataUtils.toHex(data.signedInfo.locator.getKeyData()).toLowerCase() + "<br />";
else if (data.signedInfo.locator.type == KeyLocatorType.CERTIFICATE)
output += "Certificate: " + DataUtils.toHex(data.signedInfo.locator.certificate).toLowerCase() + "<br />";
else if (data.signedInfo.locator.type == KeyLocatorType.KEYNAME)
output += "KeyName: " + data.signedInfo.locator.keyName.contentName.to_uri() + "<br />";
else
output += "[unrecognized ndn_KeyLocatorType " + data.signedInfo.locator.type + "]<br />";
}
}
return output;
};
/**
* @deprecated Use return EncodingUtils.dataToHtml(data).
*/
EncodingUtils.contentObjectToHtml = function(data)
{
return EncodingUtils.dataToHtml(data);
}
//
// Deprecated: For the browser, define these in the global scope. Applications should access as member of EncodingUtils.
//
var encodeToHexInterest = function(interest) { return EncodingUtils.encodeToHexInterest(interest); }
var encodeToHexContentObject = function(data) { return EncodingUtils.encodeToHexData(data); }
var encodeForwardingEntry = function(data) { return EncodingUtils.encodeForwardingEntry(data); }
var decodeHexFaceInstance = function(input) { return EncodingUtils.decodeHexFaceInstance(input); }
var decodeHexInterest = function(input) { return EncodingUtils.decodeHexInterest(input); }
var decodeHexContentObject = function(input) { return EncodingUtils.decodeHexData(input); }
var decodeHexForwardingEntry = function(input) { return EncodingUtils.decodeHexForwardingEntry(input); }
var decodeSubjectPublicKeyInfo = function(input) { return EncodingUtils.decodeSubjectPublicKeyInfo(input); }
var contentObjectToHtml = function(data) { return EncodingUtils.dataToHtml(data); }
/**
* @deprecated Use interest.wireEncode().
*/
function encodeToBinaryInterest(interest) { return interest.wireEncode().buf(); }
/**
* @deprecated Use data.wireEncode().
*/
function encodeToBinaryContentObject(data) { return data.wireEncode().buf(); }
},{"../data.js":27,"../face-instance.js":44,"../forwarding-entry.js":46,"../interest.js":48,"../key-locator.js":49,"../key.js":50,"../log.js":51,"./binary-xml-decoder.js":28,"./binary-xml-encoder.js":29,"./data-utils.js":32,"./wire-format.js":42}],36:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
var crypto = require('../crypto.js');
var Blob = require('../util/blob.js').Blob;
var Tlv = require('./tlv/tlv.js').Tlv;
var TlvEncoder = require('./tlv/tlv-encoder.js').TlvEncoder;
var TlvDecoder = require('./tlv/tlv-decoder.js').TlvDecoder;
var WireFormat = require('./wire-format.js').WireFormat;
var Exclude = require('../exclude.js').Exclude;
var ContentType = require('../meta-info.js').ContentType;
var KeyLocatorType = require('../key-locator.js').KeyLocatorType;
var Signature = require('../signature.js').Signature;
var DecodingException = require('./decoding-exception.js').DecodingException;
/**
* A Tlv0_1a2WireFormat implements the WireFormat interface for encoding and
* decoding with the NDN-TLV wire format, version 0.1a2
* @constructor
*/
var Tlv0_1a2WireFormat = function Tlv0_1a2WireFormat()
{
// Inherit from WireFormat.
WireFormat.call(this);
};
Tlv0_1a2WireFormat.prototype = new WireFormat();
Tlv0_1a2WireFormat.prototype.name = "Tlv0_1a2WireFormat";
exports.Tlv0_1a2WireFormat = Tlv0_1a2WireFormat;
// Default object.
Tlv0_1a2WireFormat.instance = null;
/**
* Encode the interest using NDN-TLV and return a customBuf.
* @param {Interest} interest The Interest object to encode.
* @returns {Blob} A Blob containing the encoding.
*/
Tlv0_1a2WireFormat.prototype.encodeInterest = function(interest)
{
var encoder = new TlvEncoder();
var saveLength = encoder.getLength();
// Encode backwards.
encoder.writeOptionalNonNegativeIntegerTlv
(Tlv.InterestLifetime, interest.getInterestLifetimeMilliseconds());
encoder.writeOptionalNonNegativeIntegerTlv(Tlv.Scope, interest.getScope());
// Encode the Nonce as 4 bytes.
if (interest.getNonce() == null || interest.getNonce().length == 0)
// This is the most common case. Generate a nonce.
encoder.writeBlobTlv(Tlv.Nonce, require("../crypto.js").randomBytes(4));
else if (interest.getNonce().length < 4) {
var nonce = customBuf(4);
// Copy existing nonce bytes.
interest.getNonce().copy(nonce);
// Generate random bytes for remaining bytes in the nonce.
for (var i = interest.getNonce().length; i < 4; ++i)
nonce[i] = require("crypto").randomBytes(1)[0];
encoder.writeBlobTlv(Tlv.Nonce, nonce);
}
else if (interest.getNonce().length == 4)
// Use the nonce as-is.
encoder.writeBlobTlv(Tlv.Nonce, interest.getNonce());
else
// Truncate.
encoder.writeBlobTlv(Tlv.Nonce, interest.getNonce().slice(0, 4));
Tlv0_1a2WireFormat.encodeSelectors(interest, encoder);
Tlv0_1a2WireFormat.encodeName(interest.getName(), encoder);
encoder.writeTypeAndLength(Tlv.Interest, encoder.getLength() - saveLength);
return new Blob(encoder.getOutput(), false);
};
/**
* Decode input as an NDN-TLV interest and set the fields of the interest
* object.
* @param {Interest} interest The Interest object whose fields are updated.
* @param {Buffer} input The buffer with the bytes to decode.
*/
Tlv0_1a2WireFormat.prototype.decodeInterest = function(interest, input)
{
var decoder = new TlvDecoder(input);
var endOffset = decoder.readNestedTlvsStart(Tlv.Interest);
Tlv0_1a2WireFormat.decodeName(interest.getName(), decoder);
if (decoder.peekType(Tlv.Selectors, endOffset))
Tlv0_1a2WireFormat.decodeSelectors(interest, decoder);
// Require a Nonce, but don't force it to be 4 bytes.
var nonce = decoder.readBlobTlv(Tlv.Nonce);
interest.setScope(decoder.readOptionalNonNegativeIntegerTlv
(Tlv.Scope, endOffset));
interest.setInterestLifetimeMilliseconds
(decoder.readOptionalNonNegativeIntegerTlv(Tlv.InterestLifetime, endOffset));
// Set the nonce last because setting other interest fields clears it.
interest.setNonce(nonce);
decoder.finishNestedTlvs(endOffset);
};
/**
* Encode data as NDN-TLV and return the encoding and signed offsets.
* @param {Data} data The Data object to encode.
* @returns {object with (Blob, int, int)} An associative array with fields
* (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
* is a Blob containing the encoding, signedPortionBeginOffset is the offset in
* the encoding of the beginning of the signed portion, and
* signedPortionEndOffset is the offset in the encoding of the end of the
* signed portion.
*/
Tlv0_1a2WireFormat.prototype.encodeData = function(data)
{
var encoder = new TlvEncoder(1500);
var saveLength = encoder.getLength();
// Encode backwards.
// TODO: The library needs to handle other signature types than
// SignatureSha256WithRsa.
encoder.writeBlobTlv(Tlv.SignatureValue, data.getSignature().getSignature());
var signedPortionEndOffsetFromBack = encoder.getLength();
// Use getSignatureOrMetaInfoKeyLocator for the transition of moving
// the key locator from the MetaInfo to the Signauture object.
Tlv0_1a2WireFormat.encodeSignatureSha256WithRsaValue
(data.getSignature(), encoder, data.getSignatureOrMetaInfoKeyLocator());
encoder.writeBlobTlv(Tlv.Content, data.getContent());
Tlv0_1a2WireFormat.encodeMetaInfo(data.getMetaInfo(), encoder);
Tlv0_1a2WireFormat.encodeName(data.getName(), encoder);
var signedPortionBeginOffsetFromBack = encoder.getLength();
encoder.writeTypeAndLength(Tlv.Data, encoder.getLength() - saveLength);
var signedPortionBeginOffset =
encoder.getLength() - signedPortionBeginOffsetFromBack;
var signedPortionEndOffset = encoder.getLength() - signedPortionEndOffsetFromBack;
return { encoding: new Blob(encoder.getOutput(), false),
signedPortionBeginOffset: signedPortionBeginOffset,
signedPortionEndOffset: signedPortionEndOffset };
};
/**
* Decode input as an NDN-TLV data packet, set the fields in the data object,
* and return the signed offsets.
* @param {Data} data The Data object whose fields are updated.
* @param {Buffer} input The buffer with the bytes to decode.
* @returns {object with (int, int)} An associative array with fields
* (signedPortionBeginOffset, signedPortionEndOffset) where
* signedPortionBeginOffset is the offset in the encoding of the beginning of
* the signed portion, and signedPortionEndOffset is the offset in the encoding
* of the end of the signed portion.
*/
Tlv0_1a2WireFormat.prototype.decodeData = function(data, input)
{
var decoder = new TlvDecoder(input);
var endOffset = decoder.readNestedTlvsStart(Tlv.Data);
var signedPortionBeginOffset = decoder.getOffset();
Tlv0_1a2WireFormat.decodeName(data.getName(), decoder);
Tlv0_1a2WireFormat.decodeMetaInfo(data.getMetaInfo(), decoder);
data.setContent(decoder.readBlobTlv(Tlv.Content));
Tlv0_1a2WireFormat.decodeSignatureInfo(data, decoder);
if (data.getSignature() != null &&
data.getSignature().getKeyLocator() != null &&
data.getMetaInfo() != null)
// Copy the key locator pointer to the MetaInfo object for the transition of
// moving the key locator from the MetaInfo to the Signature object.
data.getMetaInfo().locator = data.getSignature().getKeyLocator();
var signedPortionEndOffset = decoder.getOffset();
// TODO: The library needs to handle other signature types than
// SignatureSha256WithRsa.
data.getSignature().setSignature(decoder.readBlobTlv(Tlv.SignatureValue));
decoder.finishNestedTlvs(endOffset);
return { signedPortionBeginOffset: signedPortionBeginOffset,
signedPortionEndOffset: signedPortionEndOffset };
};
/**
* Get a singleton instance of a Tlv1_0a2WireFormat. To always use the
* preferred version NDN-TLV, you should use TlvWireFormat.get().
* @returns {Tlv0_1a2WireFormat} The singleton instance.
*/
Tlv0_1a2WireFormat.get = function()
{
if (Tlv0_1a2WireFormat.instance === null)
Tlv0_1a2WireFormat.instance = new Tlv0_1a2WireFormat();
return Tlv0_1a2WireFormat.instance;
};
Tlv0_1a2WireFormat.encodeName = function(name, encoder)
{
var saveLength = encoder.getLength();
// Encode the components backwards.
for (var i = name.size() - 1; i >= 0; --i)
encoder.writeBlobTlv(Tlv.NameComponent, name.get(i).getValue());
encoder.writeTypeAndLength(Tlv.Name, encoder.getLength() - saveLength);
};
Tlv0_1a2WireFormat.decodeName = function(name, decoder)
{
name.clear();
var endOffset = decoder.readNestedTlvsStart(Tlv.Name);
while (decoder.getOffset() < endOffset)
name.append(decoder.readBlobTlv(Tlv.NameComponent));
decoder.finishNestedTlvs(endOffset);
};
/**
* Encode the interest selectors. If no selectors are written, do not output a
* Selectors TLV.
*/
Tlv0_1a2WireFormat.encodeSelectors = function(interest, encoder)
{
var saveLength = encoder.getLength();
// Encode backwards.
if (interest.getMustBeFresh())
encoder.writeTypeAndLength(Tlv.MustBeFresh, 0);
encoder.writeOptionalNonNegativeIntegerTlv(
Tlv.ChildSelector, interest.getChildSelector());
if (interest.getExclude().size() > 0)
Tlv0_1a2WireFormat.encodeExclude(interest.getExclude(), encoder);
if (interest.getKeyLocator().getType() != null)
Tlv0_1a2WireFormat.encodeKeyLocator(interest.getKeyLocator(), encoder);
else {
// There is no keyLocator. If there is a publisherPublicKeyDigest, then
// encode as KEY_LOCATOR_DIGEST. (When we remove the deprecated
// publisherPublicKeyDigest, we don't need this.)
if (null != interest.publisherPublicKeyDigest) {
var savePublisherPublicKeyDigestLength = encoder.getLength();
encoder.writeBlobTlv
(Tlv.KeyLocatorDigest,
interest.publisherPublicKeyDigest.publisherPublicKeyDigest);
encoder.writeTypeAndLength
(Tlv.KeyLocator, encoder.getLength() - savePublisherPublicKeyDigestLength);
}
}
encoder.writeOptionalNonNegativeIntegerTlv(
Tlv.MaxSuffixComponents, interest.getMaxSuffixComponents());
encoder.writeOptionalNonNegativeIntegerTlv(
Tlv.MinSuffixComponents, interest.getMinSuffixComponents());
// Only output the type and length if values were written.
if (encoder.getLength() != saveLength)
encoder.writeTypeAndLength(Tlv.Selectors, encoder.getLength() - saveLength);
};
Tlv0_1a2WireFormat.decodeSelectors = function(interest, decoder)
{
var endOffset = decoder.readNestedTlvsStart(Tlv.Selectors);
interest.setMinSuffixComponents(decoder.readOptionalNonNegativeIntegerTlv
(Tlv.MinSuffixComponents, endOffset));
interest.setMaxSuffixComponents(decoder.readOptionalNonNegativeIntegerTlv
(Tlv.MaxSuffixComponents, endOffset));
// Initially set publisherPublicKeyDigest to none.
interest.publisherPublicKeyDigest = null;
if (decoder.peekType(Tlv.KeyLocator, endOffset)) {
Tlv0_1a2WireFormat.decodeKeyLocator(interest.getKeyLocator(), decoder);
if (interest.getKeyLocator().getType() == KeyLocatorType.KEY_LOCATOR_DIGEST) {
// For backwards compatibility, also set the publisherPublicKeyDigest.
interest.publisherPublicKeyDigest = new PublisherPublicKeyDigest();
interest.publisherPublicKeyDigest.publisherPublicKeyDigest =
interest.getKeyLocator().getKeyData();
}
}
else
interest.getKeyLocator().clear();
if (decoder.peekType(Tlv.Exclude, endOffset))
Tlv0_1a2WireFormat.decodeExclude(interest.getExclude(), decoder);
else
interest.getExclude().clear();
interest.setChildSelector(decoder.readOptionalNonNegativeIntegerTlv
(Tlv.ChildSelector, endOffset));
interest.setMustBeFresh(decoder.readBooleanTlv(Tlv.MustBeFresh, endOffset));
decoder.finishNestedTlvs(endOffset);
};
Tlv0_1a2WireFormat.encodeExclude = function(exclude, encoder)
{
var saveLength = encoder.getLength();
// TODO: Do we want to order the components (except for ANY)?
// Encode the entries backwards.
for (var i = exclude.size() - 1; i >= 0; --i) {
var entry = exclude.get(i);
if (entry == Exclude.ANY)
encoder.writeTypeAndLength(Tlv.Any, 0);
else
encoder.writeBlobTlv(Tlv.NameComponent, entry.getValue());
}
encoder.writeTypeAndLength(Tlv.Exclude, encoder.getLength() - saveLength);
};
Tlv0_1a2WireFormat.decodeExclude = function(exclude, decoder)
{
var endOffset = decoder.readNestedTlvsStart(Tlv.Exclude);
exclude.clear();
while (true) {
if (decoder.peekType(Tlv.NameComponent, endOffset))
exclude.appendComponent(decoder.readBlobTlv(Tlv.NameComponent));
else if (decoder.readBooleanTlv(Tlv.Any, endOffset))
exclude.appendAny();
else
// Else no more entries.
break;
}
decoder.finishNestedTlvs(endOffset);
};
Tlv0_1a2WireFormat.encodeKeyLocator = function(keyLocator, encoder)
{
var saveLength = encoder.getLength();
// Encode backwards.
if (keyLocator.getType() != null) {
if (keyLocator.getType() == KeyLocatorType.KEYNAME)
Tlv0_1a2WireFormat.encodeName(keyLocator.getKeyName(), encoder);
else if (keyLocator.getType() == KeyLocatorType.KEY_LOCATOR_DIGEST &&
keyLocator.getKeyData().length > 0)
encoder.writeBlobTlv(Tlv.KeyLocatorDigest, keyLocator.getKeyData());
else
throw new Error("Unrecognized KeyLocatorType " + keyLocator.getType());
}
encoder.writeTypeAndLength(Tlv.KeyLocator, encoder.getLength() - saveLength);
};
Tlv0_1a2WireFormat.decodeKeyLocator = function(keyLocator, decoder)
{
var endOffset = decoder.readNestedTlvsStart(Tlv.KeyLocator);
keyLocator.clear();
if (decoder.getOffset() == endOffset)
// The KeyLocator is omitted, so leave the fields as none.
return;
if (decoder.peekType(Tlv.Name, endOffset)) {
// KeyLocator is a Name.
keyLocator.setType(KeyLocatorType.KEYNAME);
Tlv0_1a2WireFormat.decodeName(keyLocator.getKeyName(), decoder);
}
else if (decoder.peekType(Tlv.KeyLocatorDigest, endOffset)) {
// KeyLocator is a KeyLocatorDigest.
keyLocator.setType(KeyLocatorType.KEY_LOCATOR_DIGEST);
keyLocator.setKeyData(decoder.readBlobTlv(Tlv.KeyLocatorDigest));
}
else
throw new DecodingException
("decodeKeyLocator: Unrecognized key locator type");
decoder.finishNestedTlvs(endOffset);
};
/**
* Encode the signature object in TLV, using the given keyLocator instead of the
* locator in this object.
* @param {Signature} signature The Signature object to encode.
* @param {TlvEncoder} encoder The encoder.
* @param {KeyLocator} keyLocator The key locator to use (from
* Data.getSignatureOrMetaInfoKeyLocator).
*/
Tlv0_1a2WireFormat.encodeSignatureSha256WithRsaValue = function
(signature, encoder, keyLocator)
{
var saveLength = encoder.getLength();
// Encode backwards.
Tlv0_1a2WireFormat.encodeKeyLocator(keyLocator, encoder);
encoder.writeNonNegativeIntegerTlv
(Tlv.SignatureType, Tlv.SignatureType_SignatureSha256WithRsa);
encoder.writeTypeAndLength(Tlv.SignatureInfo, encoder.getLength() - saveLength);
};
Tlv0_1a2WireFormat.decodeSignatureInfo = function(data, decoder)
{
var endOffset = decoder.readNestedTlvsStart(Tlv.SignatureInfo);
var signatureType = decoder.readNonNegativeIntegerTlv(Tlv.SignatureType);
// TODO: The library needs to handle other signature types than
// SignatureSha256WithRsa.
if (signatureType == Tlv.SignatureType_SignatureSha256WithRsa) {
var signature = {}
signature.sig = Signature
data.setSignature(signature.sig());
// Modify data's signature object because if we create an object
// and set it, then data will have to copy all the fields.
var signatureInfo = data.getSignature();
Tlv0_1a2WireFormat.decodeKeyLocator
(signatureInfo.getKeyLocator(), decoder);
}
else
throw new DecodingException
("decodeSignatureInfo: unrecognized SignatureInfo type" + signatureType);
decoder.finishNestedTlvs(endOffset);
};
Tlv0_1a2WireFormat.encodeMetaInfo = function(metaInfo, encoder)
{
var saveLength = encoder.getLength();
// Encode backwards.
// TODO: finalBlockID should be a Name.Component, not customBuf.
var finalBlockIdBuf = metaInfo.getFinalBlockID();
if (finalBlockIdBuf != null && finalBlockIdBuf.length > 0) {
// FinalBlockId has an inner NameComponent.
var finalBlockIdSaveLength = encoder.getLength();
encoder.writeBlobTlv(Tlv.NameComponent, finalBlockIdBuf);
encoder.writeTypeAndLength
(Tlv.FinalBlockId, encoder.getLength() - finalBlockIdSaveLength);
}
encoder.writeOptionalNonNegativeIntegerTlv
(Tlv.FreshnessPeriod, metaInfo.getFreshnessPeriod());
if (metaInfo.getType() != ContentType.BLOB) {
// Not the default, so we need to encode the type.
if (metaInfo.getType() == ContentType.LINK ||
metaInfo.getType() == ContentType.KEY)
// The ContentType enum is set up with the correct integer for
// each NDN-TLV ContentType.
encoder.writeNonNegativeIntegerTlv(Tlv.ContentType, metaInfo.getType());
else
throw new Error("unrecognized TLV ContentType");
}
encoder.writeTypeAndLength(Tlv.MetaInfo, encoder.getLength() - saveLength);
};
Tlv0_1a2WireFormat.decodeMetaInfo = function(metaInfo, decoder)
{
var endOffset = decoder.readNestedTlvsStart(Tlv.MetaInfo);
// The ContentType enum is set up with the correct integer for each
// NDN-TLV ContentType. If readOptionalNonNegativeIntegerTlv returns
// None, then setType will convert it to BLOB.
metaInfo.setType(decoder.readOptionalNonNegativeIntegerTlv
(Tlv.ContentType, endOffset));
metaInfo.setFreshnessPeriod
(decoder.readOptionalNonNegativeIntegerTlv(Tlv.FreshnessPeriod, endOffset));
if (decoder.peekType(Tlv.FinalBlockId, endOffset)) {
var finalBlockIdEndOffset = decoder.readNestedTlvsStart(Tlv.FinalBlockId);
metaInfo.setFinalBlockID(decoder.readBlobTlv(Tlv.NameComponent));
decoder.finishNestedTlvs(finalBlockIdEndOffset);
}
else
metaInfo.setFinalBlockID(null);
decoder.finishNestedTlvs(endOffset);
};
},{"../crypto.js":25,"../exclude.js":43,"../key-locator.js":49,"../meta-info.js":52,"../signature.js":57,"../util/blob.js":59,"./decoding-exception.js":33,"./tlv/tlv-decoder.js":38,"./tlv/tlv-encoder.js":39,"./tlv/tlv.js":41,"./wire-format.js":42,"crypto":5}],37:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
var WireFormat = require('./wire-format.js').WireFormat;
var Tlv0_1a2WireFormat = require('./tlv-0_1a2-wire-format.js').Tlv0_1a2WireFormat;
/**
* A TlvWireFormat extends Tlv0_1a2WireFormat to override its methods to
* implement encoding and decoding using the preferred implementation of NDN-TLV.
* @constructor
*/
var TlvWireFormat = function TlvWireFormat()
{
// Inherit from Tlv0_1a2WireFormat.
Tlv0_1a2WireFormat.call(this);
};
TlvWireFormat.prototype = new Tlv0_1a2WireFormat();
TlvWireFormat.prototype.name = "TlvWireFormat";
exports.TlvWireFormat = TlvWireFormat;
// Default object.
TlvWireFormat.instance = null;
/**
* Get a singleton instance of a TlvWireFormat. Assuming that the default
* wire format was set with WireFormat.setDefaultWireFormat(TlvWireFormat.get()),
* you can check if this is the default wire encoding with
* if WireFormat.getDefaultWireFormat() == TlvWireFormat.get().
* @returns {TlvWireFormat} The singleton instance.
*/
TlvWireFormat.get = function()
{
if (TlvWireFormat.instance === null)
TlvWireFormat.instance = new TlvWireFormat();
return TlvWireFormat.instance;
};
// On loading this module, make this the default wire format.
// This module will be loaded because WireFormat loads it.
WireFormat.setDefaultWireFormat(TlvWireFormat.get());
},{"./tlv-0_1a2-wire-format.js":36,"./wire-format.js":42}],38:[function(require,module,exports){
/**
* Copyright (C) 2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
var customBuf = require('../../buffer.js').Buffer
var DecodingException = require('../decoding-exception.js').DecodingException;
/**
* Create a new TlvDecoder for decoding the input in the NDN-TLV wire format.
* @constructor
* @param {Buffer} input The buffer with the bytes to decode.
*/
var TlvDecoder = function TlvDecoder(input)
{
this.input = input;
this.offset = 0;
};
exports.TlvDecoder = TlvDecoder;
/**
* Decode VAR-NUMBER in NDN-TLV and return it. Update offset.
* @returns {number} The decoded VAR-NUMBER.
*/
TlvDecoder.prototype.readVarNumber = function()
{
// Assume array values are in the range 0 to 255.
var firstOctet = this.input[this.offset];
this.offset += 1;
if (firstOctet < 253)
return firstOctet;
else
return this.readExtendedVarNumber(firstOctet);
};
/**
* A private function to do the work of readVarNumber, given the firstOctet
* which is >= 253.
* @param {number} firstOctet The first octet which is >= 253, used to decode
* the remaining bytes.
* @returns {number} The decoded VAR-NUMBER.
*/
TlvDecoder.prototype.readExtendedVarNumber = function(firstOctet)
{
// This is a private function so we know firstOctet >= 253.
if (firstOctet == 253) {
result = ((this.input[this.offset] << 8) +
this.input[this.offset + 1]);
this.offset += 2;
}
else if (firstOctet == 254) {
result = ((this.input[this.offset] << 24) +
(this.input[this.offset + 1] << 16) +
(this.input[this.offset + 2] << 8) +
this.input[this.offset + 3]);
this.offset += 4;
}
else {
result = ((this.input[this.offset] << 56) +
(this.input[this.offset + 1] << 48) +
(this.input[this.offset + 2] << 40) +
(this.input[this.offset + 3] << 32) +
(this.input[this.offset + 4] << 24) +
(this.input[this.offset + 5] << 16) +
(this.input[this.offset + 6] << 8) +
this.input[this.offset + 7]);
this.offset += 8;
}
return result;
};
/**
* Decode the type and length from this's input starting at offset, expecting
* the type to be expectedType and return the length. Update offset. Also make
* sure the decoded length does not exceed the number of bytes remaining in the
* input.
* @param {number} expectedType The expected type.
* @returns {number} The length of the TLV.
* @throws DecodingException if (did not get the expected TLV type or the TLV length
* exceeds the buffer length.
*/
TlvDecoder.prototype.readTypeAndLength = function(expectedType)
{
var type = this.readVarNumber();
if (type != expectedType)
throw new DecodingException("Did not get the expected TLV type");
var length = this.readVarNumber();
if (this.offset + length > this.input.length)
throw new DecodingException("TLV length exceeds the buffer length");
return length;
};
/**
* Decode the type and length from the input starting at offset, expecting the
* type to be expectedType. Update offset. Also make sure the decoded length
* does not exceed the number of bytes remaining in the input. Return the offset
* of the end of this parent TLV, which is used in decoding optional nested
* TLVs. After reading all nested TLVs, call finishNestedTlvs.
* @param {number} expectedType The expected type.
* @returns {number} The offset of the end of the parent TLV.
* @throws DecodingException if did not get the expected TLV type or the TLV
* length exceeds the buffer length.
*/
TlvDecoder.prototype.readNestedTlvsStart = function(expectedType)
{
return this.readTypeAndLength(expectedType) + this.offset;
};
/**
* Call this after reading all nested TLVs to skip any remaining unrecognized
* TLVs and to check if the offset after the final nested TLV matches the
* endOffset returned by readNestedTlvsStart.
* @param {number} endOffset The offset of the end of the parent TLV, returned
* by readNestedTlvsStart.
* @throws DecodingException if the TLV length does not equal the total length
* of the nested TLVs.
*/
TlvDecoder.prototype.finishNestedTlvs = function(endOffset)
{
// We expect offset to be endOffset, so check this first.
if (this.offset == endOffset)
return;
// Skip remaining TLVs.
while (this.offset < endOffset) {
// Skip the type VAR-NUMBER.
this.readVarNumber();
// Read the length and update offset.
var length = this.readVarNumber();
this.offset += length;
if (this.offset > this.input.length)
throw new DecodingException("TLV length exceeds the buffer length");
}
if (this.offset != endOffset)
throw new DecodingException
("TLV length does not equal the total length of the nested TLVs");
};
/**
* Decode the type from this's input starting at offset, and if it is the
* expectedType, then return true, else false. However, if this's offset is
* greater than or equal to endOffset, then return false and don't try to read
* the type. Do not update offset.
* @param {number} expectedType The expected type.
* @param {number} endOffset The offset of the end of the parent TLV, returned
* by readNestedTlvsStart.
* @returns {boolean} true if the type of the next TLV is the expectedType,
* otherwise false.
*/
TlvDecoder.prototype.peekType = function(expectedType, endOffset)
{
if (this.offset >= endOffset)
// No more sub TLVs to look at.
return false;
else {
var saveOffset = this.offset;
var type = this.readVarNumber();
// Restore offset.
this.offset = saveOffset;
return type == expectedType;
}
};
/**
* Decode a non-negative integer in NDN-TLV and return it. Update offset by
* length.
* @param {number} length The number of bytes in the encoded integer.
* @returns {number} The integer.
* @throws DecodingException if length is an invalid length for a TLV
* non-negative integer.
*/
TlvDecoder.prototype.readNonNegativeInteger = function(length)
{
var result;
if (length == 1)
result = this.input[this.offset];
else if (length == 2)
result = ((this.input[this.offset] << 8) +
this.input[this.offset + 1]);
else if (length == 4)
result = ((this.input[this.offset] << 24) +
(this.input[this.offset + 1] << 16) +
(this.input[this.offset + 2] << 8) +
this.input[this.offset + 3]);
else if (length == 8)
result = ((this.input[this.offset] << 56) +
(this.input[this.offset + 1] << 48) +
(this.input[this.offset + 2] << 40) +
(this.input[this.offset + 3] << 32) +
(this.input[this.offset + 4] << 24) +
(this.input[this.offset + 5] << 16) +
(this.input[this.offset + 6] << 8) +
this.input[this.offset + 7]);
else
throw new DecodingException("Invalid length for a TLV nonNegativeInteger");
this.offset += length;
return result;
};
/**
* Decode the type and length from this's input starting at offset, expecting
* the type to be expectedType. Then decode a non-negative integer in NDN-TLV
* and return it. Update offset.
* @param {number} expectedType The expected type.
* @returns {number} The integer.
* @throws DecodingException if did not get the expected TLV type or can't
* decode the value.
*/
TlvDecoder.prototype.readNonNegativeIntegerTlv = function(expectedType)
{
var length = this.readTypeAndLength(expectedType);
return this.readNonNegativeInteger(length);
};
/**
* Peek at the next TLV, and if it has the expectedType then call
* readNonNegativeIntegerTlv and return the integer. Otherwise, return null.
* However, if this's offset is greater than or equal to endOffset, then return
* null and don't try to read the type.
* @param {number} expectedType The expected type.
* @param {number} endOffset The offset of the end of the parent TLV, returned
* by readNestedTlvsStart.
* @returns {number} The integer or null if the next TLV doesn't have the
* expected type.
*/
TlvDecoder.prototype.readOptionalNonNegativeIntegerTlv = function
(expectedType, endOffset)
{
if (this.peekType(expectedType, endOffset))
return this.readNonNegativeIntegerTlv(expectedType);
else
return null;
};
/**
* Decode the type and length from this's input starting at offset, expecting
* the type to be expectedType. Then return an array of the bytes in the value.
* Update offset.
* @param {number} expectedType The expected type.
* @returns {Buffer} The bytes in the value as a slice on the buffer. This is
* not a copy of the bytes in the input buffer. If you need a copy, then you
* must make a copy of the return value.
* @throws DecodingException if did not get the expected TLV type.
*/
TlvDecoder.prototype.readBlobTlv = function(expectedType)
{
var length = this.readTypeAndLength(expectedType);
var result = this.input.slice(this.offset, this.offset + length);
// readTypeAndLength already checked if length exceeds the input buffer.
this.offset += length;
return result;
};
/**
* Peek at the next TLV, and if it has the expectedType then call readBlobTlv
* and return the value. Otherwise, return null. However, if this's offset is
* greater than or equal to endOffset, then return null and don't try to read
* the type.
* @param {number} expectedType The expected type.
* @param {number} endOffset The offset of the end of the parent TLV, returned
* by readNestedTlvsStart.
* @returns {Buffer} The bytes in the value as a slice on the buffer or null if
* the next TLV doesn't have the expected type. This is not a copy of the bytes
* in the input buffer. If you need a copy, then you must make a copy of the
* return value.
*/
TlvDecoder.prototype.readOptionalBlobTlv = function(expectedType, endOffset)
{
if (this.peekType(expectedType, endOffset))
return this.readBlobTlv(expectedType);
else
return null;
};
/**
* Peek at the next TLV, and if it has the expectedType then read a type and
* value, ignoring the value, and return true. Otherwise, return false.
* However, if this's offset is greater than or equal to endOffset, then return
* false and don't try to read the type.
* @param {number} expectedType The expected type.
* @param {number} endOffset The offset of the end of the parent TLV, returned
* by readNestedTlvsStart.
* @returns {boolean} true, or else false if the next TLV doesn't have the
* expected type.
*/
TlvDecoder.prototype.readBooleanTlv = function(expectedType, endOffset)
{
if (this.peekType(expectedType, endOffset)) {
var length = this.readTypeAndLength(expectedType);
// We expect the length to be 0, but update offset anyway.
this.offset += length;
return true;
}
else
return false;
};
/**
* Get the offset into the input, used for the next read.
* @returns {number} The offset.
*/
TlvDecoder.prototype.getOffset = function()
{
return this.offset;
};
/**
* Set the offset into the input, used for the next read.
* @param {number} offset The new offset.
*/
TlvDecoder.prototype.seek = function(offset)
{
this.offset = offset;
};
},{"../../buffer.js":25,"../decoding-exception.js":33}],39:[function(require,module,exports){
/**
* Copyright (C) 2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
var customBuf = require('../../buffer.js').Buffer
var DynamicBuffer = require('../../util/dynamic-buffer.js').DynamicBuffer;
/**
* Create a new TlvEncoder with an initialCapacity for the encoding buffer.
* @constructor
* @param {number} initialCapacity (optional) The initial capacity of the
* encoding buffer. If omitted, use a default value.
*/
var TlvEncoder = function TlvEncoder(initialCapacity)
{
initialCapacity = initialCapacity || 16;
this.output = new DynamicBuffer(initialCapacity);
// length is the number of bytes that have been written to the back of
// this.output.array.
this.length = 0;
};
exports.TlvEncoder = TlvEncoder;
/**
* Get the number of bytes that have been written to the output. You can
* save this number, write sub TLVs, then subtract the new length from this
* to get the total length of the sub TLVs.
* @returns {number} The number of bytes that have been written to the output.
*/
TlvEncoder.prototype.getLength = function()
{
return this.length;
};
/**
* Encode varNumber as a VAR-NUMBER in NDN-TLV and write it to this.output just
* before this.length from the back. Advance this.length.
* @param {number} varNumber The non-negative number to encode.
*/
TlvEncoder.prototype.writeVarNumber = function(varNumber)
{
if (varNumber < 253) {
this.length += 1;
this.output.ensureLengthFromBack(this.length);
this.output.array[this.output.array.length - this.length] = varNumber & 0xff;
}
else if (varNumber <= 0xffff) {
this.length += 3;
this.output.ensureLengthFromBack(this.length);
var offset = this.output.array.length - this.length;
this.output.array[offset] = 253;
this.output.array[offset + 1] = (varNumber >> 8) & 0xff;
this.output.array[offset + 2] = varNumber & 0xff;
}
else if (varNumber <= 0xffffffff) {
this.length += 5;
this.output.ensureLengthFromBack(this.length);
var offset = this.output.array.length - this.length;
this.output.array[offset] = 254;
this.output.array[offset + 1] = (varNumber >> 24) & 0xff;
this.output.array[offset + 2] = (varNumber >> 16) & 0xff;
this.output.array[offset + 3] = (varNumber >> 8) & 0xff;
this.output.array[offset + 4] = varNumber & 0xff;
}
else {
this.length += 9;
this.output.ensureLengthFromBack(this.length);
var offset = this.output.array.length - this.length;
this.output.array[offset] = 255;
this.output.array[offset + 1] = (varNumber >> 56) & 0xff;
this.output.array[offset + 2] = (varNumber >> 48) & 0xff;
this.output.array[offset + 3] = (varNumber >> 40) & 0xff;
this.output.array[offset + 4] = (varNumber >> 32) & 0xff;
this.output.array[offset + 5] = (varNumber >> 24) & 0xff;
this.output.array[offset + 6] = (varNumber >> 16) & 0xff;
this.output.array[offset + 7] = (varNumber >> 8) & 0xff;
this.output.array[offset + 8] = varNumber & 0xff;
}
};
/**
* Encode the type and length as VAR-NUMBER and write to this.output just before
* this.length from the back. Advance this.length.
* @param {number} type The type of the TLV.
* @param {number} length The non-negative length of the TLV.
*/
TlvEncoder.prototype.writeTypeAndLength = function(type, length)
{
// Write backwards.
this.writeVarNumber(length);
this.writeVarNumber(type);
};
/**
* Write the type, then the length of the encoded value then encode value as a
* non-negative integer and write it to this.output just before this.length from
* the back. Advance this.length.
* @param {number} type The type of the TLV.
* @param {number} value The non-negative integer to encode.
*/
TlvEncoder.prototype.writeNonNegativeIntegerTlv = function(type, value)
{
if (value < 0)
throw new Error("TLV integer value may not be negative");
// JavaScript doesn't distinguish int from float, so round.
value = Math.round(value)
// Write backwards.
var saveNBytes = this.length;
if (value < 253) {
this.length += 1;
this.output.ensureLengthFromBack(this.length);
this.output.array[this.output.array.length - this.length] = value & 0xff;
}
else if (value <= 0xffff) {
this.length += 2;
this.output.ensureLengthFromBack(this.length);
var offset = this.output.array.length - this.length;
this.output.array[offset] = (value >> 8) & 0xff;
this.output.array[offset + 1] = value & 0xff;
}
else if (value <= 0xffffffff) {
this.length += 4;
this.output.ensureLengthFromBack(this.length);
var offset = this.output.array.length - this.length;
this.output.array[offset] = (value >> 24) & 0xff;
this.output.array[offset + 1] = (value >> 16) & 0xff;
this.output.array[offset + 2] = (value >> 8) & 0xff;
this.output.array[offset + 3] = value & 0xff;
}
else {
this.length += 8;
this.output.ensureLengthFromBack(this.length);
var offset = this.output.array.length - this.length;
this.output.array[offset] = (value >> 56) & 0xff;
this.output.array[offset + 1] = (value >> 48) & 0xff;
this.output.array[offset + 2] = (value >> 40) & 0xff;
this.output.array[offset + 3] = (value >> 32) & 0xff;
this.output.array[offset + 4] = (value >> 24) & 0xff;
this.output.array[offset + 5] = (value >> 16) & 0xff;
this.output.array[offset + 6] = (value >> 8) & 0xff;
this.output.array[offset + 7] = value & 0xff;
}
this.writeTypeAndLength(type, this.length - saveNBytes);
};
/**
* If value is negative or null then do nothing, otherwise call
* writeNonNegativeIntegerTlv.
* @param {number} type The type of the TLV.
* @param {number} value If negative or None do nothing, otherwise the integer
* to encode.
*/
TlvEncoder.prototype.writeOptionalNonNegativeIntegerTlv = function(type, value)
{
if (value != null && value >= 0)
this.writeNonNegativeIntegerTlv(type, value);
};
/**
* Write the type, then the length of the buffer then the buffer value to
* this.output just before this.length from the back. Advance this.length.
* @param {number} type The type of the TLV.
* @param {Buffer} value The byte array with the bytes of the blob. If value is
null, then just write the type and length 0.
*/
TlvEncoder.prototype.writeBlobTlv = function(type, value)
{
if (value == null) {
this.writeTypeAndLength(type, 0);
return;
}
// Write backwards, starting with the blob array.
this.length += value.length;
this.output.copyFromBack(value, this.length);
this.writeTypeAndLength(type, value.length);
};
/**
* If the byte array is null or zero length then do nothing, otherwise call
* writeBlobTlv.
* @param {number} type The type of the TLV.
* @param {Buffer} value If null or zero length do nothing, otherwise the byte
* array with the bytes of the blob.
*/
TlvEncoder.prototype.writeOptionalBlobTlv = function(type, value)
{
if (value != null && value.length > 0)
this.writeBlobTlv(type, value);
};
/**
* Get a slice of the encoded bytes.
* @returns {Buffer} A slice backed by the encoding customBuf.
*/
TlvEncoder.prototype.getOutput = function()
{
return this.output.array.slice(this.output.array.length - this.length);
};
},{"../../buffer.js":25,"../../util/dynamic-buffer.js":60}],40:[function(require,module,exports){
/**
* Copyright (C) 2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
var TlvDecoder = require('./tlv-decoder.js').TlvDecoder;
var customBuf = require('../../buffer.js').Buffer
/**
* Create and initialize a TlvStructureDecoder.
*/
var TlvStructureDecoder = function TlvStructureDecoder()
{
this.gotElementEnd = false;
this.offset = 0;
this.state = TlvStructureDecoder.READ_TYPE;
this.headerLength = 0;
this.useHeaderBuffer = false;
// 8 bytes is enough to hold the extended bytes in the length encoding
// where it is an 8-byte number.
this.headerBuffer = new customBuf(8);
this.nBytesToRead = 0;
};
exports.TlvStructureDecoder = TlvStructureDecoder;
TlvStructureDecoder.READ_TYPE = 0;
TlvStructureDecoder.READ_TYPE_BYTES = 1;
TlvStructureDecoder.READ_LENGTH = 2;
TlvStructureDecoder.READ_LENGTH_BYTES = 3;
TlvStructureDecoder.READ_VALUE_BYTES = 4;
/**
* Continue scanning input starting from this.offset to find the element end.
* If the end of the element which started at offset 0 is found, this returns
* true and getOffset() is the length of the element. Otherwise, this returns
* false which means you should read more into input and call again.
* @param {Buffer} input The input buffer. You have to pass in input each time
* because the buffer could be reallocated.
* @returns {boolean} true if found the element end, false if not.
*/
TlvStructureDecoder.prototype.findElementEnd = function(input)
{
if (this.gotElementEnd)
// Someone is calling when we already got the end.
return true;
var decoder = new TlvDecoder(input);
while (true) {
if (this.offset >= input.length)
// All the cases assume we have some input. Return and wait for more.
return false;
if (this.state == TlvStructureDecoder.READ_TYPE) {
var firstOctet = input[this.offset];
this.offset += 1;
if (firstOctet < 253)
// The value is simple, so we can skip straight to reading the length.
this.state = TlvStructureDecoder.READ_LENGTH;
else {
// Set up to skip the type bytes.
if (firstOctet == 253)
this.nBytesToRead = 2;
else if (firstOctet == 254)
this.nBytesToRead = 4;
else
// value == 255.
this.nBytesToRead = 8;
this.state = TlvStructureDecoder.READ_TYPE_BYTES;
}
}
else if (this.state == TlvStructureDecoder.READ_TYPE_BYTES) {
var nRemainingBytes = input.length - this.offset;
if (nRemainingBytes < this.nBytesToRead) {
// Need more.
this.offset += nRemainingBytes;
this.nBytesToRead -= nRemainingBytes;
return false;
}
// Got the type bytes. Move on to read the length.
this.offset += this.nBytesToRead;
this.state = TlvStructureDecoder.READ_LENGTH;
}
else if (this.state == TlvStructureDecoder.READ_LENGTH) {
var firstOctet = input[this.offset];
this.offset += 1;
if (firstOctet < 253) {
// The value is simple, so we can skip straight to reading
// the value bytes.
this.nBytesToRead = firstOctet;
if (this.nBytesToRead == 0) {
// No value bytes to read. We're finished.
this.gotElementEnd = true;
return true;
}
this.state = TlvStructureDecoder.READ_VALUE_BYTES;
}
else {
// We need to read the bytes in the extended encoding of
// the length.
if (firstOctet == 253)
this.nBytesToRead = 2;
else if (firstOctet == 254)
this.nBytesToRead = 4;
else
// value == 255.
this.nBytesToRead = 8;
// We need to use firstOctet in the next state.
this.firstOctet = firstOctet;
this.state = TlvStructureDecoder.READ_LENGTH_BYTES;
}
}
else if (this.state == TlvStructureDecoder.READ_LENGTH_BYTES) {
var nRemainingBytes = input.length - this.offset;
if (!this.useHeaderBuffer && nRemainingBytes >= this.nBytesToRead) {
// We don't have to use the headerBuffer. Set nBytesToRead.
decoder.seek(this.offset);
this.nBytesToRead = decoder.readExtendedVarNumber(this.firstOctet);
// Update this.offset to the decoder's offset after reading.
this.offset = decoder.getOffset();
}
else {
this.useHeaderBuffer = true;
var nNeededBytes = this.nBytesToRead - this.headerLength;
if (nNeededBytes > nRemainingBytes) {
// We can't get all of the header bytes from this input.
// Save in headerBuffer.
if (this.headerLength + nRemainingBytes > this.headerBuffer.length)
// We don't expect this to happen.
throw new Error
("Cannot store more header bytes than the size of headerBuffer");
input.slice(this.offset, this.offset + nRemainingBytes).copy
(this.headerBuffer, this.headerLength);
this.offset += nRemainingBytes;
this.headerLength += nRemainingBytes;
return false;
}
// Copy the remaining bytes into headerBuffer, read the
// length and set nBytesToRead.
if (this.headerLength + nNeededBytes > this.headerBuffer.length)
// We don't expect this to happen.
throw new Error
("Cannot store more header bytes than the size of headerBuffer");
input.slice(this.offset, this.offset + nNeededBytes).copy
(this.headerBuffer, this.headerLength);
this.offset += nNeededBytes;
// Use a local decoder just for the headerBuffer.
var bufferDecoder = new TlvDecoder(this.headerBuffer);
// Replace nBytesToRead with the length of the value.
this.nBytesToRead = bufferDecoder.readExtendedVarNumber(this.firstOctet);
}
if (this.nBytesToRead == 0) {
// No value bytes to read. We're finished.
this.gotElementEnd = true;
return true;
}
// Get ready to read the value bytes.
this.state = TlvStructureDecoder.READ_VALUE_BYTES;
}
else if (this.state == TlvStructureDecoder.READ_VALUE_BYTES) {
nRemainingBytes = input.length - this.offset;
if (nRemainingBytes < this.nBytesToRead) {
// Need more.
this.offset += nRemainingBytes;
this.nBytesToRead -= nRemainingBytes;
return false;
}
// Got the bytes. We're finished.
this.offset += this.nBytesToRead;
this.gotElementEnd = true;
return true;
}
else
// We don't expect this to happen.
throw new Error("findElementEnd: unrecognized state");
}
};
/**
* Get the current offset into the input buffer.
* @returns {number} The offset.
*/
TlvStructureDecoder.prototype.getOffset = function()
{
return this.offset;
};
/**
* Set the offset into the input, used for the next read.
* @param {number} offset The new offset.
*/
TlvStructureDecoder.prototype.seek = function(offset)
{
this.offset = offset;
};
},{"../../buffer.js":25,"./tlv-decoder.js":38}],41:[function(require,module,exports){
/**
* Copyright (C) 2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
/**
* The Tlv class has static type codes for the NDN-TLV wire format.
* @constructor
*/
var Tlv = function Tlv()
{
}
exports.Tlv = Tlv;
Tlv.Interest = 5;
Tlv.Data = 6;
Tlv.Name = 7;
Tlv.NameComponent = 8;
Tlv.Selectors = 9;
Tlv.Nonce = 10;
Tlv.Scope = 11;
Tlv.InterestLifetime = 12;
Tlv.MinSuffixComponents = 13;
Tlv.MaxSuffixComponents = 14;
Tlv.PublisherPublicKeyLocator = 15;
Tlv.Exclude = 16;
Tlv.ChildSelector = 17;
Tlv.MustBeFresh = 18;
Tlv.Any = 19;
Tlv.MetaInfo = 20;
Tlv.Content = 21;
Tlv.SignatureInfo = 22;
Tlv.SignatureValue = 23;
Tlv.ContentType = 24;
Tlv.FreshnessPeriod = 25;
Tlv.FinalBlockId = 26;
Tlv.SignatureType = 27;
Tlv.KeyLocator = 28;
Tlv.KeyLocatorDigest = 29;
Tlv.FaceInstance = 128;
Tlv.ForwardingEntry = 129;
Tlv.StatusResponse = 130;
Tlv.Action = 131;
Tlv.FaceID = 132;
Tlv.IPProto = 133;
Tlv.Host = 134;
Tlv.Port = 135;
Tlv.MulticastInterface = 136;
Tlv.MulticastTTL = 137;
Tlv.ForwardingFlags = 138;
Tlv.StatusCode = 139;
Tlv.StatusText = 140;
Tlv.SignatureType_DigestSha256 = 0;
Tlv.SignatureType_SignatureSha256WithRsa = 1;
},{}],42:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
* This class represents Interest Objects
*/
var customBuf = require('../buffer.js').Buffer
/**
* Create a WireFormat base class where the encode and decode methods throw an error. You should use a derived class like TlvWireFormat.
* @constructor
*/
var WireFormat = function WireFormat() {
};
exports.WireFormat = WireFormat;
/**
* Encode interest and return the encoding. Your derived class should override.
* @param {Interest} interest The Interest to encode.
* @returns {Blob} A Blob containing the encoding.
* @throws Error This always throws an "unimplemented" error. The derived class should override.
*/
WireFormat.prototype.encodeInterest = function(interest)
{
throw new Error("encodeInterest is unimplemented in the base WireFormat class. You should use a derived class.");
};
/**
* Decode input as an interest and set the fields of the interest object.
* Your derived class should override.
* @param {Interest} interest The Interest object whose fields are updated.
* @param {Buffer} input The buffer with the bytes to decode.
* @throws Error This always throws an "unimplemented" error. The derived class should override.
*/
WireFormat.prototype.decodeInterest = function(interest, input)
{
throw new Error("decodeInterest is unimplemented in the base WireFormat class. You should use a derived class.");
};
/**
* Encode data and return the encoding and signed offsets. Your derived class
* should override.
* @param {Data} data The Data object to encode.
* @returns {object with (Blob, int, int)} An associative array with fields
* (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
* is a Blob containing the encoding, signedPortionBeginOffset is the offset in
* the encoding of the beginning of the signed portion, and
* signedPortionEndOffset is the offset in the encoding of the end of the
* signed portion.
* @throws Error This always throws an "unimplemented" error. The derived class should override.
*/
WireFormat.prototype.encodeData = function(data)
{
throw new Error("encodeData is unimplemented in the base WireFormat class. You should use a derived class.");
};
/**
* Decode input as a data packet, set the fields in the data object, and return
* the signed offsets. Your derived class should override.
* @param {Data} data The Data object whose fields are updated.
* @param {Buffer} input The buffer with the bytes to decode.
* @returns {object with (int, int)} An associative array with fields
* (signedPortionBeginOffset, signedPortionEndOffset) where
* signedPortionBeginOffset is the offset in the encoding of the beginning of
* the signed portion, and signedPortionEndOffset is the offset in the encoding
* of the end of the signed portion.
* @throws Error This always throws an "unimplemented" error. The derived class should override.
*/
WireFormat.prototype.decodeData = function(data, input)
{
throw new Error("decodeData is unimplemented in the base WireFormat class. You should use a derived class.");
};
/**
* Set the static default WireFormat used by default encoding and decoding
* methods.
* @param wireFormat {a subclass of WireFormat} An object of a subclass of
* WireFormat.
*/
WireFormat.setDefaultWireFormat = function(wireFormat)
{
WireFormat.defaultWireFormat = wireFormat;
};
/**
* Return the default WireFormat used by default encoding and decoding methods
* which was set with setDefaultWireFormat.
* @returns {a subclass of WireFormat} The WireFormat object.
*/
WireFormat.getDefaultWireFormat = function()
{
return WireFormat.defaultWireFormat;
};
// Invoke TlvWireFormat to set the default format.
// Since tlv-wire-format.js includes this file, put this at the bottom
// to avoid problems with cycles of require.
var TlvWireFormat = require('./tlv-wire-format.js').TlvWireFormat;
},{"../buffer.js":25,"./tlv-wire-format.js":37}],43:[function(require,module,exports){
/**
* Copyright (C) 2014 Regents of the University of California.
* @author: Meki Cheraoui
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
* This class represents an Interest Exclude.
*/
var customBuf = require('./buffer.js').Buffer
var Name = require('./name.js').Name;
var NDNProtocolDTags = require('./util/ndn-protoco-id-tags.js').NDNProtocolDTags;
var BinaryXMLEncoder = require('./encoding/binary-xml-encoder.js').BinaryXMLEncoder;
var BinaryXMLDecoder = require('./encoding/binary-xml-decoder.js').BinaryXMLDecoder;
var DataUtils = require('./encoding/data-utils.js').DataUtils;
/**
* Create a new Exclude.
* @constructor
* @param {Array<Name.Component|Buffer|Exclude.ANY>} values (optional) An array where each element is either a Name.Component, customBuf component or Exclude.ANY.
*/
var Exclude = function Exclude(values)
{
this.values = [];
if (typeof values === 'object' && values instanceof Exclude)
// Copy the exclude.
this.values = values.values.slice(0);
else if (values) {
for (var i = 0; i < values.length; ++i) {
if (values[i] == Exclude.ANY)
this.appendAny();
else
this.appendComponent(values[i]);
}
}
};
exports.Exclude = Exclude;
Exclude.ANY = "*";
/**
* Get the number of entries.
* @returns {number} The number of entries.
*/
Exclude.prototype.size = function() { return this.values.length; };
/**
* Get the entry at the given index.
* @param {number} i The index of the entry, starting from 0.
* @returns {Exclude.ANY|Name.Component} Exclude.ANY or a Name.Component.
*/
Exclude.prototype.get = function(i) { return this.values[i]; };
/**
* Append an Exclude.ANY element.
* @returns This Exclude so that you can chain calls to append.
*/
Exclude.prototype.appendAny = function()
{
this.values.push(Exclude.ANY);
return this;
};
/**
* Append a component entry, copying from component.
* @param {Name.Component|Buffer} component
* @returns This Exclude so that you can chain calls to append.
*/
Exclude.prototype.appendComponent = function(component)
{
this.values.push(new Name.Component(component));
return this;
};
/**
* Clear all the entries.
*/
Exclude.prototype.clear = function()
{
this.values = [];
};
Exclude.prototype.from_ndnb = function(/*XMLDecoder*/ decoder)
{
decoder.readElementStartDTag(NDNProtocolDTags.Exclude);
while (true) {
if (decoder.peekDTag(NDNProtocolDTags.Component))
this.appendComponent(decoder.readBinaryDTagElement(NDNProtocolDTags.Component));
else if (decoder.peekDTag(NDNProtocolDTags.Any)) {
decoder.readElementStartDTag(NDNProtocolDTags.Any);
decoder.readElementClose();
this.appendAny();
}
else if (decoder.peekDTag(NDNProtocolDTags.Bloom)) {
// Skip the Bloom and treat it as Any.
decoder.readBinaryDTagElement(NDNProtocolDTags.Bloom);
this.appendAny();
}
else
break;
}
decoder.readElementClose();
};
Exclude.prototype.to_ndnb = function(/*XMLEncoder*/ encoder)
{
if (this.values == null || this.values.length == 0)
return;
encoder.writeElementStartDTag(NDNProtocolDTags.Exclude);
// TODO: Do we want to order the components (except for ANY)?
for (var i = 0; i < this.values.length; ++i) {
if (this.values[i] == Exclude.ANY) {
encoder.writeElementStartDTag(NDNProtocolDTags.Any);
encoder.writeElementClose();
}
else
encoder.writeDTagElement(NDNProtocolDTags.Component, this.values[i].getValue());
}
encoder.writeElementClose();
};
/**
* Return a string with elements separated by "," and Exclude.ANY shown as "*".
*/
Exclude.prototype.toUri = function()
{
if (this.values == null || this.values.length == 0)
return "";
var result = "";
for (var i = 0; i < this.values.length; ++i) {
if (i > 0)
result += ",";
if (this.values[i] == Exclude.ANY)
result += "*";
else
result += Name.toEscapedString(this.values[i].getValue());
}
return result;
};
/**
* Return true if the component matches any of the exclude criteria.
*/
Exclude.prototype.matches = function(/*Buffer*/ component)
{
if (typeof component == 'object' && component instanceof Name.Component)
component = component.getValue();
for (var i = 0; i < this.values.length; ++i) {
if (this.values[i] == Exclude.ANY) {
var lowerBound = null;
if (i > 0)
lowerBound = this.values[i - 1];
// Find the upper bound, possibly skipping over multiple ANY in a row.
var iUpperBound;
var upperBound = null;
for (iUpperBound = i + 1; iUpperBound < this.values.length; ++iUpperBound) {
if (this.values[iUpperBound] != Exclude.ANY) {
upperBound = this.values[iUpperBound];
break;
}
}
// If lowerBound != null, we already checked component equals lowerBound on the last pass.
// If upperBound != null, we will check component equals upperBound on the next pass.
if (upperBound != null) {
if (lowerBound != null) {
if (Exclude.compareComponents(component, lowerBound) > 0 &&
Exclude.compareComponents(component, upperBound) < 0)
return true;
}
else {
if (Exclude.compareComponents(component, upperBound) < 0)
return true;
}
// Make i equal iUpperBound on the next pass.
i = iUpperBound - 1;
}
else {
if (lowerBound != null) {
if (Exclude.compareComponents(component, lowerBound) > 0)
return true;
}
else
// this.values has only ANY.
return true;
}
}
else {
if (DataUtils.arraysEqual(component, this.values[i].getValue()))
return true;
}
}
return false;
};
/**
* Return -1 if component1 is less than component2, 1 if greater or 0 if equal.
* A component is less if it is shorter, otherwise if equal length do a byte comparison.
*/
Exclude.compareComponents = function(component1, component2)
{
if (typeof component1 == 'object' && component1 instanceof Name.Component)
component1 = component1.getValue();
if (typeof component2 == 'object' && component2 instanceof Name.Component)
component2 = component2.getValue();
if (component1.length < component2.length)
return -1;
if (component1.length > component2.length)
return 1;
for (var i = 0; i < component1.length; ++i) {
if (component1[i] < component2[i])
return -1;
if (component1[i] > component2[i])
return 1;
}
return 0;
};
},{"./buffer.js":25,"./encoding/binary-xml-decoder.js":28,"./encoding/binary-xml-encoder.js":29,"./encoding/data-utils.js":32,"./name.js":53,"./util/ndn-protoco-id-tags.js":62}],44:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Meki Cheraoui
* See COPYING for copyright and distribution information.
* This class represents Face Instances
*/
var NDNProtocolDTags = require('./util/ndn-protoco-id-tags.js').NDNProtocolDTags;
var PublisherPublicKeyDigest = require('./publisher-public-key-digest.js').PublisherPublicKeyDigest;
/**
* @constructor
*/
var FaceInstance = function FaceInstance(action, publisherPublicKeyDigest, faceID, ipProto, host, port, multicastInterface,
multicastTTL, freshnessSeconds)
{
this.action = action;
this.publisherPublicKeyDigest = publisherPublicKeyDigest;
this.faceID = faceID;
this.ipProto = ipProto;
this.host = host;
this.Port = port;
this.multicastInterface =multicastInterface;
this.multicastTTL =multicastTTL;
this.freshnessSeconds = freshnessSeconds;
};
exports.FaceInstance = FaceInstance;
FaceInstance.NetworkProtocol = { TCP:6, UDP:17};
/**
* Used by NetworkObject to decode the object from a network stream.
*/
FaceInstance.prototype.from_ndnb = function(
//XMLDecoder
decoder)
{
decoder.readElementStartDTag(this.getElementLabel());
if (decoder.peekDTag(NDNProtocolDTags.Action))
this.action = decoder.readUTF8DTagElement(NDNProtocolDTags.Action);
if (decoder.peekDTag(NDNProtocolDTags.PublisherPublicKeyDigest)) {
this.publisherPublicKeyDigest = new PublisherPublicKeyDigest();
this.publisherPublicKeyDigest.from_ndnb(decoder);
}
if (decoder.peekDTag(NDNProtocolDTags.FaceID))
this.faceID = decoder.readIntegerDTagElement(NDNProtocolDTags.FaceID);
if (decoder.peekDTag(NDNProtocolDTags.IPProto)) {
//int
var pI = decoder.readIntegerDTagElement(NDNProtocolDTags.IPProto);
this.ipProto = null;
if (FaceInstance.NetworkProtocol.TCP == pI)
this.ipProto = FaceInstance.NetworkProtocol.TCP;
else if (FaceInstance.NetworkProtocol.UDP == pI)
this.ipProto = FaceInstance.NetworkProtocol.UDP;
else
throw new Error("FaceInstance.decoder. Invalid NDNProtocolDTags.IPProto field: " + pI);
}
if (decoder.peekDTag(NDNProtocolDTags.Host))
this.host = decoder.readUTF8DTagElement(NDNProtocolDTags.Host);
if (decoder.peekDTag(NDNProtocolDTags.Port))
this.Port = decoder.readIntegerDTagElement(NDNProtocolDTags.Port);
if (decoder.peekDTag(NDNProtocolDTags.MulticastInterface))
this.multicastInterface = decoder.readUTF8DTagElement(NDNProtocolDTags.MulticastInterface);
if (decoder.peekDTag(NDNProtocolDTags.MulticastTTL))
this.multicastTTL = decoder.readIntegerDTagElement(NDNProtocolDTags.MulticastTTL);
if (decoder.peekDTag(NDNProtocolDTags.FreshnessSeconds))
this.freshnessSeconds = decoder.readIntegerDTagElement(NDNProtocolDTags.FreshnessSeconds);
decoder.readElementClose();
};
/**
* Used by NetworkObject to encode the object to a network stream.
*/
FaceInstance.prototype.to_ndnb = function(
//XMLEncoder
encoder)
{
encoder.writeElementStartDTag(this.getElementLabel());
if (null != this.action && this.action.length != 0)
encoder.writeDTagElement(NDNProtocolDTags.Action, this.action);
if (null != this.publisherPublicKeyDigest)
this.publisherPublicKeyDigest.to_ndnb(encoder);
if (null != this.faceID)
encoder.writeDTagElement(NDNProtocolDTags.FaceID, this.faceID);
if (null != this.ipProto)
encoder.writeDTagElement(NDNProtocolDTags.IPProto, this.ipProto);
if (null != this.host && this.host.length != 0)
encoder.writeDTagElement(NDNProtocolDTags.Host, this.host);
if (null != this.Port)
encoder.writeDTagElement(NDNProtocolDTags.Port, this.Port);
if (null != this.multicastInterface && this.multicastInterface.length != 0)
encoder.writeDTagElement(NDNProtocolDTags.MulticastInterface, this.multicastInterface);
if (null != this.multicastTTL)
encoder.writeDTagElement(NDNProtocolDTags.MulticastTTL, this.multicastTTL);
if (null != this.freshnessSeconds)
encoder.writeDTagElement(NDNProtocolDTags.FreshnessSeconds, this.freshnessSeconds);
encoder.writeElementClose();
};
FaceInstance.prototype.getElementLabel = function()
{
return NDNProtocolDTags.FaceInstance;
};
},{"./publisher-public-key-digest.js":55,"./util/ndn-protoco-id-tags.js":62}],45:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Meki Cherkaoui, Jeff Thompson <jefft0@remap.ucla.edu>, Wentao Shang
* See COPYING for copyright and distribution information.
* This class represents the top-level object for communicating with an NDN host.
*/
var customBuf = require('./buffer.js').Buffer
var crypto = require('./crypto.js');
var DataUtils = require('./encoding/data-utils.js').DataUtils;
var Name = require('./name.js').Name;
var Interest = require('./interest.js').Interest;
var Data = require('./data.js').Data;
var MetaInfo = require('./meta-info.js').MetaInfo;
var ForwardingEntry = require('./forwarding-entry.js').ForwardingEntry;
var TlvWireFormat = require('./encoding/tlv-wire-format.js').TlvWireFormat;
var BinaryXmlWireFormat = require('./encoding/binary-xml-wire-format.js').BinaryXmlWireFormat;
var Tlv = require('./encoding/tlv/tlv.js').Tlv;
var TlvDecoder = require('./encoding/tlv/tlv-decoder.js').TlvDecoder;
var BinaryXMLDecoder = require('./encoding/binary-xml-decoder.js').BinaryXMLDecoder;
var BinaryXMLEncoder = require('./encoding/binary-xml-encoder.js').BinaryXMLEncoder;
var NDNProtocolDTags = require('./util/ndn-protoco-id-tags.js').NDNProtocolDTags;
var Key = require('./key.js').Key;
var KeyLocatorType = require('./key-locator.js').KeyLocatorType;
var ForwardingFlags = require('./forwarding-flags.js').ForwardingFlags;
var Closure = require('./closure.js').Closure;
var UpcallInfo = require('./closure.js').UpcallInfo;
var TcpTransport = require('./transport/tcp-transport.js').TcpTransport;
var LOG = require('./log.js').Log.LOG;
/**
* Create a new Face with the given settings.
* This throws an exception if Face.supported is false.
* @constructor
* @param {Object} settings if not null, an associative array with the following defaults:
* {
* getTransport: function() { return new WebSocketTransport(); }, // If in the browser.
* OR function() { return new TcpTransport(); }, // If in Node.js.
* getHostAndPort: transport.defaultGetHostAndPort, // a function, on each call it returns a new { host: host, port: port } or null if there are no more hosts.
* host: null, // If null, use getHostAndPort when connecting.
* port: 9696, // If in the browser.
* OR 6363, // If in Node.js.
* onopen: function() { if (LOG > 3) console.log("NDN connection established."); },
* onclose: function() { if (LOG > 3) console.log("NDN connection closed."); },
* verify: false // If false, don't verify and call upcall with Closure.UPCALL_CONTENT_UNVERIFIED.
* }
*/
var Face = function Face(settings)
{
if (!Face.supported)
throw new Error("The necessary JavaScript support is not available on this platform.");
settings = (settings || {});
// For the browser, browserify-tcp-transport.js replaces TcpTransport with WebSocketTransport.
var getTransport = (settings.getTransport || function() { return new TcpTransport(); });
this.transport = getTransport();
this.getHostAndPort = (settings.getHostAndPort || this.transport.defaultGetHostAndPort);
this.host = (settings.host !== undefined ? settings.host : null);
this.port = (settings.port || (typeof WebSocketTransport != 'undefined' ? 9696 : 6363));
this.readyStatus = Face.UNOPEN;
this.verify = (settings.verify !== undefined ? settings.verify : false);
// Event handler
this.onopen = (settings.onopen || function() { if (LOG > 3) console.log("Face connection established."); });
this.onclose = (settings.onclose || function() { if (LOG > 3) console.log("Face connection closed."); });
this.ndndid = null;
};
exports.Face = Face;
Face.UNOPEN = 0; // created but not opened yet
Face.OPENED = 1; // connection to ndnd opened
Face.CLOSED = 2; // connection to ndnd closed
/**
* Return true if necessary JavaScript support is available, else log an error and return false.
*/
Face.getSupported = function()
{
try {
var dummy = new customBuf(1).slice(0, 1);
}
catch (ex) {
console.log("NDN not available: customBuf not supported. " + ex);
return false;
}
return true;
};
Face.supported = Face.getSupported();
Face.ndndIdFetcher = new Name('/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY');
Face.prototype.createRoute = function(host, port)
{
this.host=host;
this.port=port;
};
Face.KeyStore = new Array();
var KeyStoreEntry = function KeyStoreEntry(name, rsa, time)
{
this.keyName = name; // KeyName
this.rsaKey = rsa; // RSA key
this.timeStamp = time; // Time Stamp
};
Face.addKeyEntry = function(/* KeyStoreEntry */ keyEntry)
{
var result = Face.getKeyByName(keyEntry.keyName);
if (result == null)
Face.KeyStore.push(keyEntry);
else
result = keyEntry;
};
Face.getKeyByName = function(/* KeyName */ name)
{
var result = null;
for (var i = 0; i < Face.KeyStore.length; i++) {
if (Face.KeyStore[i].keyName.contentName.match(name.contentName)) {
if (result == null || Face.KeyStore[i].keyName.contentName.components.length > result.keyName.contentName.components.length)
result = Face.KeyStore[i];
}
}
return result;
};
Face.prototype.close = function()
{
if (this.readyStatus != Face.OPENED)
throw new Error('Cannot close because Face connection is not opened.');
this.readyStatus = Face.CLOSED;
this.transport.close();
};
// For fetching data
Face.PITTable = new Array();
/**
* @constructor
*/
var PITEntry = function PITEntry(interest, closure)
{
this.interest = interest; // Interest
this.closure = closure; // Closure
this.timerID = -1; // Timer ID
};
/**
* Return the entry from Face.PITTable where the name conforms to the interest selectors, and
* the interest name is the longest that matches name.
*/
/**
* Find all entries from Face.PITTable where the name conforms to the entry's
* interest selectors, remove the entries from the table, cancel their timeout
* timers and return them.
* @param {Name} name The name to find the interest for (from the incoming data
* packet).
* @returns {Array<PITEntry>} The matching entries from Face.PITTable, or [] if
* none are found.
*/
Face.extractEntriesForExpressedInterest = function(name)
{
var result = [];
// Go backwards through the list so we can erase entries.
for (var i = Face.PITTable.length - 1; i >= 0; --i) {
var entry = Face.PITTable[i];
if (entry.interest.matchesName(name)) {
// Cancel the timeout timer.
clearTimeout(entry.timerID);
result.push(entry);
Face.PITTable.splice(i, 1);
}
}
return result;
};
// For publishing data
Face.registeredPrefixTable = new Array();
/**
* @constructor
*/
var RegisteredPrefix = function RegisteredPrefix(prefix, closure)
{
this.prefix = prefix; // String
this.closure = closure; // Closure
};
/**
* Find the first entry from Face.registeredPrefixTable where the entry prefix is the longest that matches name.
* @param {Name} name The name to find the PrefixEntry for (from the incoming interest packet).
* @returns {object} The entry from Face.registeredPrefixTable, or 0 if not found.
*/
function getEntryForRegisteredPrefix(name)
{
var iResult = -1;
for (var i = 0; i < Face.registeredPrefixTable.length; i++) {
if (LOG > 3) console.log("Registered prefix " + i + ": checking if " , Face.registeredPrefixTable[i].prefix , " matches " , name);
if (Face.registeredPrefixTable[i].prefix.match(name)) {
if (iResult < 0 ||
Face.registeredPrefixTable[i].prefix.size() > Face.registeredPrefixTable[iResult].prefix.size())
// Update to the longer match.
iResult = i;
}
}
if (iResult >= 0)
return Face.registeredPrefixTable[iResult];
else
return null;
}
/**
* Return a function that selects a host at random from hostList and returns { host: host, port: port }.
* If no more hosts remain, return null.
*/
Face.makeShuffledGetHostAndPort = function(hostList, port)
{
// Make a copy.
hostList = hostList.slice(0, hostList.length);
DataUtils.shuffle(hostList);
return function() {
if (hostList.length == 0)
return null;
return { host: hostList.splice(0, 1)[0], port: port };
};
};
/**
* Send the interest through the transport, read the entire response and call onData.
* If the interest times out according to interest lifetime, call onTimeout (if not omitted).
* There are two forms of expressInterest. The first form takes the exact interest (including lifetime):
* expressInterest(interest, onData [, onTimeout]). The second form creates the interest from
* a name and optional interest template:
* expressInterest(name [, template], onData [, onTimeout]).
* This also supports the deprecated form expressInterest(name, closure [, template]), but you should use the other forms.
* @param {Interest} interest The Interest to send which includes the interest lifetime for the timeout.
* @param {function} onData When a matching data packet is received, this calls onData(interest, data) where:
* interest is the interest given to expressInterest,
* data is the received Data object.
* @param {function} onTimeout (optional) If the interest times out according to the interest lifetime,
* this calls onTimeout(interest) where:
* interest is the interest given to expressInterest.
* @param {Name} name The Name for the interest. (only used for the second form of expressInterest).
* @param {Interest} template (optional) If not omitted, copy the interest selectors from this Interest.
* If omitted, use a default interest lifetime. (only used for the second form of expressInterest).
*/
Face.prototype.expressInterest = function(interestOrName, arg2, arg3, arg4)
{
// There are several overloaded versions of expressInterest, each shown inline below.
// expressInterest(Name name, Closure closure); // deprecated
// expressInterest(Name name, Closure closure, Interest template); // deprecated
if (arg2 && arg2.upcall && typeof arg2.upcall == 'function') {
// Assume arg2 is the deprecated use with Closure.
// The first argument is a name. Make the interest from the name and possible template.
interest = new Interest(interestOrName);
if (arg3) {
var template = arg3;
interest.minSuffixComponents = template.minSuffixComponents;
interest.maxSuffixComponents = template.maxSuffixComponents;
interest.publisherPublicKeyDigest = template.publisherPublicKeyDigest;
interest.exclude = template.exclude;
interest.childSelector = template.childSelector;
interest.answerOriginKind = template.answerOriginKind;
interest.scope = template.scope;
interest.interestLifetime = template.interestLifetime;
}
else
interest.interestLifetime = 4000; // default interest timeout value in milliseconds.
this.expressInterestWithClosure(interest, arg2);
return;
}
var interest;
var onData;
var onTimeout;
// expressInterest(Interest interest, function onData);
// expressInterest(Interest interest, function onData, function onTimeout);
if (typeof interestOrName == 'object' && interestOrName instanceof Interest) {
// Just use a copy of the interest.
interest = new Interest(interestOrName);
onData = arg2;
onTimeout = (arg3 ? arg3 : function() {});
}
else {
// The first argument is a name. Make the interest from the name and possible template.
interest = new Interest(interestOrName);
// expressInterest(Name name, Interest template, function onData);
// expressInterest(Name name, Interest template, function onData, function onTimeout);
if (arg2 && typeof arg2 == 'object' && arg2 instanceof Interest) {
var template = arg2;
interest.minSuffixComponents = template.minSuffixComponents;
interest.maxSuffixComponents = template.maxSuffixComponents;
interest.publisherPublicKeyDigest = template.publisherPublicKeyDigest;
interest.exclude = template.exclude;
interest.childSelector = template.childSelector;
interest.answerOriginKind = template.answerOriginKind;
interest.scope = template.scope;
interest.interestLifetime = template.interestLifetime;
onData = arg3;
onTimeout = (arg4 ? arg4 : function() {});
}
// expressInterest(Name name, function onData);
// expressInterest(Name name, function onData, function onTimeout);
else {
interest.interestLifetime = 4000; // default interest timeout value in milliseconds.
onData = arg2;
onTimeout = (arg3 ? arg3 : function() {});
}
}
// Make a Closure from the callbacks so we can use expressInterestWithClosure.
// TODO: Convert the PIT to use callbacks, not a closure.
this.expressInterestWithClosure(interest, new Face.CallbackClosure(onData, onTimeout), interest);
}
Face.CallbackClosure = function FaceCallbackClosure(onData, onTimeout, onInterest, prefix, transport) {
// Inherit from Closure.
Closure.call(this);
this.onData = onData;
this.onTimeout = onTimeout;
this.onInterest = onInterest;
this.prefix = prefix;
this.transport = transport;
};
Face.CallbackClosure.prototype.upcall = function(kind, upcallInfo) {
if (kind == Closure.UPCALL_CONTENT || kind == Closure.UPCALL_CONTENT_UNVERIFIED)
this.onData(upcallInfo.interest, upcallInfo.data);
else if (kind == Closure.UPCALL_INTEREST_TIMED_OUT)
this.onTimeout(upcallInfo.interest);
else if (kind == Closure.UPCALL_INTEREST)
// Note: We never return INTEREST_CONSUMED because onInterest will send the result to the transport.
this.onInterest(this.prefix, upcallInfo.interest, this.transport)
return Closure.RESULT_OK;
};
/**
* A private method to send the the interest to host:port, read the entire response and call
* closure.upcall(Closure.UPCALL_CONTENT (or Closure.UPCALL_CONTENT_UNVERIFIED),
* new UpcallInfo(this, interest, 0, data)).
* @deprecated Use expressInterest with callback functions, not Closure.
* @param {Interest} the interest, already processed with a template (if supplied).
* @param {Closure} closure
*/
Face.prototype.expressInterestWithClosure = function(interest, closure)
{
if (this.host == null || this.port == null) {
if (this.getHostAndPort == null)
console.log('ERROR: host OR port NOT SET');
else {
var thisNDN = this;
this.connectAndExecute(function() { thisNDN.reconnectAndExpressInterest(interest, closure); });
}
}
else
this.reconnectAndExpressInterest(interest, closure);
};
/**
* If the host and port are different than the ones in this.transport, then call
* this.transport.connect to change the connection (or connect for the first time).
* Then call expressInterestHelper.
*/
Face.prototype.reconnectAndExpressInterest = function(interest, closure)
{
if (this.transport.connectedHost != this.host || this.transport.connectedPort != this.port) {
var thisNDN = this;
this.transport.connect(thisNDN, function() { thisNDN.expressInterestHelper(interest, closure); });
this.readyStatus = Face.OPENED;
}
else
this.expressInterestHelper(interest, closure);
};
/**
* Do the work of reconnectAndExpressInterest once we know we are connected. Set the PITTable and call
* this.transport.send to send the interest.
*/
Face.prototype.expressInterestHelper = function(interest, closure)
{
var binaryInterest = interest.wireEncode();
var thisNDN = this;
//TODO: check local content store first
if (closure != null) {
var pitEntry = new PITEntry(interest, closure);
// TODO: This needs to be a single thread-safe transaction on a global object.
Face.PITTable.push(pitEntry);
closure.pitEntry = pitEntry;
// Set interest timer.
var timeoutMilliseconds = (interest.interestLifetime || 4000);
var timeoutCallback = function() {
if (LOG > 1) console.log("Interest time out: " + interest.name.toUri());
// Remove PIT entry from Face.PITTable, even if we add it again later to re-express
// the interest because we don't want to match it in the mean time.
// TODO: Make this a thread-safe operation on the global PITTable.
var index = Face.PITTable.indexOf(pitEntry);
if (index >= 0)
Face.PITTable.splice(index, 1);
// Raise closure callback
if (closure.upcall(Closure.UPCALL_INTEREST_TIMED_OUT, new UpcallInfo(thisNDN, interest, 0, null)) == Closure.RESULT_REEXPRESS) {
if (LOG > 1) console.log("Re-express interest: " + interest.name.toUri());
pitEntry.timerID = setTimeout(timeoutCallback, timeoutMilliseconds);
Face.PITTable.push(pitEntry);
thisNDN.transport.send(binaryInterest.buf());
}
};
pitEntry.timerID = setTimeout(timeoutCallback, timeoutMilliseconds);
}
this.transport.send(binaryInterest.buf());
};
/**
* Register prefix with the connected NDN hub and call onInterest when a matching interest is received.
* This uses the form:
* registerPrefix(name, onInterest, onRegisterFailed [, flags]).
* This also supports the deprecated form registerPrefix(name, closure [, intFlags]), but you should use the main form.
* @param {Name} prefix The Name prefix.
* @param {function} onInterest When an interest is received which matches the name prefix, this calls
* onInterest(prefix, interest, transport) where:
* prefix is the prefix given to registerPrefix.
* interest is the received interest.
* transport The Transport with the connection which received the interest. You must encode a signed Data packet and send it using transport.send().
* @param {function} onRegisterFailed If failed to retrieve the connected hub's ID or failed to register the prefix,
* this calls onRegisterFailed(prefix) where:
* prefix is the prefix given to registerPrefix.
* @param {ForwardingFlags} flags (optional) The flags for finer control of which interests are forward to the application.
* If omitted, use the default flags defined by the default ForwardingFlags constructor.
*/
Face.prototype.registerPrefix = function(prefix, arg2, arg3, arg4)
{
// There are several overloaded versions of registerPrefix, each shown inline below.
// registerPrefix(Name prefix, Closure closure); // deprecated
// registerPrefix(Name prefix, Closure closure, int flags); // deprecated
if (arg2 && arg2.upcall && typeof arg2.upcall == 'function') {
// Assume arg2 is the deprecated use with Closure.
if (arg3)
this.registerPrefixWithClosure(prefix, arg2, arg3);
else
this.registerPrefixWithClosure(prefix, arg2);
return;
}
// registerPrefix(Name prefix, function onInterest, function onRegisterFailed);
// registerPrefix(Name prefix, function onInterest, function onRegisterFailed, ForwardingFlags flags);
var onInterest = arg2;
var onRegisterFailed = (arg3 ? arg3 : function() {});
var intFlags = (arg4 ? arg4.getForwardingEntryFlags() : new ForwardingFlags().getForwardingEntryFlags());
this.registerPrefixWithClosure(prefix, new Face.CallbackClosure(null, null, onInterest, prefix, this.transport),
intFlags, onRegisterFailed);
}
/**
* A private method to register the prefix with the host, receive the data and call
* closure.upcall(Closure.UPCALL_INTEREST, new UpcallInfo(this, interest, 0, null)).
* @deprecated Use registerPrefix with callback functions, not Closure.
* @param {Name} prefix
* @param {Closure} closure
* @param {number} intFlags
* @param {function} (optional) If called from the non-deprecated registerPrefix, call onRegisterFailed(prefix)
* if registration fails.
*/
Face.prototype.registerPrefixWithClosure = function(prefix, closure, intFlags, onRegisterFailed)
{
intFlags = intFlags | 3;
var thisNDN = this;
var onConnected = function() {
if (thisNDN.ndndid == null) {
// Fetch ndndid first, then register.
var interest = new Interest(Face.ndndIdFetcher);
interest.interestLifetime = 4000; // milliseconds
if (LOG > 3) console.log('Expressing interest for ndndid from ndnd.');
thisNDN.reconnectAndExpressInterest
(interest, new Face.FetchNdndidClosure(thisNDN, prefix, closure, intFlags, onRegisterFailed));
}
else
thisNDN.registerPrefixHelper(prefix, closure, flags, onRegisterFailed);
};
if (this.host == null || this.port == null) {
if (this.getHostAndPort == null)
console.log('ERROR: host OR port NOT SET');
else
this.connectAndExecute(onConnected);
}
else
onConnected();
};
/**
* This is a closure to receive the Data for Face.ndndIdFetcher and call
* registerPrefixHelper(prefix, callerClosure, flags).
*/
Face.FetchNdndidClosure = function FetchNdndidClosure(face, prefix, callerClosure, flags, onRegisterFailed)
{
// Inherit from Closure.
Closure.call(this);
this.face = face;
this.prefix = prefix;
this.callerClosure = callerClosure;
this.flags = flags;
this.onRegisterFailed = onRegisterFailed;
};
Face.FetchNdndidClosure.prototype.upcall = function(kind, upcallInfo)
{
if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
console.log("Timeout while requesting the ndndid. Cannot registerPrefix for " + this.prefix.toUri() + " .");
if (this.onRegisterFailed)
this.onRegisterFailed(this.prefix);
return Closure.RESULT_OK;
}
if (!(kind == Closure.UPCALL_CONTENT ||
kind == Closure.UPCALL_CONTENT_UNVERIFIED))
// The upcall is not for us. Don't expect this to happen.
return Closure.RESULT_ERR;
if (LOG > 3) console.log('Got ndndid from ndnd.');
// Get the digest of the public key in the data packet content.
var hash = require("./crypto.js").createHash('sha256');
hash.update(upcallInfo.data.getContent());
this.face.ndndid = new customBuf(hash.digest());
if (LOG > 3) console.log(this.face.ndndid);
this.face.registerPrefixHelper
(this.prefix, this.callerClosure, this.flags, this.onRegisterFailed);
return Closure.RESULT_OK;
};
/**
* This is a closure to receive the response Data packet from the register
* prefix interest sent to the connected NDN hub. If this gets a bad response
* or a timeout, call onRegisterFailed.
*/
Face.RegisterResponseClosure = function RegisterResponseClosure
(prefix, onRegisterFailed)
{
// Inherit from Closure.
Closure.call(this);
this.prefix = prefix;
this.onRegisterFailed = onRegisterFailed;
};
Face.RegisterResponseClosure.prototype.upcall = function(kind, upcallInfo)
{
if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
if (this.onRegisterFailed)
this.onRegisterFailed(this.prefix);
return Closure.RESULT_OK;
}
if (!(kind == Closure.UPCALL_CONTENT ||
kind == Closure.UPCALL_CONTENT_UNVERIFIED))
// The upcall is not for us. Don't expect this to happen.
return Closure.RESULT_ERR;
var expectedName = new Name("/ndnx/.../selfreg");
// Got a response. Do a quick check of expected name components.
if (upcallInfo.data.getName().size() < 4 ||
!upcallInfo.data.getName().get(0).equals(expectedName.get(0)) ||
!upcallInfo.data.getName().get(2).equals(expectedName.get(2))) {
this.onRegisterFailed(this.prefix);
return;
}
// Otherwise, silently succeed.
return Closure.RESULT_OK;
};
/**
* Do the work of registerPrefix once we know we are connected with a ndndid.
*/
Face.prototype.registerPrefixHelper = function
(prefix, closure, flags, onRegisterFailed)
{
var fe = new ForwardingEntry('selfreg', prefix, null, null, flags, null);
// Always encode as BinaryXml until we support TLV for ForwardingEntry.
var encoder = new BinaryXMLEncoder();
fe.to_ndnb(encoder);
var bytes = encoder.getReducedOstream();
var si = new MetaInfo();
si.setFields();
// Set the name to a random value so that each request is unique.
var data = new Data(new Name().append(require("crypto").randomBytes(4)), si, bytes);
// Always encode as BinaryXml until we support TLV for ForwardingEntry.
data.sign(BinaryXmlWireFormat.get());
var coBinary = data.wireEncode(BinaryXmlWireFormat.get());;
var nodename = this.ndndid;
var interestName = new Name(['ndnx', nodename, 'selfreg', coBinary]);
var interest = new Interest(interestName);
interest.setInterestLifetimeMilliseconds(4000.0);
interest.setScope(1);
if (LOG > 3) console.log('Send Interest registration packet.');
Face.registeredPrefixTable.push(new RegisteredPrefix(prefix, closure));
this.reconnectAndExpressInterest
(interest, new Face.RegisterResponseClosure(prefix, onRegisterFailed));
};
/**
* This is called when an entire binary XML element is received, such as a Data or Interest.
* Look up in the PITTable and call the closure callback.
*/
Face.prototype.onReceivedElement = function(element)
{
if (LOG > 3) console.log('Complete element received. Length ' + element.length + '. Start decoding.');
// First, decode as Interest or Data.
var interest = null;
var data = null;
// The type codes for TLV Interest and Data packets are chosen to not
// conflict with the first byte of a binary XML packet, so we can
// just look at the first byte.
if (element[0] == Tlv.Interest || element[0] == Tlv.Data) {
if (LOG > 3) console.log('Detected Tlv element', element, TlvWireFormat.get())
var decoder = new TlvDecoder(element);
if (decoder.peekType(Tlv.Interest, element.length)) {
interest = new Interest();
interest.wireDecode(element, TlvWireFormat.get());
}
else if (decoder.peekType(Tlv.Data, element.length)) {
data = new Data();
data.wireDecode(element, TlvWireFormat.get());
}
}
else {
if (LOG > 3) console.log('assumed BinaryXML')
// Binary XML.
var decoder = new BinaryXMLDecoder(element);
if (decoder.peekDTag(NDNProtocolDTags.Interest)) {
interest = new Interest();
interest.wireDecode(element, BinaryXmlWireFormat.get());
}
else if (decoder.peekDTag(NDNProtocolDTags.Data)) {
data = new Data();
data.wireDecode(element, BinaryXmlWireFormat.get());
}
}
// Now process as Interest or Data.
if (interest !== null) {
if (LOG > 3) console.log('Interest packet received.');
var entry = getEntryForRegisteredPrefix(interest.name);
if (entry != null) {
if (LOG > 3) console.log("Found registered prefix for " + interest.name.toUri());
var info = new UpcallInfo(this, interest, 0, null);
var ret = entry.closure.upcall(Closure.UPCALL_INTEREST, info);
if (ret == Closure.RESULT_INTEREST_CONSUMED && info.data != null)
this.transport.send(info.data.wireEncode().buf());
}
}
else if (data !== null) {
if (LOG > 3) console.log('Data packet received.');
var pendingInterests = Face.extractEntriesForExpressedInterest(data.name);
// Process each matching PIT entry (if any).
for (var i = 0; i < pendingInterests.length; ++i) {
var pitEntry = pendingInterests[i];
var currentClosure = pitEntry.closure;
if (this.verify == false) {
// Pass content up without verifying the signature
currentClosure.upcall(Closure.UPCALL_CONTENT_UNVERIFIED, new UpcallInfo(this, pitEntry.interest, 0, data));
continue;
}
// Key verification
// Recursive key fetching & verification closure
var KeyFetchClosure = function KeyFetchClosure(content, closure, key, sig, wit) {
this.data = content; // unverified data packet object
this.closure = closure; // closure corresponding to the data
this.keyName = key; // name of current key to be fetched
Closure.call(this);
};
var thisNDN = this;
KeyFetchClosure.prototype.upcall = function(kind, upcallInfo) {
if (kind == Closure.UPCALL_INTEREST_TIMED_OUT) {
console.log("In KeyFetchClosure.upcall: interest time out.");
console.log(this.keyName.contentName.toUri());
}
else if (kind == Closure.UPCALL_CONTENT) {
var rsakey = new Key();
rsakey.readDerPublicKey(upcallInfo.data.content);
var verified = data.verify(rsakey);
var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
this.closure.upcall(flag, new UpcallInfo(thisNDN, null, 0, this.data));
// Store key in cache
var keyEntry = new KeyStoreEntry(keylocator.keyName, rsakey, new Date().getTime());
Face.addKeyEntry(keyEntry);
}
else if (kind == Closure.UPCALL_CONTENT_BAD)
console.log("In KeyFetchClosure.upcall: signature verification failed");
};
if (data.signedInfo && data.signedInfo.locator && data.signature) {
if (LOG > 3) console.log("Key verification...");
var sigHex = DataUtils.toHex(data.signature.signature).toLowerCase();
var wit = null;
if (data.signature.witness != null)
//SWT: deprecate support for Witness decoding and Merkle hash tree verification
currentClosure.upcall(Closure.UPCALL_CONTENT_BAD, new UpcallInfo(this, pitEntry.interest, 0, data));
var keylocator = data.signedInfo.locator;
if (keylocator.type == KeyLocatorType.KEYNAME) {
if (LOG > 3) console.log("KeyLocator contains KEYNAME");
if (keylocator.keyName.contentName.match(data.name)) {
if (LOG > 3) console.log("Content is key itself");
var rsakey = new Key();
rsakey.readDerPublicKey(data.content);
var verified = data.verify(rsakey);
var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
currentClosure.upcall(flag, new UpcallInfo(this, pitEntry.interest, 0, data));
// SWT: We don't need to store key here since the same key will be stored again in the closure.
}
else {
// Check local key store
var keyEntry = Face.getKeyByName(keylocator.keyName);
if (keyEntry) {
// Key found, verify now
if (LOG > 3) console.log("Local key cache hit");
var rsakey = keyEntry.rsaKey;
var verified = data.verify(rsakey);
var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
// Raise callback
currentClosure.upcall(flag, new UpcallInfo(this, pitEntry.interest, 0, data));
}
else {
// Not found, fetch now
if (LOG > 3) console.log("Fetch key according to keylocator");
var nextClosure = new KeyFetchClosure(data, currentClosure, keylocator.keyName, sigHex, wit);
// TODO: Use expressInterest with callbacks, not Closure.
this.expressInterest(keylocator.keyName.contentName.getPrefix(4), nextClosure);
}
}
}
else if (keylocator.type == KeyLocatorType.KEY) {
if (LOG > 3) console.log("Keylocator contains KEY");
var rsakey = new Key();
rsakey.readDerPublicKey(keylocator.publicKey);
var verified = data.verify(rsakey);
var flag = (verified == true) ? Closure.UPCALL_CONTENT : Closure.UPCALL_CONTENT_BAD;
// Raise callback
currentClosure.upcall(Closure.UPCALL_CONTENT, new UpcallInfo(this, pitEntry.interest, 0, data));
// Since KeyLocator does not contain key name for this key,
// we have no way to store it as a key entry in KeyStore.
}
else {
var cert = keylocator.certificate;
console.log("KeyLocator contains CERT");
console.log(cert);
// TODO: verify certificate
}
}
}
}
};
/**
* Assume this.getHostAndPort is not null. This is called when this.host is null or its host
* is not alive. Get a host and port, connect, then execute onConnected().
*/
Face.prototype.connectAndExecute = function(onConnected)
{
var hostAndPort = this.getHostAndPort();
if (hostAndPort == null) {
console.log('ERROR: No more hosts from getHostAndPort');
this.host = null;
return;
}
if (hostAndPort.host == this.host && hostAndPort.port == this.port) {
console.log('ERROR: The host returned by getHostAndPort is not alive: ' + this.host + ":" + this.port);
return;
}
this.host = hostAndPort.host;
this.port = hostAndPort.port;
if (LOG>0) console.log("connectAndExecute: trying host from getHostAndPort: " + this.host);
// Fetch any content.
var interest = new Interest(new Name("/"));
interest.interestLifetime = 4000; // milliseconds
var thisNDN = this;
var timerID = setTimeout(function() {
if (LOG>0) console.log("connectAndExecute: timeout waiting for host " + thisNDN.host);
// Try again.
thisNDN.connectAndExecute(onConnected);
}, 3000);
this.reconnectAndExpressInterest(interest, new Face.ConnectClosure(this, onConnected, timerID));
};
/**
* This is called by the Transport when the connection is closed by the remote host.
*/
Face.prototype.closeByTransport = function()
{
this.readyStatus = Face.CLOSED;
this.onclose();
};
Face.ConnectClosure = function ConnectClosure(face, onConnected, timerID)
{
// Inherit from Closure.
Closure.call(this);
this.face = face;
this.onConnected = onConnected;
this.timerID = timerID;
};
Face.ConnectClosure.prototype.upcall = function(kind, upcallInfo)
{
if (!(kind == Closure.UPCALL_CONTENT ||
kind == Closure.UPCALL_CONTENT_UNVERIFIED))
// The upcall is not for us.
return Closure.RESULT_ERR;
// The host is alive, so cancel the timeout and continue with onConnected().
clearTimeout(this.timerID);
// Call Face.onopen after success
this.face.readyStatus = Face.OPENED;
this.face.onopen();
if (LOG>0) console.log("connectAndExecute: connected to host " + this.face.host);
this.onConnected();
return Closure.RESULT_OK;
};
/**
* @deprecated Use new Face.
*/
var NDN = function NDN(settings)
{
// Call the base constructor.
Face.call(this, settings);
}
// Use dummy functions so that the Face constructor will not try to set its own defaults.
NDN.prototype = new Face({ getTransport: function(){}, getHostAndPort: function(){} });
exports.NDN = NDN;
NDN.supported = Face.supported;
NDN.UNOPEN = Face.UNOPEN;
NDN.OPENED = Face.OPENED;
NDN.CLOSED = Face.CLOSED;
},{"./buffer.js":25,"./closure.js":26,"./crypto.js":25,"./data.js":27,"./encoding/binary-xml-decoder.js":28,"./encoding/binary-xml-encoder.js":29,"./encoding/binary-xml-wire-format.js":31,"./encoding/data-utils.js":32,"./encoding/tlv-wire-format.js":37,"./encoding/tlv/tlv-decoder.js":38,"./encoding/tlv/tlv.js":41,"./forwarding-entry.js":46,"./forwarding-flags.js":47,"./interest.js":48,"./key-locator.js":49,"./key.js":50,"./log.js":51,"./meta-info.js":52,"./name.js":53,"./transport/tcp-transport.js":24,"./util/ndn-protoco-id-tags.js":62,"crypto":5}],46:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Meki Cheraoui
* See COPYING for copyright and distribution information.
* This class represents Forwarding Entries
*/
var NDNProtocolDTags = require('./util/ndn-protoco-id-tags.js').NDNProtocolDTags;
var PublisherPublicKeyDigest = require('./publisher-public-key-digest.js').PublisherPublicKeyDigest;
var Name = require('./name.js').Name;
/**
* Create a new ForwardingEntry with the optional arguments.
* @constructor
* @param {String} action
* @param {Name} prefixName
* @param {PublisherPublicKeyDigest} ndndId
* @param {number} faceID
* @param {number} flags
* @param {number} lifetime in seconds
*/
var ForwardingEntry = function ForwardingEntry(action, prefixName, ndndId, faceID, flags, lifetime)
{
this.action = action;
this.prefixName = prefixName;
this.ndndID = ndndId;
this.faceID = faceID;
this.flags = flags;
this.lifetime = lifetime;
};
exports.ForwardingEntry = ForwardingEntry;
ForwardingEntry.ACTIVE = 1;
ForwardingEntry.CHILD_INHERIT = 2;
ForwardingEntry.ADVERTISE = 4;
ForwardingEntry.LAST = 8;
ForwardingEntry.CAPTURE = 16;
ForwardingEntry.LOCAL = 32;
ForwardingEntry.TAP = 64;
ForwardingEntry.CAPTURE_OK = 128;
ForwardingEntry.prototype.from_ndnb = function(
//XMLDecoder
decoder)
//throws DecodingException
{
decoder.readElementStartDTag(this.getElementLabel());
if (decoder.peekDTag(NDNProtocolDTags.Action))
this.action = decoder.readUTF8DTagElement(NDNProtocolDTags.Action);
if (decoder.peekDTag(NDNProtocolDTags.Name)) {
this.prefixName = new Name();
this.prefixName.from_ndnb(decoder) ;
}
if (decoder.peekDTag(NDNProtocolDTags.PublisherPublicKeyDigest)) {
this.NdndId = new PublisherPublicKeyDigest();
this.NdndId.from_ndnb(decoder);
}
if (decoder.peekDTag(NDNProtocolDTags.FaceID))
this.faceID = decoder.readIntegerDTagElement(NDNProtocolDTags.FaceID);
if (decoder.peekDTag(NDNProtocolDTags.ForwardingFlags))
this.flags = decoder.readIntegerDTagElement(NDNProtocolDTags.ForwardingFlags);
if (decoder.peekDTag(NDNProtocolDTags.FreshnessSeconds))
this.lifetime = decoder.readIntegerDTagElement(NDNProtocolDTags.FreshnessSeconds);
decoder.readElementClose();
};
ForwardingEntry.prototype.to_ndnb = function(
//XMLEncoder
encoder)
{
encoder.writeElementStartDTag(this.getElementLabel());
if (null != this.action && this.action.length != 0)
encoder.writeDTagElement(NDNProtocolDTags.Action, this.action);
if (null != this.prefixName)
this.prefixName.to_ndnb(encoder);
if (null != this.NdndId)
this.NdndId.to_ndnb(encoder);
if (null != this.faceID)
encoder.writeDTagElement(NDNProtocolDTags.FaceID, this.faceID);
if (null != this.flags)
encoder.writeDTagElement(NDNProtocolDTags.ForwardingFlags, this.flags);
if (null != this.lifetime)
encoder.writeDTagElement(NDNProtocolDTags.FreshnessSeconds, this.lifetime);
encoder.writeElementClose();
};
ForwardingEntry.prototype.getElementLabel = function() { return NDNProtocolDTags.ForwardingEntry; }
},{"./name.js":53,"./publisher-public-key-digest.js":55,"./util/ndn-protoco-id-tags.js":62}],47:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
var ForwardingEntry = require('./forwarding-entry.js').ForwardingEntry;
/**
* A ForwardingFlags object holds the flags which specify how the forwarding daemon should forward an interest for
* a registered prefix. We use a separate ForwardingFlags object to retain future compatibility if the daemon forwarding
* bits are changed, amended or deprecated.
* Create a new ForwardingFlags with "active" and "childInherit" set and all other flags cleared.
*/
var ForwardingFlags = function ForwardingFlags()
{
this.active = true;
this.childInherit = true;
this.advertise = false;
this.last = false;
this.capture = false;
this.local = false;
this.tap = false;
this.captureOk = false;
}
exports.ForwardingFlags = ForwardingFlags;
/**
* Get an integer with the bits set according to the flags as used by the ForwardingEntry message.
* @returns {number} An integer with the bits set.
*/
ForwardingFlags.prototype.getForwardingEntryFlags = function()
{
var result = 0;
if (this.active)
result |= ForwardingEntry.ACTIVE;
if (this.childInherit)
result |= ForwardingEntry.CHILD_INHERIT;
if (this.advertise)
result |= ForwardingEntry.ADVERTISE;
if (this.last)
result |= ForwardingEntry.LAST;
if (this.capture)
result |= ForwardingEntry.CAPTURE;
if (this.local)
result |= ForwardingEntry.LOCAL;
if (this.tap)
result |= ForwardingEntry.TAP;
if (this.captureOk)
result |= ForwardingEntry.CAPTURE_OK;
return result;
};
/**
* Set the flags according to the bits in forwardingEntryFlags as used by the ForwardingEntry message.
* @param {number} forwardingEntryFlags An integer with the bits set.
*/
ForwardingFlags.prototype.setForwardingEntryFlags = function(forwardingEntryFlags)
{
this.active = ((forwardingEntryFlags & ForwardingEntry.ACTIVE) != 0);
this.childInherit = ((forwardingEntryFlags & ForwardingEntry.CHILD_INHERIT) != 0);
this.advertise = ((forwardingEntryFlags & ForwardingEntry.ADVERTISE) != 0);
this.last = ((forwardingEntryFlags & ForwardingEntry.LAST) != 0);
this.capture = ((forwardingEntryFlags & ForwardingEntry.CAPTURE) != 0);
this.local = ((forwardingEntryFlags & ForwardingEntry.LOCAL) != 0);
this.tap = ((forwardingEntryFlags & ForwardingEntry.TAP) != 0);
this.captureOk = ((forwardingEntryFlags & ForwardingEntry.CAPTURE_OK) != 0);
};
/**
* Get the value of the "active" flag.
* @returns {Boolean} true if the flag is set, false if it is cleared.
*/
ForwardingFlags.prototype.getActive = function() { return this.active; };
/**
* Get the value of the "childInherit" flag.
* @returns {Boolean} true if the flag is set, false if it is cleared.
*/
ForwardingFlags.prototype.getChildInherit = function() { return this.childInherit; };
/**
* Get the value of the "advertise" flag.
* @returns {Boolean} true if the flag is set, false if it is cleared.
*/
ForwardingFlags.prototype.getAdvertise = function() { return this.advertise; };
/**
* Get the value of the "last" flag.
* @returns {Boolean} true if the flag is set, false if it is cleared.
*/
ForwardingFlags.prototype.getLast = function() { return this.last; };
/**
* Get the value of the "capture" flag.
* @returns {Boolean} true if the flag is set, false if it is cleared.
*/
ForwardingFlags.prototype.getCapture = function() { return this.capture; };
/**
* Get the value of the "local" flag.
* @returns {Boolean} true if the flag is set, false if it is cleared.
*/
ForwardingFlags.prototype.getLocal = function() { return this.local; };
/**
* Get the value of the "tap" flag.
* @returns {Boolean} true if the flag is set, false if it is cleared.
*/
ForwardingFlags.prototype.getTap = function() { return this.tap; };
/**
* Get the value of the "captureOk" flag.
* @returns {Boolean} true if the flag is set, false if it is cleared.
*/
ForwardingFlags.prototype.getCaptureOk = function() { return this.captureOk; };
/**
* Set the value of the "active" flag
* @param {number} value true to set the flag, false to clear it.
*/
ForwardingFlags.prototype.setActive = function(value) { this.active = value; };
/**
* Set the value of the "childInherit" flag
* @param {number} value true to set the flag, false to clear it.
*/
ForwardingFlags.prototype.setChildInherit = function(value) { this.childInherit = value; };
/**
* Set the value of the "advertise" flag
* @param {number} value true to set the flag, false to clear it.
*/
ForwardingFlags.prototype.setAdvertise = function(value) { this.advertise = value; };
/**
* Set the value of the "last" flag
* @param {number} value true to set the flag, false to clear it.
*/
ForwardingFlags.prototype.setLast = function(value) { this.last = value; };
/**
* Set the value of the "capture" flag
* @param {number} value true to set the flag, false to clear it.
*/
ForwardingFlags.prototype.setCapture = function(value) { this.capture = value; };
/**
* Set the value of the "local" flag
* @param {number} value true to set the flag, false to clear it.
*/
ForwardingFlags.prototype.setLocal = function(value) { this.local = value; };
/**
* Set the value of the "tap" flag
* @param {number} value true to set the flag, false to clear it.
*/
ForwardingFlags.prototype.setTap = function(value) { this.tap = value; };
/**
* Set the value of the "captureOk" flag
* @param {number} value true to set the flag, false to clear it.
*/
ForwardingFlags.prototype.setCaptureOk = function(value) { this.captureOk = value; };
},{"./forwarding-entry.js":46}],48:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Meki Cheraoui
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
* This class represents Interest Objects
*/
var Blob = require('./util/blob.js').Blob;
var Name = require('./name.js').Name;
var Exclude = require('./exclude.js').Exclude;
var PublisherPublicKeyDigest = require('./publisher-public-key-digest.js').PublisherPublicKeyDigest;
var KeyLocator = require('./key-locator.js').KeyLocator;
var WireFormat = require('./encoding/wire-format.js').WireFormat;
var customBuf = require('./buffer.js').Buffer
var LOG = require('./log.js').LOG
/**
* Create a new Interest with the optional values.
*
* @constructor
* @param {Name|Interest} nameOrInterest If this is an Interest, copy values from the interest and ignore the
* other arguments. Otherwise this is the optional name for the new Interest.
* @param {number} minSuffixComponents
* @param {number} maxSuffixComponents
* @param {Buffer} publisherPublicKeyDigest
* @param {Exclude} exclude
* @param {number} childSelector
* @param {number} answerOriginKind
* @param {number} scope
* @param {number} interestLifetimeMilliseconds in milliseconds
* @param {Buffer} nonce
*/
var Interest = function Interest
(nameOrInterest, minSuffixComponents, maxSuffixComponents, publisherPublicKeyDigest, exclude,
childSelector, answerOriginKind, scope, interestLifetimeMilliseconds, nonce)
{
if (typeof nameOrInterest === 'object' && nameOrInterest instanceof Interest) {
// Special case: this is a copy constructor. Ignore all but the first argument.
var interest = nameOrInterest;
if (interest.name)
// Copy the name.
this.name = new Name(interest.name);
this.maxSuffixComponents = interest.maxSuffixComponents;
this.minSuffixComponents = interest.minSuffixComponents;
this.publisherPublicKeyDigest = interest.publisherPublicKeyDigest;
this.keyLocator = new KeyLocator(interest.keyLocator);
this.exclude = new Exclude(interest.exclude);
this.childSelector = interest.childSelector;
this.answerOriginKind = interest.answerOriginKind;
this.scope = interest.scope;
this.interestLifetime = interest.interestLifetime;
if (interest.nonce)
// Copy.
this.nonce = new customBuf(interest.nonce);
}
else {
this.name = typeof nameOrInterest === 'object' && nameOrInterest instanceof Name ?
new Name(nameOrInterest) : new Name();
this.maxSuffixComponents = maxSuffixComponents;
this.minSuffixComponents = minSuffixComponents;
this.publisherPublicKeyDigest = publisherPublicKeyDigest;
this.keyLocator = new KeyLocator();
this.exclude = typeof exclude === 'object' && exclude instanceof Exclude ?
new Exclude(exclude) : new Exclude();
this.childSelector = childSelector;
this.answerOriginKind = answerOriginKind;
this.scope = scope;
this.interestLifetime = interestLifetimeMilliseconds;
if (nonce)
// Copy and make sure it is a customBuf.
this.nonce = new customBuf(nonce);
}
};
exports.Interest = Interest;
Interest.RECURSIVE_POSTFIX = "*";
Interest.CHILD_SELECTOR_LEFT = 0;
Interest.CHILD_SELECTOR_RIGHT = 1;
Interest.ANSWER_NO_CONTENT_STORE = 0;
Interest.ANSWER_CONTENT_STORE = 1;
Interest.ANSWER_GENERATED = 2;
Interest.ANSWER_STALE = 4; // Stale answer OK
Interest.MARK_STALE = 16; // Must have scope 0. Michael calls this a "hack"
Interest.DEFAULT_ANSWER_ORIGIN_KIND = Interest.ANSWER_CONTENT_STORE | Interest.ANSWER_GENERATED;
/**
* Return true if this.name.match(name) and the name conforms to the interest selectors.
* @param {Name} name
* @returns {boolean}
*/
Interest.prototype.matchesName = function(/*Name*/ name)
{
if (!this.name.match(name))
return false;
if (this.minSuffixComponents != null &&
// Add 1 for the implicit digest.
!(name.size() + 1 - this.name.size() >= this.minSuffixComponents))
return false;
if (this.maxSuffixComponents != null &&
// Add 1 for the implicit digest.
!(name.size() + 1 - this.name.size() <= this.maxSuffixComponents))
return false;
if (this.exclude != null && name.size() > this.name.size() &&
this.exclude.matches(name.components[this.name.size()]))
return false;
return true;
};
/**
* @deprecated Use matchesName.
*/
Interest.prototype.matches_name = function(/*Name*/ name)
{
return this.matchesName(name);
};
/**
* Return a new Interest with the same fields as this Interest.
*/
Interest.prototype.clone = function()
{
return new Interest
(this.name, this.minSuffixComponents, this.maxSuffixComponents,
this.publisherPublicKeyDigest, this.exclude, this.childSelector, this.answerOriginKind,
this.scope, this.interestLifetime, this.nonce);
};
/**
* Get the interest Name.
* @returns {Name} The name. The name size() may be 0 if not specified.
*/
Interest.prototype.getName = function() { return this.name; };
/**
* Get the min suffix components.
* @returns number} The min suffix components, or null if not specified.
*/
Interest.prototype.getMinSuffixComponents = function()
{
return this.minSuffixComponents;
};
/**
* Get the max suffix components.
* @returns {number} The max suffix components, or null if not specified.
*/
Interest.prototype.getMaxSuffixComponents = function()
{
return this.maxSuffixComponents;
};
/**
* Get the interest key locator.
* @returns {KeyLocator} The key locator. If its getType() is null,
* then the key locator is not specified.
*/
Interest.prototype.getKeyLocator = function()
{
return this.keyLocator;
};
/**
* Get the exclude object.
* @returns {Exclude} The exclude object. If the exclude size() is zero, then
* the exclude is not specified.
*/
Interest.prototype.getExclude = function() { return this.exclude; };
/**
* Get the child selector.
* @returns {number} The child selector, or null if not specified.
*/
Interest.prototype.getChildSelector = function()
{
return this.childSelector;
};
/**
* @deprecated Use getMustBeFresh.
*/
Interest.prototype.getAnswerOriginKind = function()
{
return this.answerOriginKind;
};
/**
* Return true if the content must be fresh.
* @return true if must be fresh, otherwise false.
*/
/**
* Get the must be fresh flag. If not specified, the default is true.
* @returns {boolean} The must be fresh flag.
*/
Interest.prototype.getMustBeFresh = function()
{
if (this.answerOriginKind == null || this.answerOriginKind < 0)
return true;
else
return (this.answerOriginKind & Interest.ANSWER_STALE) == 0;
};
/**
* Return the nonce value from the incoming interest. If you change any of the
* fields in this Interest object, then the nonce value is cleared.
* @returns {Buffer} The nonce, or null if not specified.
*/
Interest.prototype.getNonce = function() { return this.nonce; };
/**
* Get the interest scope.
* @returns {number} The scope, or null if not specified.
*/
Interest.prototype.getScope = function() { return this.scope; };
/**
* Get the interest lifetime.
* @returns {number} The interest lifetime in milliseconds, or null if not
* specified.
*/
Interest.prototype.getInterestLifetimeMilliseconds = function()
{
return this.interestLifetime;
};
Interest.prototype.setName = function(name)
{
// The object has changed, so the nonce is invalid.
this.nonce = null;
this.name = typeof name === 'object' && name instanceof Interest ?
new Name(name) : new Name();
};
Interest.prototype.setMinSuffixComponents = function(minSuffixComponents)
{
// The object has changed, so the nonce is invalid.
this.nonce = null;
this.minSuffixComponents = minSuffixComponents;
};
Interest.prototype.setMaxSuffixComponents = function(maxSuffixComponents)
{
// The object has changed, so the nonce is invalid.
this.nonce = null;
this.maxSuffixComponents = maxSuffixComponents;
};
/**
* Set this interest to use a copy of the given exclude object. Note: You can
* also change this interest's exclude object modifying the object from
* getExclude().
* @param {Exclude} exclude The exlcude object that is copied.
*/
Interest.prototype.setExclude = function(exclude)
{
// The object has changed, so the nonce is invalid.
this.nonce = null;
this.exclude = typeof exclude === 'object' && exclude instanceof Exclude ?
new Exclude(exclude) : new Exclude();
};
Interest.prototype.setChildSelector = function(childSelector)
{
// The object has changed, so the nonce is invalid.
this.nonce = null;
this.childSelector = childSelector;
};
/**
* @deprecated Use setMustBeFresh.
*/
Interest.prototype.setAnswerOriginKind = function(answerOriginKind)
{
// The object has changed, so the nonce is invalid.
this.nonce = null;
this.answerOriginKind = answerOriginKind;
};
/**
* Set the MustBeFresh flag.
* @param {boolean} mustBeFresh True if the content must be fresh, otherwise false.
*/
Interest.prototype.setMustBeFresh = function(mustBeFresh)
{
// The object has changed, so the nonce is invalid.
this.nonce = null;
if (this.answerOriginKind == null || this.answerOriginKind < 0) {
// It is is already the default where MustBeFresh is true.
if (!mustBeFresh)
// Set answerOriginKind_ so that getMustBeFresh returns false.
this.answerOriginKind = Interest.ANSWER_STALE;
}
else {
if (mustBeFresh)
// Clear the stale bit.
this.answerOriginKind &= ~Interest.ANSWER_STALE;
else
// Set the stale bit.
this.answerOriginKind |= Interest.ANSWER_STALE;
}
};
Interest.prototype.setScope = function(scope)
{
// The object has changed, so the nonce is invalid.
this.nonce = null;
this.scope = scope;
};
Interest.prototype.setInterestLifetimeMilliseconds = function(interestLifetimeMilliseconds)
{
// The object has changed, so the nonce is invalid.
this.nonce = null;
this.interestLifetime = interestLifetimeMilliseconds;
};
/**
* @deprecated You should let the wire encoder generate a random nonce
* internally before sending the interest.
*/
Interest.prototype.setNonce = function(nonce)
{
if (nonce)
// Copy and make sure it is a customBuf.
this.nonce = new customBuf(nonce);
else
this.nonce = null;
};
/**
* Encode the name according to the "NDN URI Scheme". If there are interest selectors, append "?" and
* added the selectors as a query string. For example "/test/name?ndn.ChildSelector=1".
* @returns {string} The URI string.
* @note This is an experimental feature. See the API docs for more detail at
* http://named-data.net/doc/ndn-ccl-api/interest.html#interest-touri-method .
*/
Interest.prototype.toUri = function()
{
var selectors = "";
if (this.minSuffixComponents != null)
selectors += "&ndn.MinSuffixComponents=" + this.minSuffixComponents;
if (this.maxSuffixComponents != null)
selectors += "&ndn.MaxSuffixComponents=" + this.maxSuffixComponents;
if (this.childSelector != null)
selectors += "&ndn.ChildSelector=" + this.childSelector;
if (this.answerOriginKind != null)
selectors += "&ndn.AnswerOriginKind=" + this.answerOriginKind;
if (this.scope != null)
selectors += "&ndn.Scope=" + this.scope;
if (this.interestLifetime != null)
selectors += "&ndn.InterestLifetime=" + this.interestLifetime;
if (this.publisherPublicKeyDigest != null)
selectors += "&ndn.PublisherPublicKeyDigest=" + Name.toEscapedString(this.publisherPublicKeyDigest.publisherPublicKeyDigest);
if (this.nonce != null)
selectors += "&ndn.Nonce=" + Name.toEscapedString(this.nonce);
if (this.exclude != null && this.exclude.size() > 0)
selectors += "&ndn.Exclude=" + this.exclude.toUri();
var result = this.name.toUri();
if (selectors != "")
// Replace the first & with ?.
result += "?" + selectors.substr(1);
return result;
};
/**
* Encode this Interest for a particular wire format.
* @param {a subclass of WireFormat} wireFormat (optional) A WireFormat object
* used to encode this object. If omitted, use WireFormat.getDefaultWireFormat().
* @returns {Blob} The encoded buffer in a Blob object.
*/
Interest.prototype.wireEncode = function(wireFormat)
{
wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
return wireFormat.encodeInterest(this);
};
/**
* Decode the input using a particular wire format and update this Interest.
* @param {Buffer} input The buffer with the bytes to decode.
* @param {a subclass of WireFormat} wireFormat (optional) A WireFormat object
* used to decode this object. If omitted, use WireFormat.getDefaultWireFormat().
*/
Interest.prototype.wireDecode = function(input, wireFormat)
{
wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
// If input is a blob, get its buf().
if (LOG > 3 ) console.log('decoding input to interes', input)
var decodeBuffer = typeof input === 'object' && input instanceof Blob ?
input.buf() : input;
wireFormat.decodeInterest(this, decodeBuffer);
};
// Since binary-xml-wire-format.js includes this file, put these at the bottom
// to avoid problems with cycles of require.
var BinaryXmlWireFormat = require('./encoding/binary-xml-wire-format.js').BinaryXmlWireFormat;
/**
* @deprecated Use wireDecode(input, BinaryXmlWireFormat.get()).
*/
Interest.prototype.from_ndnb = function(/*XMLDecoder*/ decoder)
{
BinaryXmlWireFormat.decodeInterest(this, decoder);
};
/**
* @deprecated Use wireEncode(BinaryXmlWireFormat.get()).
*/
Interest.prototype.to_ndnb = function(/*XMLEncoder*/ encoder)
{
BinaryXmlWireFormat.encodeInterest(this, encoder);
};
/**
* @deprecated Use wireEncode. If you need binary XML, use
* wireEncode(BinaryXmlWireFormat.get()).
*/
Interest.prototype.encode = function(wireFormat)
{
return this.wireEncode(BinaryXmlWireFormat.get()).buf();
};
/**
* @deprecated Use wireDecode. If you need binary XML, use
* wireDecode(input, BinaryXmlWireFormat.get()).
*/
Interest.prototype.decode = function(input, wireFormat)
{
this.wireDecode(input, BinaryXmlWireFormat.get())
};
},{"./buffer.js":25,"./encoding/binary-xml-wire-format.js":31,"./encoding/wire-format.js":42,"./exclude.js":43,"./key-locator.js":49,"./log.js":51,"./name.js":53,"./publisher-public-key-digest.js":55,"./util/blob.js":59}],49:[function(require,module,exports){
/**
* Copyright (C) 2014 Regents of the University of California.
* @author: Meki Cheraoui
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
* This class represents an NDN KeyLocator object.
*/
var Name = require('./name.js').Name;
var NDNProtocolDTags = require('./util/ndn-protoco-id-tags.js').NDNProtocolDTags;
var PublisherID = require('./publisher-id.js').PublisherID;
var customBuf = require('./buffer.js').Buffer
var LOG = require('./log.js').Log.LOG;
/**
* KeyLocator
*/
var KeyLocatorType = {
KEYNAME: 1,
KEY_LOCATOR_DIGEST: 2,
KEY: 3,
CERTIFICATE: 4
};
exports.KeyLocatorType = KeyLocatorType;
/**
* @constructor
*/
var KeyLocator = function KeyLocator(input,type)
{
if (typeof input === 'object' && input instanceof KeyLocator) {
// Copy from the input KeyLocator.
this.type = input.type;
this.keyName = new KeyName();
if (input.keyName != null) {
this.keyName.contentName = input.keyName.contentName == null ?
null : new Name(input.keyName.contentName);
this.keyName.publisherID = input.keyName.publisherID;
}
this.keyData = input.keyData == null ? null : new customBuf(input.keyData);
this.publicKey = input.publicKey == null ? null : new customBuf(input.publicKey);
this.certificate = input.certificate == null ? null : new customBuf(input.certificate);
}
else {
this.type = type;
this.keyName = new KeyName();
if (type == KeyLocatorType.KEYNAME)
this.keyName = input;
else if (type == KeyLocatorType.KEY_LOCATOR_DIGEST)
this.keyData = new customBuf(input);
else if (type == KeyLocatorType.KEY) {
this.keyData = new customBuf(input);
// Set for backwards compatibility.
this.publicKey = this.keyData;
}
else if (type == KeyLocatorType.CERTIFICATE) {
this.keyData = new customBuf(input);
// Set for backwards compatibility.
this.certificate = this.keyData;
}
}
};
exports.KeyLocator = KeyLocator;
/**
* Get the key locator type. If KeyLocatorType.KEYNAME, you may also
* getKeyName(). If KeyLocatorType.KEY_LOCATOR_DIGEST, you may also
* getKeyData() to get the digest.
* @returns {number} The key locator type, or null if not specified.
*/
KeyLocator.prototype.getType = function() { return this.type; };
/**
* Get the key name. This is meaningful if getType() is KeyLocatorType.KEYNAME.
* @returns {Name} The key name. If not specified, the Name is empty.
*/
KeyLocator.prototype.getKeyName = function()
{
if (this.keyName == null)
this.keyName = new KeyName();
if (this.keyName.contentName == null)
this.keyName.contentName = new Name();
return this.keyName.contentName;
};
/**
* Get the key data. If getType() is KeyLocatorType.KEY_LOCATOR_DIGEST, this is
* the digest bytes. If getType() is KeyLocatorType.KEY, this is the DER
* encoded public key. If getType() is KeyLocatorType.CERTIFICATE, this is the
* DER encoded certificate.
* @returns {Buffer} The key data, or null if not specified.
*/
KeyLocator.prototype.getKeyData = function()
{
if (this.type == KeyLocatorType.KEY)
return this.publicKey;
else if (this.type == KeyLocatorType.CERTIFICATE)
return this.certificate;
else
return this.keyData;
};
/**
* Set the key locator type. If KeyLocatorType.KEYNAME, you must also
* setKeyName(). If KeyLocatorType.KEY_LOCATOR_DIGEST, you must also
* setKeyData() to the digest.
* @param {number} type The key locator type. If null, the type is unspecified.
*/
KeyLocator.prototype.setType = function(type) { this.type = type; };
/**
* Set key name to a copy of the given Name. This is the name if getType()
* is KeyLocatorType.KEYNAME.
* @param {Name} name The key name which is copied.
*/
KeyLocator.prototype.setKeyName = function(name)
{
if (this.keyName == null)
this.keyName = new KeyName();
this.keyName.contentName = typeof name === 'object' && name instanceof Name ?
new Name(name) : new Name();
};
/**
* Set the key data to the given value. This is the digest bytes if getType() is
* KeyLocatorType.KEY_LOCATOR_DIGEST.
* @param {Buffer} keyData The array with the key data bytes.
*/
KeyLocator.prototype.setKeyData = function(keyData)
{
var value = keyData;
if (value != null)
// Make a copy.
value = new customBuf(value);
this.keyData = value;
// Set for backwards compatibility.
this.publicKey = value;
this.certificate = value;
};
/**
* Clear the keyData and set the type to none.
*/
KeyLocator.prototype.clear = function()
{
this.type = null;
this.keyName = null;
this.keyData = null;
this.publicKey = null;
this.certificate = null;
};
KeyLocator.prototype.from_ndnb = function(decoder) {
decoder.readElementStartDTag(this.getElementLabel());
if (decoder.peekDTag(NDNProtocolDTags.Key))
{
try {
var encodedKey = decoder.readBinaryDTagElement(NDNProtocolDTags.Key);
// This is a DER-encoded SubjectPublicKeyInfo.
//TODO FIX THIS, This should create a Key Object instead of keeping bytes
this.publicKey = encodedKey;//CryptoUtil.getPublicKey(encodedKey);
this.type = KeyLocatorType.KEY;
if (LOG > 4) console.log('PUBLIC KEY FOUND: '+ this.publicKey);
}
catch (e) {
throw new Error("Cannot parse key: ", e);
}
if (null == this.publicKey)
throw new Error("Cannot parse key: ");
}
else if (decoder.peekDTag(NDNProtocolDTags.Certificate)) {
try {
var encodedCert = decoder.readBinaryDTagElement(NDNProtocolDTags.Certificate);
/*
* Certificates not yet working
*/
this.certificate = encodedCert;
this.type = KeyLocatorType.CERTIFICATE;
if (LOG > 4) console.log('CERTIFICATE FOUND: '+ this.certificate);
}
catch (e) {
throw new Error("Cannot decode certificate: " + e);
}
if (null == this.certificate)
throw new Error("Cannot parse certificate! ");
} else {
this.type = KeyLocatorType.KEYNAME;
this.keyName = new KeyName();
this.keyName.from_ndnb(decoder);
}
decoder.readElementClose();
};
KeyLocator.prototype.to_ndnb = function(encoder)
{
if (LOG > 4) console.log('type is is ' + this.type);
if (this.type == KeyLocatorType.KEY_LOCATOR_DIGEST)
// encodeSignedInfo already encoded this as the publisherPublicKeyDigest,
// so do nothing here.
return;
encoder.writeElementStartDTag(this.getElementLabel());
if (this.type == KeyLocatorType.KEY) {
if (LOG > 5) console.log('About to encode a public key' +this.publicKey);
encoder.writeDTagElement(NDNProtocolDTags.Key, this.publicKey);
}
else if (this.type == KeyLocatorType.CERTIFICATE) {
try {
encoder.writeDTagElement(NDNProtocolDTags.Certificate, this.certificate);
}
catch (e) {
throw new Error("CertificateEncodingException attempting to write key locator: " + e);
}
}
else if (this.type == KeyLocatorType.KEYNAME)
this.keyName.to_ndnb(encoder);
encoder.writeElementClose();
};
KeyLocator.prototype.getElementLabel = function()
{
return NDNProtocolDTags.KeyLocator;
};
/**
* KeyName is only used by KeyLocator.
* @constructor
*/
var KeyName = function KeyName()
{
this.contentName = new Name(); //contentName
this.publisherID = this.publisherID; //publisherID
};
exports.KeyName = KeyName;
KeyName.prototype.from_ndnb = function(decoder)
{
decoder.readElementStartDTag(this.getElementLabel());
this.contentName = new Name();
this.contentName.from_ndnb(decoder);
if (LOG > 4) console.log('KEY NAME FOUND: ');
if (PublisherID.peek(decoder)) {
this.publisherID = new PublisherID();
this.publisherID.from_ndnb(decoder);
}
decoder.readElementClose();
};
KeyName.prototype.to_ndnb = function(encoder)
{
encoder.writeElementStartDTag(this.getElementLabel());
this.contentName.to_ndnb(encoder);
if (null != this.publisherID)
this.publisherID.to_ndnb(encoder);
encoder.writeElementClose();
};
KeyName.prototype.getElementLabel = function() { return NDNProtocolDTags.KeyName; };
},{"./buffer.js":25,"./log.js":51,"./name.js":53,"./publisher-id.js":54,"./util/ndn-protoco-id-tags.js":62}],50:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Meki Cheraoui
* See COPYING for copyright and distribution information.
* This class represents Key Objects
*/
var customBuf = require('./buffer.js').Buffer
var LOG = require('./log.js').Log.LOG;
/**
* @constructor
*/
/**
* Key
*/
var Key = function Key()
{
this.publicKeyDer = null; // customBuf
this.publicKeyDigest = null; // customBuf
this.publicKeyPem = null; // String
this.privateKeyPem = null; // String
};
exports.Key = Key;
/**
* Helper functions to read Key fields
* TODO: generateRSA()
*/
Key.prototype.publicToDER = function()
{
return this.publicKeyDer; // customBuf
};
Key.prototype.privateToDER = function()
{
// Remove the '-----XXX-----' from the beginning and the end of the key
// and also remove any \n in the key string
var lines = this.privateKeyPem.split('\n');
priKey = "";
for (var i = 1; i < lines.length - 1; i++)
priKey += lines[i];
return new customBuf(priKey, 'base64');
};
Key.prototype.publicToPEM = function()
{
return this.publicKeyPem;
};
Key.prototype.privateToPEM = function()
{
return this.privateKeyPem;
};
Key.prototype.getKeyID = function()
{
return this.publicKeyDigest;
};
exports.Key = Key;
Key.prototype.readDerPublicKey = function(/*Buffer*/pub_der)
{
if (LOG > 4) console.log("Encode DER public key:\n" + pub_der.toString('hex'));
this.publicKeyDer = pub_der;
var hash = require("./crypto.js").createHash('sha256');
hash.update(this.publicKeyDer);
this.publicKeyDigest = new customBuf(hash.digest());
var keyStr = pub_der.toString('base64');
var keyPem = "-----BEGIN PUBLIC KEY-----\n";
for (var i = 0; i < keyStr.length; i += 64)
keyPem += (keyStr.substr(i, 64) + "\n");
keyPem += "-----END PUBLIC KEY-----";
this.publicKeyPem = keyPem;
if (LOG > 4) console.log("Convert public key to PEM format:\n" + this.publicKeyPem);
};
/**
* Load RSA key pair from PEM-encoded strings.
* Will throw an Error if both 'pub' and 'pri' are null.
*/
Key.prototype.fromPemString = function(pub, pri)
{
if (pub == null && pri == null)
throw new Error('Cannot create Key object if both public and private PEM string is empty.');
// Read public key
if (pub != null) {
this.publicKeyPem = pub;
if (LOG > 4) console.log("Key.publicKeyPem: \n" + this.publicKeyPem);
// Remove the '-----XXX-----' from the beginning and the end of the public key
// and also remove any \n in the public key string
var lines = pub.split('\n');
pub = "";
for (var i = 1; i < lines.length - 1; i++)
pub += lines[i];
this.publicKeyDer = new customBuf(pub, 'base64');
if (LOG > 4) console.log("Key.publicKeyDer: \n" + this.publicKeyDer.toString('hex'));
var hash = require("./crypto.js").createHash('sha256');
hash.update(this.publicKeyDer);
this.publicKeyDigest = new customBuf(hash.digest());
if (LOG > 4) console.log("Key.publicKeyDigest: \n" + this.publicKeyDigest.toString('hex'));
}
// Read private key
if (pri != null) {
this.privateKeyPem = pri;
if (LOG > 4) console.log("Key.privateKeyPem: \n" + this.privateKeyPem);
}
};
Key.prototype.fromPem = Key.prototype.fromPemString;
/**
* Static method that create a Key object.
* Parameter 'obj' is a JSON object that has two properties:
* pub: the PEM string for the public key
* pri: the PEM string for the private key
* Will throw an Error if both obj.pub and obj.pri are null.
*/
Key.createFromPEM = function(obj)
{
var key = new Key();
key.fromPemString(obj.pub, obj.pri);
return key;
};
},{"./buffer.js":25,"./crypto.js":25,"./log.js":51}],51:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
/**
* The Log class holds the global static variable LOG.
*/
var Log = function Log()
{
}
exports.Log = Log;
/**
* LOG is the level for logging debugging statements. 0 means no log messages.
* @type Number
*/
Log.LOG = 0;
},{}],52:[function(require,module,exports){
/**
* Copyright (C) 2014 Regents of the University of California.
* @author: Meki Cheraoui
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
* This class represents an NDN Data MetaInfo object.
*/
var customBuf = require('./buffer.js').Buffer
var BinaryXMLEncoder = require('./encoding/binary-xml-encoder.js').BinaryXMLEncoder;
var BinaryXMLDecoder = require('./encoding/binary-xml-decoder.js').BinaryXMLDecoder;
var Blob = require('./util/blob.js').Blob;
var NDNProtocolDTags = require('./util/ndn-protoco-id-tags.js').NDNProtocolDTags;
var KeyLocator = require('./key-locator.js').KeyLocator;
var KeyLocatorType = require('./key-locator.js').KeyLocatorType;
var Name = require('./name.js').Name;
var PublisherPublicKeyDigest = require('./publisher-public-key-digest.js').PublisherPublicKeyDigest;
var NDNTime = require('./util/ndn-time.js').NDNTime;
var globalKeyManager = require('./security/key-manager.js').globalKeyManager;
var LOG = require('./log.js').Log.LOG;
var ContentType = {
BLOB:0,
// ContentType DATA is deprecated. Use ContentType.BLOB .
DATA:0,
LINK:1,
KEY: 2,
// ContentType ENCR, GONE and NACK are not supported in NDN-TLV encoding and are deprecated.
ENCR:3,
GONE:4,
NACK:5
};
exports.ContentType = ContentType;
/**
* Create a new MetaInfo with the optional values.
* @constructor
*/
var MetaInfo = function MetaInfo(publisherOrMetaInfo, timestamp, type, locator, freshnessSeconds, finalBlockID, skipSetFields)
{
if (typeof publisherOrMetaInfo === 'object' &&
publisherOrMetaInfo instanceof MetaInfo) {
// Copy values.
var metaInfo = publisherOrMetaInfo;
this.publisher = metaInfo.publisher;
this.timestamp = metaInfo.timestamp;
this.type = metaInfo.type;
this.locator = metaInfo.locator == null ?
new KeyLocator() : new KeyLocator(metaInfo.locator);
this.freshnessSeconds = metaInfo.freshnessSeconds;
this.finalBlockID = metaInfo.finalBlockID;
}
else {
this.publisher = publisherOrMetaInfo; //publisherPublicKeyDigest
this.timestamp = timestamp; // NDN Time
this.type = type; // ContentType
this.locator = locator == null ? new KeyLocator() : new KeyLocator(locator);
this.freshnessSeconds = freshnessSeconds; // Integer
this.finalBlockID = finalBlockID; //byte array
if (!skipSetFields)
this.setFields();
}
};
exports.MetaInfo = MetaInfo;
/**
* Get the content type.
* @returns {an int from ContentType} The content type.
*/
MetaInfo.prototype.getType = function()
{
return this.type;
};
/**
* Get the freshness period.
* @returns {number} The freshness period in milliseconds, or null if not
* specified.
*/
MetaInfo.prototype.getFreshnessPeriod = function()
{
// Use attribute freshnessSeconds for backwards compatibility.
if (this.freshnessSeconds == null || this.freshnessSeconds < 0)
return null;
else
// Convert to milliseconds.
return this.freshnessSeconds * 1000.0;
};
/**
* Get the final block ID.
* @returns {Buffer} The final block ID or null if not specified.
*/
MetaInfo.prototype.getFinalBlockID = function()
{
// TODO: finalBlockID should be a Name.Component, not customBuf.
return this.finalBlockID;
};
/**
* Set the content type.
* @param {an int from ContentType} type The content type. If null, this
* uses ContentType.BLOB.
*/
MetaInfo.prototype.setType = function(type)
{
this.type = type == null || type < 0 ? ContentType.BLOB : type;
};
/**
* Set the freshness period.
* @param {type} freshnessPeriod The freshness period in milliseconds, or null
* for not specified.
*/
MetaInfo.prototype.setFreshnessPeriod = function(freshnessPeriod)
{
// Use attribute freshnessSeconds for backwards compatibility.
if (freshnessPeriod == null || freshnessPeriod < 0)
this.freshnessSeconds = null;
else
// Convert from milliseconds.
this.freshnessSeconds = freshnessPeriod / 1000.0;
};
MetaInfo.prototype.setFinalBlockID = function(finalBlockID)
{
// TODO: finalBlockID should be a Name.Component, not customBuf.
if (finalBlockID == null)
this.finalBlockID = null;
else if (typeof finalBlockID === 'object' && finalBlockID instanceof Blob)
this.finalBlockID = finalBlockID.buf();
else if (typeof finalBlockID === 'object' && finalBlockID instanceof Name.Component)
this.finalBlockID = finalBlockID.getValue();
else
this.finalBlockID = new customBuf(finalBlockID);
};
MetaInfo.prototype.setFields = function()
{
var key = globalKeyManager.getKey();
this.publisher = new PublisherPublicKeyDigest(key.getKeyID());
var d = new Date();
var time = d.getTime();
this.timestamp = new NDNTime(time);
if (LOG > 4) console.log('TIME msec is');
if (LOG > 4) console.log(this.timestamp.msec);
//DATA
this.type = ContentType.BLOB;
if (LOG > 4) console.log('PUBLIC KEY TO WRITE TO DATA PACKET IS ');
if (LOG > 4) console.log(key.publicToDER().toString('hex'));
this.locator = new KeyLocator(key.getKeyID(), KeyLocatorType.KEY_LOCATOR_DIGEST);
};
MetaInfo.prototype.from_ndnb = function(decoder)
{
decoder.readElementStartDTag(this.getElementLabel());
if (decoder.peekDTag(NDNProtocolDTags.PublisherPublicKeyDigest)) {
if (LOG > 4) console.log('DECODING PUBLISHER KEY');
this.publisher = new PublisherPublicKeyDigest();
this.publisher.from_ndnb(decoder);
}
if (decoder.peekDTag(NDNProtocolDTags.Timestamp)) {
if (LOG > 4) console.log('DECODING TIMESTAMP');
this.timestamp = decoder.readDateTimeDTagElement(NDNProtocolDTags.Timestamp);
}
if (decoder.peekDTag(NDNProtocolDTags.Type)) {
var binType = decoder.readBinaryDTagElement(NDNProtocolDTags.Type);
if (LOG > 4) console.log('Binary Type of of Signed Info is '+binType);
this.type = binType;
//TODO Implement type of Key Reading
if (null == this.type)
throw new Error("Cannot parse signedInfo type: bytes.");
}
else
this.type = ContentType.DATA; // default
if (decoder.peekDTag(NDNProtocolDTags.FreshnessSeconds)) {
this.freshnessSeconds = decoder.readIntegerDTagElement(NDNProtocolDTags.FreshnessSeconds);
if (LOG > 4) console.log('FRESHNESS IN SECONDS IS '+ this.freshnessSeconds);
}
if (decoder.peekDTag(NDNProtocolDTags.FinalBlockID)) {
if (LOG > 4) console.log('DECODING FINAL BLOCKID');
this.finalBlockID = decoder.readBinaryDTagElement(NDNProtocolDTags.FinalBlockID);
}
if (decoder.peekDTag(NDNProtocolDTags.KeyLocator)) {
if (LOG > 4) console.log('DECODING KEY LOCATOR');
this.locator = new KeyLocator();
this.locator.from_ndnb(decoder);
}
decoder.readElementClose();
};
/**
* Encode this MetaInfo in ndnb, using the given keyLocator instead of the
* locator in this object.
* @param {BinaryXMLEncoder} encoder The encoder.
* @param {KeyLocator} keyLocator The key locator to use (from
* Data.getSignatureOrMetaInfoKeyLocator).
*/
MetaInfo.prototype.to_ndnb = function(encoder, keyLocator) {
if (!this.validate())
throw new Error("Cannot encode : field values missing.");
encoder.writeElementStartDTag(this.getElementLabel());
if (null != this.publisher) {
// We have a publisherPublicKeyDigest, so use it.
if (LOG > 3) console.log('ENCODING PUBLISHER KEY' + this.publisher.publisherPublicKeyDigest);
this.publisher.to_ndnb(encoder);
}
else {
if (null != keyLocator &&
keyLocator.getType() == KeyLocatorType.KEY_LOCATOR_DIGEST &&
keyLocator.getKeyData() != null &&
keyLocator.getKeyData().length > 0)
// We have a TLV-style KEY_LOCATOR_DIGEST, so encode as the
// publisherPublicKeyDigest.
encoder.writeDTagElement
(NDNProtocolDTags.PublisherPublicKeyDigest, keyLocator.getKeyData());
}
if (null != this.timestamp)
encoder.writeDateTimeDTagElement(NDNProtocolDTags.Timestamp, this.timestamp);
if (null != this.type && this.type != 0)
encoder.writeDTagElement(NDNProtocolDTags.type, this.type);
if (null != this.freshnessSeconds)
encoder.writeDTagElement(NDNProtocolDTags.FreshnessSeconds, this.freshnessSeconds);
if (null != this.finalBlockID)
encoder.writeDTagElement(NDNProtocolDTags.FinalBlockID, this.finalBlockID);
if (null != keyLocator)
keyLocator.to_ndnb(encoder);
encoder.writeElementClose();
};
MetaInfo.prototype.valueToType = function()
{
return null;
};
MetaInfo.prototype.getElementLabel = function() {
return NDNProtocolDTags.SignedInfo;
};
MetaInfo.prototype.validate = function()
{
// We don't do partial matches any more, even though encoder/decoder
// is still pretty generous.
if (null == this.timestamp)
return false;
return true;
};
/**
* @deprecated Use new MetaInfo.
*/
var SignedInfo = function SignedInfo(publisherOrMetaInfo, timestamp, type, locator, freshnessSeconds, finalBlockID)
{
// Call the base constructor.
MetaInfo.call(this, publisherOrMetaInfo, timestamp, type, locator, freshnessSeconds, finalBlockID);
}
// Set skipSetFields true since we only need the prototype functions.
SignedInfo.prototype = new MetaInfo(null, null, null, null, null, null, true);
exports.SignedInfo = SignedInfo;
},{"./buffer.js":25,"./encoding/binary-xml-decoder.js":28,"./encoding/binary-xml-encoder.js":29,"./key-locator.js":49,"./log.js":51,"./name.js":53,"./publisher-public-key-digest.js":55,"./security/key-manager.js":56,"./util/blob.js":59,"./util/ndn-protoco-id-tags.js":62,"./util/ndn-time.js":63}],53:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Meki Cheraoui, Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
* This class represents a Name as an array of components where each is a byte array.
*/
var Blob = require('./util/blob.js').Blob;
var DataUtils = require('./encoding/data-utils.js').DataUtils;
var BinaryXMLEncoder = require('./encoding/binary-xml-encoder.js').BinaryXMLEncoder;
var BinaryXMLDecoder = require('./encoding/binary-xml-decoder.js').BinaryXMLDecoder;
var NDNProtocolDTags = require('./util/ndn-protoco-id-tags.js').NDNProtocolDTags;
var customBuf = require('./buffer.js').Buffer
var LOG = require('./log.js').Log.LOG;
/**
* Create a new Name from components.
*
* @constructor
* @param {string|Name|Array<string|Array<number>|ArrayBuffer|Buffer|Name>} components if a string, parse it as a URI. If a Name, add a deep copy of its components.
* Otherwise it is an array of components which are appended according to Name.append, so
* convert each and store it as an array of customBuf. If a component is a string, encode as utf8.
*/
var Name = function Name(components)
{
if (typeof components == 'string') {
if (LOG > 3) console.log('Content Name String ' + components);
this.components = Name.createNameArray(components);
}
else if (typeof components === 'object') {
this.components = [];
if (components instanceof Name)
this.append(components);
else {
for (var i = 0; i < components.length; ++i)
this.append(components[i]);
}
}
else if (components == null)
this.components = [];
else
if (LOG > 1) console.log("NO CONTENT NAME GIVEN");
};
exports.Name = Name;
/**
*
* @constructor
* Create a new Name.Component with a copy of the given value.
* @param {Name.Component|String|Array<number>|ArrayBuffer|Buffer} value If the value is a string, encode it as utf8 (but don't unescape).
*/
Name.Component = function NameComponent(value)
{
if (typeof value === 'string')
this.value = DataUtils.stringToUtf8Array(value);
else if (typeof value === 'object' && value instanceof Name.Component)
this.value = new customBuf(value.value);
else if (typeof value === 'object' && value instanceof Blob)
this.value = new customBuf(value.buf());
else if (typeof value === 'object' && value instanceof customBuf)
this.value = new customBuf(value);
else if (typeof value === 'object' && typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
// Make a copy. Don't use ArrayBuffer.slice since it isn't always supported.
this.value = new customBuf(new ArrayBuffer(value.byteLength));
this.value.set(new customBuf(value));
}
else if (typeof value === 'object')
// Assume value is a byte array. We can't check instanceof Array because
// this doesn't work in JavaScript if the array comes from a different module.
this.value = new customBuf(value);
else if (!value)
this.value = new customBuf(0);
else
throw new Error("Name.Component constructor: Invalid type");
}
/**
* Get the component value.
* @returns {Buffer} The component value.
*/
Name.Component.prototype.getValue = function()
{
return this.value;
}
/**
* Convert this component value to a string by escaping characters according to the NDN URI Scheme.
* This also adds "..." to a value with zero or more ".".
* @returns {string} The escaped string.
*/
Name.Component.prototype.toEscapedString = function()
{
return Name.toEscapedString(this.value);
}
/**
* Check if this is the same component as other.
* @param {Name.Component} other The other Component to compare with.
* @returns {Boolean} true if the components are equal, otherwise false.
*/
Name.Component.prototype.equals = function(other)
{
return DataUtils.arraysEqual(this.value, other.value);
}
/**
* @deprecated Use toUri.
*/
Name.prototype.getName = function()
{
return this.toUri();
};
/** Parse uri as a URI and return an array of customBuf components.
*/
Name.createNameArray = function(uri)
{
uri = uri.trim();
if (uri.length <= 0)
return [];
var iColon = uri.indexOf(':');
if (iColon >= 0) {
// Make sure the colon came before a '/'.
var iFirstSlash = uri.indexOf('/');
if (iFirstSlash < 0 || iColon < iFirstSlash)
// Omit the leading protocol such as ndn:
uri = uri.substr(iColon + 1, uri.length - iColon - 1).trim();
}
if (uri[0] == '/') {
if (uri.length >= 2 && uri[1] == '/') {
// Strip the authority following "//".
var iAfterAuthority = uri.indexOf('/', 2);
if (iAfterAuthority < 0)
// Unusual case: there was only an authority.
return [];
else
uri = uri.substr(iAfterAuthority + 1, uri.length - iAfterAuthority - 1).trim();
}
else
uri = uri.substr(1, uri.length - 1).trim();
}
var array = uri.split('/');
// Unescape the components.
for (var i = 0; i < array.length; ++i) {
var value = Name.fromEscapedString(array[i]);
if (value == null) {
// Ignore the illegal componenent. This also gets rid of a trailing '/'.
array.splice(i, 1);
--i;
continue;
}
else
array[i] = new Name.Component(value);
}
return array;
};
Name.prototype.from_ndnb = function(/*XMLDecoder*/ decoder)
{
decoder.readElementStartDTag(this.getElementLabel());
this.components = [];
while (decoder.peekDTag(NDNProtocolDTags.Component))
this.append(decoder.readBinaryDTagElement(NDNProtocolDTags.Component));
decoder.readElementClose();
};
Name.prototype.to_ndnb = function(/*XMLEncoder*/ encoder)
{
if (this.components == null)
throw new Error("CANNOT ENCODE EMPTY CONTENT NAME");
encoder.writeElementStartDTag(this.getElementLabel());
var count = this.size();
for (var i=0; i < count; i++)
encoder.writeDTagElement(NDNProtocolDTags.Component, this.components[i].getValue());
encoder.writeElementClose();
};
Name.prototype.getElementLabel = function()
{
return NDNProtocolDTags.Name;
};
/**
* Convert the component to a customBuf and append to this Name.
* Return this Name object to allow chaining calls to add.
* @param {Name.Component|String|Array<number>|ArrayBuffer|Buffer|Name} component If a component is a string, encode as utf8 (but don't unescape).
* @returns {Name}
*/
Name.prototype.append = function(component)
{
if (typeof component == 'object' && component instanceof Name) {
var components;
if (component == this)
// special case, when we need to create a copy
components = this.components.slice(0, this.components.length);
else
components = component.components;
for (var i = 0; i < components.length; ++i)
this.components.push(new Name.Component(components[i]));
}
else
// Just use the Name.Component constructor.
this.components.push(new Name.Component(component));
return this;
};
/**
* @deprecated Use append.
*/
Name.prototype.add = function(component)
{
return this.append(component);
};
/**
* Clear all the components.
*/
Name.prototype.clear = function()
{
this.components = [];
};
/**
* Return the escaped name string according to "NDNx URI Scheme".
* @returns {String}
*/
Name.prototype.toUri = function()
{
if (this.size() == 0)
return "/";
var result = "";
for (var i = 0; i < this.size(); ++i)
result += "/"+ Name.toEscapedString(this.components[i].getValue());
return result;
};
/**
* @deprecated Use toUri.
*/
Name.prototype.to_uri = function()
{
return this.toUri();
};
/**
* Append a component with the encoded segment number.
* @param {number} segment The segment number.
* @returns {Name} This name so that you can chain calls to append.
*/
Name.prototype.appendSegment = function(segment)
{
var segmentNumberBigEndian = DataUtils.nonNegativeIntToBigEndian(segment);
// Put a 0 byte in front.
var segmentNumberComponent = new customBuf(segmentNumberBigEndian.length + 1);
segmentNumberComponent[0] = 0;
segmentNumberBigEndian.copy(segmentNumberComponent, 1);
this.components.push(new Name.Component(segmentNumberComponent));
return this;
};
/**
* Append a component with the encoded version number.
* Note that this encodes the exact value of version without converting from a
* time representation.
* @param {number} version The version number.
* @returns {Name} This name so that you can chain calls to append.
*/
Name.prototype.appendVersion = function(version)
{
var segmentNumberBigEndian = DataUtils.nonNegativeIntToBigEndian(version);
// Put a 0 byte in front.
var segmentNumberComponent = new customBuf(segmentNumberBigEndian.length + 1);
segmentNumberComponent[0] = 0xfD;
segmentNumberBigEndian.copy(segmentNumberComponent, 1);
this.components.push(new Name.Component(segmentNumberComponent));
return this;
};
/**
* @deprecated Use appendSegment.
*/
Name.prototype.addSegment = function(number)
{
return this.appendSegment(number);
};
/**
* Get a new name, constructed as a subset of components.
* @param {number} iStartComponent The index if the first component to get.
* @param {number} (optional) nComponents The number of components starting at iStartComponent. If omitted,
* return components starting at iStartComponent until the end of the name.
* @returns {Name} A new name.
*/
Name.prototype.getSubName = function(iStartComponent, nComponents)
{
if (nComponents == undefined)
nComponents = this.components.length - iStartComponent;
var result = new Name();
var iEnd = iStartComponent + nComponents;
for (var i = iStartComponent; i < iEnd && i < this.components.length; ++i)
result.components.push(this.components[i]);
return result;
};
/**
* Return a new Name with the first nComponents components of this Name.
* @param {number} nComponents The number of prefix components. If nComponents is -N then return the prefix up
* to name.size() - N. For example getPrefix(-1) returns the name without the final component.
* @returns {Name} A new name.
*/
Name.prototype.getPrefix = function(nComponents)
{
if (nComponents < 0)
return this.getSubName(0, this.components.length + nComponents);
else
return this.getSubName(0, nComponents);
};
/**
* @brief Get prefix of the name, containing less minusComponents right components
* @param minusComponents number of components to cut from the back
*/
Name.prototype.cut = function(minusComponents)
{
return new Name(this.components.slice(0, this.components.length - minusComponents));
};
/**
* Return the number of name components.
* @returns {number}
*/
Name.prototype.size = function()
{
return this.components.length;
};
/**
* Return a new Name.Component of the component at the given index. To get just the component value, use get(i).getValue().
* @param {Number} i The index of the component, starting from 0. However, if i is negative, return the component
* at size() - (-i).
* @returns {Name.Component}
*/
Name.prototype.get = function(i)
{
if (i >= 0) {
if (i >= this.components.length)
throw new Error("Name.get: Index is out of bounds");
return new Name.Component(this.components[i]);
}
else {
// Negative index.
if (i < -this.components.length)
throw new Error("Name.get: Index is out of bounds");
return new Name.Component(this.components[this.components.length - (-i)]);
}
};
/**
* @deprecated Use size().
*/
Name.prototype.getComponentCount = function()
{
return this.components.length;
};
/**
* @deprecated To get just the component value, use get(i).getValue().
*/
Name.prototype.getComponent = function(i)
{
return new customBuf(this.components[i].getValue());
};
/**
* The "file name" in a name is the last component that isn't blank and doesn't start with one of the
* special marker octets (for version, etc.). Return the index in this.components of
* the file name, or -1 if not found.
*/
Name.prototype.indexOfFileName = function()
{
for (var i = this.size() - 1; i >= 0; --i) {
var component = this.components[i].getValue();
if (component.length <= 0)
continue;
if (component[0] == 0 || component[0] == 0xC0 || component[0] == 0xC1 ||
(component[0] >= 0xF5 && component[0] <= 0xFF))
continue;
return i;
}
return -1;
};
/**
* Return true if this Name has the same components as name.
*/
Name.prototype.equals = function(name)
{
if (this.components.length != name.components.length)
return false;
// Start from the last component because they are more likely to differ.
for (var i = this.components.length - 1; i >= 0; --i) {
if (!this.components[i].equals(name.components[i]))
return false;
}
return true;
};
/**
* @deprecated Use equals.
*/
Name.prototype.equalsName = function(name)
{
return this.equals(name);
};
/**
* Find the last component in name that has a ContentDigest and return the digest value as customBuf,
* or null if not found. See Name.getComponentContentDigestValue.
*/
Name.prototype.getContentDigestValue = function()
{
for (var i = this.size() - 1; i >= 0; --i) {
var digestValue = Name.getComponentContentDigestValue(this.components[i]);
if (digestValue != null)
return digestValue;
}
return null;
};
/**
* If component is a ContentDigest, return the digest value as a customBuf slice (don't modify!).
* If not a ContentDigest, return null.
* A ContentDigest component is Name.ContentDigestPrefix + 32 bytes + Name.ContentDigestSuffix.
*/
Name.getComponentContentDigestValue = function(component)
{
if (typeof component == 'object' && component instanceof Name.Component)
component = component.getValue();
var digestComponentLength = Name.ContentDigestPrefix.length + 32 + Name.ContentDigestSuffix.length;
// Check for the correct length and equal ContentDigestPrefix and ContentDigestSuffix.
if (component.length == digestComponentLength &&
DataUtils.arraysEqual(component.slice(0, Name.ContentDigestPrefix.length),
Name.ContentDigestPrefix) &&
DataUtils.arraysEqual(component.slice
(component.length - Name.ContentDigestSuffix.length, component.length),
Name.ContentDigestSuffix))
return component.slice(Name.ContentDigestPrefix.length, Name.ContentDigestPrefix.length + 32);
else
return null;
};
// Meta GUID "%C1.M.G%C1" + ContentDigest with a 32 byte BLOB.
Name.ContentDigestPrefix = new customBuf([0xc1, 0x2e, 0x4d, 0x2e, 0x47, 0xc1, 0x01, 0xaa, 0x02, 0x85]);
Name.ContentDigestSuffix = new customBuf([0x00]);
/**
* Return value as an escaped string according to "NDNx URI Scheme".
* We can't use encodeURIComponent because that doesn't encode all the characters we want to.
* @param {Buffer|Name.Component} component The value or Name.Component to escape.
* @returns {string} The escaped string.
*/
Name.toEscapedString = function(value)
{
if (typeof value == 'object' && value instanceof Name.Component)
value = value.getValue();
var result = "";
var gotNonDot = false;
for (var i = 0; i < value.length; ++i) {
if (value[i] != 0x2e) {
gotNonDot = true;
break;
}
}
if (!gotNonDot) {
// Special case for component of zero or more periods. Add 3 periods.
result = "...";
for (var i = 0; i < value.length; ++i)
result += ".";
}
else {
for (var i = 0; i < value.length; ++i) {
var x = value[i];
// Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
if (x >= 0x30 && x <= 0x39 || x >= 0x41 && x <= 0x5a ||
x >= 0x61 && x <= 0x7a || x == 0x2b || x == 0x2d ||
x == 0x2e || x == 0x5f)
result += String.fromCharCode(x);
else
result += "%" + (x < 16 ? "0" : "") + x.toString(16).toUpperCase();
}
}
return result;
};
/**
* Return a customBuf byte array by decoding the escapedString according to "NDNx URI Scheme".
* If escapedString is "", "." or ".." then return null, which means to skip the component in the name.
* @param {string} escapedString The escaped string to decode.
* @returns {Buffer} The byte array, or null which means to skip the component in the name.
*/
Name.fromEscapedString = function(escapedString)
{
var value = unescape(escapedString.trim());
if (value.match(/[^.]/) == null) {
// Special case for value of only periods.
if (value.length <= 2)
// Zero, one or two periods is illegal. Ignore this componenent to be
// consistent with the C implementation.
return null;
else
// Remove 3 periods.
return DataUtils.toNumbersFromString(value.substr(3, value.length - 3));
}
else
return DataUtils.toNumbersFromString(value);
};
/**
* Return true if the N components of this name are the same as the first N components of the given name.
* @param {Name} name The name to check.
* @returns {Boolean} true if this matches the given name. This always returns true if this name is empty.
*/
Name.prototype.match = function(name)
{
var i_name = this.components;
var o_name = name.components;
// This name is longer than the name we are checking it against.
if (i_name.length > o_name.length)
return false;
// Check if at least one of given components doesn't match.
for (var i = 0; i < i_name.length; ++i) {
if (!i_name[i].equals(o_name[i]))
return false;
}
return true;
};
},{"./buffer.js":25,"./encoding/binary-xml-decoder.js":28,"./encoding/binary-xml-encoder.js":29,"./encoding/data-utils.js":32,"./log.js":51,"./util/blob.js":59,"./util/ndn-protoco-id-tags.js":62}],54:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Meki Cheraoui
* See COPYING for copyright and distribution information.
* This class represents Publisher and PublisherType Objects
*/
var NDNProtocolDTags = require('./util/ndn-protoco-id-tags.js').NDNProtocolDTags;
var NDNProtocolDTagsStrings = require('./util/ndn-protoco-id-tags.js').NDNProtocolDTagsStrings;
var DecodingException = require('./encoding/decoding-exception.js').DecodingException;
/**
* @constructor
*/
var PublisherType = function PublisherType(tag)
{
this.KEY = NDNProtocolDTags.PublisherPublicKeyDigest;
this.CERTIFICATE = NDNProtocolDTags.PublisherCertificateDigest;
this.ISSUER_KEY = NDNProtocolDTags.PublisherIssuerKeyDigest;
this.ISSUER_CERTIFICATE = NDNProtocolDTags.PublisherIssuerCertificateDigest;
this.Tag = tag;
};
/**
* @constructor
*/
var PublisherID = function PublisherID()
{
this.PUBLISHER_ID_DIGEST_ALGORITHM = "SHA-256";
this.PUBLISHER_ID_LEN = 256/8;
//TODO, implement publisherID creation and key creation
//TODO implement generatePublicKeyDigest
this.publisherID =null;//= generatePublicKeyDigest(key);//ByteArray
//TODO implement generate key
//CryptoUtil.generateKeyID(PUBLISHER_ID_DIGEST_ALGORITHM, key);
this.publisherType = null;//isIssuer ? PublisherType.ISSUER_KEY : PublisherType.KEY;//publisher Type
};
exports.PublisherID = PublisherID;
PublisherID.prototype.from_ndnb = function(decoder)
{
// We have a choice here of one of 4 binary element types.
var nextTag = PublisherID.peekAndGetNextDTag(decoder);
this.publisherType = new PublisherType(nextTag);
if (nextTag < 0)
throw new Error("Invalid publisher ID, got unexpected type");
this.publisherID = decoder.readBinaryDTagElement(nextTag);
if (null == this.publisherID)
throw new DecodingException(new Error("Cannot parse publisher ID of type : " + nextTag + "."));
};
PublisherID.prototype.to_ndnb = function(encoder)
{
if (!this.validate())
throw new Error("Cannot encode " + this.getClass().getName() + ": field values missing.");
encoder.writeDTagElement(this.getElementLabel(), this.publisherID);
};
/**
* Peek the next DTag in the decoder and return it if it is a PublisherID DTag.
* @param {BinaryXMLDecoder} decoder The BinaryXMLDecoder with the input to decode.
* @returns {number} The PublisherID DTag or -1 if it is not one of them.
*/
PublisherID.peekAndGetNextDTag = function(decoder)
{
if (decoder.peekDTag(NDNProtocolDTags.PublisherPublicKeyDigest))
return NDNProtocolDTags.PublisherPublicKeyDigest;
if (decoder.peekDTag(NDNProtocolDTags.PublisherCertificateDigest))
return NDNProtocolDTags.PublisherCertificateDigest;
if (decoder.peekDTag(NDNProtocolDTags.PublisherIssuerKeyDigest))
return NDNProtocolDTags.PublisherIssuerKeyDigest;
if (decoder.peekDTag(NDNProtocolDTags.PublisherIssuerCertificateDigest))
return NDNProtocolDTags.PublisherIssuerCertificateDigest;
return -1;
};
PublisherID.peek = function(/* XMLDecoder */ decoder)
{
return PublisherID.peekAndGetNextDTag(decoder) >= 0;
};
PublisherID.prototype.getElementLabel = function()
{
return this.publisherType.Tag;
};
PublisherID.prototype.validate = function()
{
return null != id() && null != type();
};
},{"./encoding/decoding-exception.js":33,"./util/ndn-protoco-id-tags.js":62}],55:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Meki Cheraoui
* See COPYING for copyright and distribution information.
* This class represents PublisherPublicKeyDigest Objects
*/
var NDNProtocolDTags = require('./util/ndn-protoco-id-tags.js').NDNProtocolDTags;
var LOG = require('./log.js').Log.LOG;
/**
* @constructor
*/
var PublisherPublicKeyDigest = function PublisherPublicKeyDigest(pkd)
{
this.PUBLISHER_ID_LEN = 512/8;
this.publisherPublicKeyDigest = pkd;
};
exports.PublisherPublicKeyDigest = PublisherPublicKeyDigest;
PublisherPublicKeyDigest.prototype.from_ndnb = function(decoder)
{
this.publisherPublicKeyDigest = decoder.readBinaryDTagElement(this.getElementLabel());
if (LOG > 4) console.log('Publisher public key digest is ' + this.publisherPublicKeyDigest);
if (null == this.publisherPublicKeyDigest)
throw new Error("Cannot parse publisher key digest.");
//TODO check if the length of the PublisherPublicKeyDigest is correct (Security reason)
if (this.publisherPublicKeyDigest.length != this.PUBLISHER_ID_LEN) {
if (LOG > 0)
console.log('LENGTH OF PUBLISHER ID IS WRONG! Expected ' + this.PUBLISHER_ID_LEN + ", got " + this.publisherPublicKeyDigest.length);
//this.publisherPublicKeyDigest = new PublisherPublicKeyDigest(this.PublisherPublicKeyDigest).PublisherKeyDigest;
}
};
PublisherPublicKeyDigest.prototype.to_ndnb= function(encoder)
{
//TODO Check that the ByteArray for the key is present
if (!this.validate())
throw new Error("Cannot encode : field values missing.");
if (LOG > 3) console.log('PUBLISHER KEY DIGEST IS'+this.publisherPublicKeyDigest);
encoder.writeDTagElement(this.getElementLabel(), this.publisherPublicKeyDigest);
};
PublisherPublicKeyDigest.prototype.getElementLabel = function() { return NDNProtocolDTags.PublisherPublicKeyDigest; };
PublisherPublicKeyDigest.prototype.validate = function()
{
return null != this.publisherPublicKeyDigest;
};
},{"./log.js":51,"./util/ndn-protoco-id-tags.js":62}],56:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Meki Cheraoui
* See COPYING for copyright and distribution information.
*/
var Key = require('../key.js').Key;
/**
* @constructor
*/
var KeyManager = function KeyManager()
{
this.certificate =
"MIIBmzCCAQQCCQC32FyQa61S7jANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwd" +
"heGVsY2R2MB4XDTEyMDQyODIzNDQzN1oXDTEyMDUyODIzNDQzN1owEjEQMA4GA1" +
"UEAxMHYXhlbGNkdjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4X0wp9goq" +
"xuECxdULcr2IHr9Ih4Iaypg0Wy39URIup8/CLzQmdsh3RYqd55hqonu5VTTpH3i" +
"MLx6xZDVJAZ8OJi7pvXcQ2C4Re2kjL2c8SanI0RfDhlS1zJadfr1VhRPmpivcYa" +
"wJ4aFuOLAi+qHFxtN7lhcGCgpW1OV60oXd58CAwEAATANBgkqhkiG9w0BAQUFAA" +
"OBgQDLOrA1fXzSrpftUB5Ro6DigX1Bjkf7F5Bkd69hSVp+jYeJFBBlsILQAfSxU" +
"ZPQtD+2Yc3iCmSYNyxqu9PcufDRJlnvB7PG29+L3y9lR37tetzUV9eTscJ7rdp8" +
"Wt6AzpW32IJ/54yKNfP7S6ZIoIG+LP6EIxq6s8K1MXRt8uBJKw==";
// Public Key
this.publicKey =
"-----BEGIN PUBLIC KEY-----\n" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhfTCn2CirG4QLF1QtyvYgev0i\n" +
"HghrKmDRbLf1REi6nz8IvNCZ2yHdFip3nmGqie7lVNOkfeIwvHrFkNUkBnw4mLum\n" +
"9dxDYLhF7aSMvZzxJqcjRF8OGVLXMlp1+vVWFE+amK9xhrAnhoW44sCL6ocXG03u\n" +
"WFwYKClbU5XrShd3nwIDAQAB\n" +
"-----END PUBLIC KEY-----";
// Private Key
this.privateKey =
"-----BEGIN RSA PRIVATE KEY-----\n" +
"MIICXQIBAAKBgQDhfTCn2CirG4QLF1QtyvYgev0iHghrKmDRbLf1REi6nz8IvNCZ\n" +
"2yHdFip3nmGqie7lVNOkfeIwvHrFkNUkBnw4mLum9dxDYLhF7aSMvZzxJqcjRF8O\n" +
"GVLXMlp1+vVWFE+amK9xhrAnhoW44sCL6ocXG03uWFwYKClbU5XrShd3nwIDAQAB\n" +
"AoGAGkv6T6jC3WmhFZYL6CdCWvlc6gysmKrhjarrLTxgavtFY6R5g2ft5BXAsCCV\n" +
"bUkWxkIFSKqxpVNl0gKZCNGEzPDN6mHJOQI/h0rlxNIHAuGfoAbCzALnqmyZivhJ\n" +
"APGijAyKuU9tczsst5+Kpn+bn7ehzHQuj7iwJonS5WbojqECQQD851K8TpW2GrRi\n" +
"zNgG4dx6orZxAaon/Jnl8lS7soXhllQty7qG+oDfzznmdMsiznCqEABzHUUKOVGE\n" +
"9RWPN3aRAkEA5D/w9N55d0ibnChFJlc8cUAoaqH+w+U3oQP2Lb6AZHJpLptN4y4b\n" +
"/uf5d4wYU5/i/gC7SSBH3wFhh9bjRLUDLwJAVOx8vN0Kqt7myfKNbCo19jxjVSlA\n" +
"8TKCn1Oznl/BU1I+rC4oUaEW25DjmX6IpAR8kq7S59ThVSCQPjxqY/A08QJBAIRa\n" +
"F2zGPITQk3r/VumemCvLWiRK/yG0noc9dtibqHOWbCtcXtOm/xDWjq+lis2i3ssO\n" +
"vYrvrv0/HcDY+Dv1An0CQQCLJtMsfSg4kvG/FRY5UMhtMuwo8ovYcMXt4Xv/LWaM\n" +
"hndD67b2UGawQCRqr5ghRTABWdDD/HuuMBjrkPsX0861\n" +
"-----END RSA PRIVATE KEY-----";
this.key = null;
};
/**
* Return a Key object for the keys in this KeyManager. This creates the Key on the first
* call and returns a cached copy after that.
* @returns {Key}
*/
KeyManager.prototype.getKey = function()
{
if (this.key === null) {
this.key = new Key();
this.key.fromPemString(this.publicKey, this.privateKey);
}
return this.key;
}
var globalKeyManager = globalKeyManager || new KeyManager();
exports.globalKeyManager = globalKeyManager;
},{"../key.js":50}],57:[function(require,module,exports){
/**
* Copyright (C) 2014 Regents of the University of California.
* @author: Meki Cheraoui
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
* This class represents an NDN Data Signature object.
*/
var Blob = require('./util/blob.js').Blob;
var BinaryXMLEncoder = require('./encoding/binary-xml-encoder.js').BinaryXMLEncoder;
var BinaryXMLDecoder = require('./encoding/binary-xml-decoder.js').BinaryXMLDecoder;
var NDNProtocolDTags = require('./util/ndn-protoco-id-tags.js').NDNProtocolDTags;
var KeyLocator = require('./key-locator.js').KeyLocator;
var customBuf = require('./buffer.js').Buffer
var LOG = require('./log.js').Log.LOG;
/**
* Create a new Signature with the optional values.
* @constructor
*/
var Signature = function Signature(witnessOrSignatureObject, signature, digestAlgorithm)
{
if (typeof witnessOrSignatureObject === 'object' &&
witnessOrSignatureObject instanceof Signature) {
// Copy the values.
this.keyLocator = new KeyLocator(witnessOrSignatureObject.keyLocator);
this.signature = witnessOrSignatureObject.signature;
// witness is deprecated.
this.witness = witnessOrSignatureObject.witness;
// digestAlgorithm is deprecated.
this.digestAlgorithm = witnessOrSignatureObject.digestAlgorithm;
}
else {
this.keyLocator = new KeyLocator();
this.signature = signature;
// witness is deprecated.
this.witness = witnessOrSignatureObject;
// digestAlgorithm is deprecated.
this.digestAlgorithm = digestAlgorithm;
}
};
exports.Signature = Signature;
/**
* Create a new Signature which is a copy of this object.
* @returns {Signature} A new object which is a copy of this object.
*/
Signature.prototype.clone = function()
{
return new Signature(this);
};
/**
* Get the key locator.
* @returns {KeyLocator} The key locator.
*/
Signature.prototype.getKeyLocator = function()
{
return this.keyLocator;
};
/**
* Get the data packet's signature bytes.
* @returns {Buffer} The signature bytes.
*/
Signature.prototype.getSignature = function()
{
return this.signature;
};
/**
* Set the key locator to a copy of the given keyLocator.
* @param {KeyLocator} keyLocator The KeyLocator to copy.
*/
Signature.prototype.setKeyLocator = function(keyLocator)
{
this.keyLocator = typeof keyLocator === 'object' && keyLocator instanceof KeyLocator ?
new KeyLocator(keyLocator) : new KeyLocator();
};
/**
* Set the data packet's signature bytes.
* @param {type} signature
*/
Signature.prototype.setSignature = function(signature)
{
if (signature == null)
this.signature = null;
else if (typeof signature === 'object' && signature instanceof Blob)
this.signature = new customBuf(signature.buf());
else
this.signature = new customBuf(signature);
};
Signature.prototype.from_ndnb = function(decoder)
{
decoder.readElementStartDTag(this.getElementLabel());
if (LOG > 4) console.log('STARTED DECODING SIGNATURE');
if (decoder.peekDTag(NDNProtocolDTags.DigestAlgorithm)) {
if (LOG > 4) console.log('DIGIEST ALGORITHM FOUND');
this.digestAlgorithm = decoder.readUTF8DTagElement(NDNProtocolDTags.DigestAlgorithm);
}
if (decoder.peekDTag(NDNProtocolDTags.Witness)) {
if (LOG > 4) console.log('WITNESS FOUND');
this.witness = decoder.readBinaryDTagElement(NDNProtocolDTags.Witness);
}
//FORCE TO READ A SIGNATURE
if (LOG > 4) console.log('SIGNATURE FOUND');
this.signature = decoder.readBinaryDTagElement(NDNProtocolDTags.SignatureBits);
decoder.readElementClose();
};
Signature.prototype.to_ndnb = function(encoder)
{
if (!this.validate())
throw new Error("Cannot encode: field values missing.");
encoder.writeElementStartDTag(this.getElementLabel());
if (null != this.digestAlgorithm && !this.digestAlgorithm.equals(NDNDigestHelper.DEFAULT_DIGEST_ALGORITHM))
encoder.writeDTagElement(NDNProtocolDTags.DigestAlgorithm, OIDLookup.getDigestOID(this.DigestAlgorithm));
if (null != this.witness)
// needs to handle null witness
encoder.writeDTagElement(NDNProtocolDTags.Witness, this.witness);
encoder.writeDTagElement(NDNProtocolDTags.SignatureBits, this.signature);
encoder.writeElementClose();
};
Signature.prototype.getElementLabel = function() { return NDNProtocolDTags.Signature; };
Signature.prototype.validate = function()
{
return null != this.signature;
};
},{"./buffer.js":25,"./encoding/binary-xml-decoder.js":28,"./encoding/binary-xml-encoder.js":29,"./key-locator.js":49,"./log.js":51,"./util/blob.js":59,"./util/ndn-protoco-id-tags.js":62}],58:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Wentao Shang
* See COPYING for copyright and distribution information.
*/
var customBuf = require('../buffer.js').Buffer
var ElementReader = require('../encoding/element-reader.js').ElementReader;
var DataUtils = require('../encoding/data-utils.js').DataUtils;
var LOG = require('../log.js').Log.LOG;
function makeShuffledGetHostAndPort (hostList, port)
{
// Make a copy.
hostList = hostList.slice(0, hostList.length);
DataUtils.shuffle(hostList);
return function() {
if (hostList.length == 0)
return null;
return { host: hostList.splice(0, 1)[0], port: port };
};
};
/**
* @constructor
*/
var WebSocketTransport = function WebSocketTransport()
{
if (!WebSocket)
throw new Error("WebSocket support is not available on this platform.");
this.ws = null;
this.connectedHost = null; // Read by Face.
this.connectedPort = null; // Read by Face.
this.elementReader = null;
this.defaultGetHostAndPort = makeShuffledGetHostAndPort
(["A.ws.ndn.ucla.edu", "B.ws.ndn.ucla.edu", "C.ws.ndn.ucla.edu", "D.ws.ndn.ucla.edu",
"E.ws.ndn.ucla.edu", "F.ws.ndn.ucla.edu", "G.ws.ndn.ucla.edu", "H.ws.ndn.ucla.edu",
"I.ws.ndn.ucla.edu", "J.ws.ndn.ucla.edu", "K.ws.ndn.ucla.edu", "L.ws.ndn.ucla.edu",
"M.ws.ndn.ucla.edu", "N.ws.ndn.ucla.edu"],
9696);
};
exports.WebSocketTransport = WebSocketTransport;
/**
* Connect to the host and port in face. This replaces a previous connection and sets connectedHost
* and connectedPort. Once connected, call onopenCallback().
* Listen on the port to read an entire binary XML encoded element and call
* face.onReceivedElement(element).
*/
WebSocketTransport.prototype.connect = function(face, onopenCallback)
{
this.close();
this.ws = new WebSocket('ws:' + face.host + ':' + face.port);
if (LOG > 0) console.log('ws connection created.');
this.connectedHost = face.host;
this.connectedPort = face.port;
this.ws.binaryType = "arraybuffer";
this.elementReader = new ElementReader(face);
var self = this;
this.ws.onmessage = function(ev) {
var result = ev.data;
//console.log('RecvHandle called.');
if (result == null || result == undefined || result == "") {
console.log('INVALID ANSWER');
}
else if (result instanceof ArrayBuffer) {
var bytearray = new customBuf(result);
if (LOG > 3) console.log('BINARY RESPONSE IS ' + bytearray.toString('hex'));
try {
// Find the end of the binary XML element and call face.onReceivedElement.
self.elementReader.onReceivedData(bytearray);
} catch (ex) {
console.log("NDN.ws.onmessage exception: " + ex);
return;
}
}
}
this.ws.onopen = function(ev) {
if (LOG > 3) console.log(ev);
if (LOG > 3) console.log('ws.onopen: WebSocket connection opened.');
if (LOG > 3) console.log('ws.onopen: ReadyState: ' + this.readyState);
// Face.registerPrefix will fetch the ndndid when needed.
onopenCallback();
}
this.ws.onerror = function(ev) {
console.log('ws.onerror: ReadyState: ' + this.readyState);
console.log(ev);
console.log('ws.onerror: WebSocket error: ' + ev.data);
}
this.ws.onclose = function(ev) {
console.log('ws.onclose: WebSocket connection closed.');
self.ws = null;
// Close Face when WebSocket is closed
face.readyStatus = 2; //Face.CLOSED
face.onclose();
//console.log("NDN.onclose event fired.");
}
};
/**
* Send the Uint8Array data.
*/
WebSocketTransport.prototype.send = function(data)
{
if (this.ws != null) {
// If we directly use data.buffer to feed ws.send(),
// WebSocket may end up sending a packet with 10000 bytes of data.
// That is, WebSocket will flush the entire buffer
// regardless of the offset of the Uint8Array. So we have to create
// a new Uint8Array buffer with just the right size and copy the
// content from binaryInterest to the new buffer.
// ---Wentao
var bytearray = new Uint8Array(data.length);
bytearray.set(data);
this.ws.send(bytearray.buffer);
if (LOG > 3) console.log('ws.send() returned.');
}
else
console.log('WebSocket connection is not established.');
};
/**
* Close the connection.
*/
WebSocketTransport.prototype.close = function()
{
if (this.ws != null)
delete this.ws;
}
},{"../buffer.js":25,"../encoding/data-utils.js":32,"../encoding/element-reader.js":34,"../log.js":51}],59:[function(require,module,exports){
/**
* Copyright (C) 2013 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
var customBuf = require('../buffer.js').Buffer
/**
* A Blob holds an immutable byte array implemented as a customBuf. This should be
* treated like a string which is a pointer to an immutable string. (It is OK to
* pass a pointer to the string because the new owner can’t change the bytes of
* the string.) Blob does not inherit from customBuf. Instead you must call buf()
* to get the byte array which reminds you that you should not change the
* contents. Also remember that buf() can return null.
* @param {Blob|Buffer|Array<number>} value (optional) If value is a Blob, take
* another pointer to the customBuf without copying. If value is a customBuf or byte
* array, copy to create a new customBuf. If omitted, buf() will return null.
* @param {boolean} copy (optional) (optional) If true, copy the contents of
* value into a new customBuf. If false, just use the existing value without
* copying. If omitted, then copy the contents (unless value is already a Blob).
* IMPORTANT: If copy is false, if you keep a pointer to the value then you must
* treat the value as immutable and promise not to change it.
*/
var Blob = function Blob(value, copy)
{
if (copy == null)
copy = true;
if (value == null)
this.buffer = null;
else if (typeof value === 'object' && value instanceof Blob)
// Use the existing buffer. Don't need to check for copy.
this.buffer = value.buffer;
else {
if (typeof value === 'string')
// Convert from a string to utf-8 byte encoding.
this.buffer = new customBuf(value, 'utf8');
else {
if (copy)
// We are copying, so just make another customBuf.
this.buffer = new customBuf(value);
else {
if (typeof value === 'object' && value instanceof customBuf)
// We can use as-is.
this.buffer = value;
else
// We need a customBuf, so copy.
this.buffer = new customBuf(value);
}
}
}
};
exports.Blob = Blob;
/**
* Return the length of the immutable byte array.
* @returns {number} The length of the array. If buf() is null, return 0.
*/
Blob.prototype.size = function()
{
if (this.buffer != null)
return this.buffer.length;
else
return 0;
};
/**
* Return the immutable byte array. DO NOT change the contents of the customBuf.
* If you need to change it, make a copy.
* @returns {Buffer} The customBuf holding the immutable byte array, or null.
*/
Blob.prototype.buf = function()
{
return this.buffer;
};
/**
* Return true if the array is null, otherwise false.
* @returns {boolean} True if the array is null.
*/
Blob.prototype.isNull = function()
{
return this.buffer == null;
};
/**
* Return the hex representation of the bytes in the byte array.
* @returns {string} The hex string.
*/
Blob.prototype.toHex = function()
{
if (this.buffer == null)
return "";
else
return this.buffer.toString('hex');
};
},{"../buffer.js":25}],60:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
* Encapsulate a customBuf and support dynamic reallocation.
*/
var customBuf = require('../buffer.js').Buffer
/**
* Create a DynamicBuffer where this.array is a customBuf of size length.
* To access the array, use this.array or call slice.
* @constructor
* @param {number} length the initial length of the array. If null, use a default.
*/
var DynamicBuffer = function DynamicBuffer(length)
{
if (!length)
length = 16;
this.array = new customBuf(length);
};
exports.DynamicBuffer = DynamicBuffer;
/**
* Ensure that this.array has the length, reallocate and copy if necessary.
* Update the length of this.array which may be greater than length.
* @param {number} length The minimum length for the array.
*/
DynamicBuffer.prototype.ensureLength = function(length)
{
if (this.array.length >= length)
return;
// See if double is enough.
var newLength = this.array.length * 2;
if (length > newLength)
// The needed length is much greater, so use it.
newLength = length;
var newArray = new customBuf(newLength);
this.array.copy(newArray);
this.array = newArray;
};
/**
* Copy the value to this.array at offset, reallocating if necessary.
* @param {Buffer} value The buffer to copy.
* @param {number} offset The offset in the buffer to start copying into.
*/
DynamicBuffer.prototype.copy = function(value, offset)
{
this.ensureLength(value.length + offset);
if (typeof value == 'object' && value instanceof customBuf)
value.copy(this.array, offset);
else
// Need to make value a customBuf to copy.
new customBuf(value).copy(this.array, offset);
};
/**
* Ensure that this.array has the length. If necessary, reallocate the array
* and shift existing data to the back of the new array.
* Update the length of this.array which may be greater than length.
* @param {number} length The minimum length for the array.
*/
DynamicBuffer.prototype.ensureLengthFromBack = function(length)
{
if (this.array.length >= length)
return;
// See if double is enough.
var newLength = this.array.length * 2;
if (length > newLength)
// The needed length is much greater, so use it.
newLength = length;
var newArray = new customBuf(newLength);
// Copy to the back of newArray.
this.array.copy(newArray, newArray.length - this.array.length);
this.array = newArray;
};
/**
* First call ensureLengthFromBack to make sure the bytearray has
* offsetFromBack bytes, then copy value into the array starting
* offsetFromBack bytes from the back of the array.
* @param {Buffer} value The buffer to copy.
* @param {offsetFromBack} offset The offset from the back of the array to start
* copying.
*/
DynamicBuffer.prototype.copyFromBack = function(value, offsetFromBack)
{
this.ensureLengthFromBack(offsetFromBack);
if (typeof value == 'object' && value instanceof customBuf)
value.copy(this.array, this.array.length - offsetFromBack);
else
// Need to make value a customBuf to copy.
new customBuf(value).copy(this.array, this.array.length - offsetFromBack);
};
/**
* Return this.array.slice(begin, end);
* @param {number} begin The begin index for the slice.
* @param {number} end The end index for the slice.
* @returns {Buffer} The buffer slice.
*/
DynamicBuffer.prototype.slice = function(begin, end)
{
return this.array.slice(begin, end);
};
},{"../buffer.js":25}],61:[function(require,module,exports){
(function (Buffer){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
var customBuf = require('../buffer.js').Buffer
var DataUtils = require('../encoding/data-utils.js').DataUtils;
var BinaryXMLDecoder = require('../encoding/binary-xml-decoder.js').BinaryXMLDecoder;
var NDNProtocolDTags = require('./ndn-protoco-id-tags.js').NDNProtocolDTags;
var Name = require('../name.js').Name;
/**
* Create a context for getting the response from the name enumeration command, as neede by getComponents.
* (To do name enumeration, call the static method NameEnumeration.getComponents.)
* @param {Face} face The Face object for using expressInterest.
* @param {function} onComponents The onComponents callback given to getComponents.
*/
var NameEnumeration = function NameEnumeration(face, onComponents)
{
this.face = face;
this.onComponents = onComponents;
this.contentParts = [];
var self = this;
this.onData = function(interest, data) { self.processData(data); };
this.onTimeout = function(interest) { self.processTimeout(); };
};
exports.NameEnumeration = NameEnumeration;
/**
* Use the name enumeration protocol to get the child components of the name prefix.
* @param {Face} face The Face object for using expressInterest.
* @param {Name} name The name prefix for finding the child components.
* @param {function} onComponents On getting the response, this calls onComponents(components) where
* components is an array of customBuf name components. If there is no response, this calls onComponents(null).
*/
NameEnumeration.getComponents = function(face, prefix, onComponents)
{
var command = new Name(prefix);
// Add %C1.E.be
command.add([0xc1, 0x2e, 0x45, 0x2e, 0x62, 0x65])
var enumeration = new NameEnumeration(face, onComponents);
face.expressInterest(command, enumeration.onData, enumeration.onTimeout);
};
/**
* Parse the response from the name enumeration command and call this.onComponents.
* @param {Data} data
*/
NameEnumeration.prototype.processData = function(data)
{
try {
if (!NameEnumeration.endsWithSegmentNumber(data.name))
// We don't expect a name without a segment number. Treat it as a bad packet.
this.onComponents(null);
else {
var segmentNumber = DataUtils.bigEndianToUnsignedInt
(data.name.get(data.name.size() - 1).getValue());
// Each time we get a segment, we put it in contentParts, so its length follows the segment numbers.
var expectedSegmentNumber = this.contentParts.length;
if (segmentNumber != expectedSegmentNumber)
// Try again to get the expected segment. This also includes the case where the first segment is not segment 0.
this.face.expressInterest
(data.name.getPrefix(-1).addSegment(expectedSegmentNumber), this.onData, this.onTimeout);
else {
// Save the content and check if we are finished.
this.contentParts.push(data.content);
if (data.signedInfo != null && data.signedInfo.finalBlockID != null) {
var finalSegmentNumber = DataUtils.bigEndianToUnsignedInt(data.signedInfo.finalBlockID);
if (segmentNumber == finalSegmentNumber) {
// We are finished. Parse and return the result.
this.onComponents(NameEnumeration.parseComponents(Buffer.concat(this.contentParts)));
return;
}
}
// Fetch the next segment.
this.face.expressInterest
(data.name.getPrefix(-1).addSegment(expectedSegmentNumber + 1), this.onData, this.onTimeout);
}
}
} catch (ex) {
console.log("NameEnumeration: ignoring exception: " + ex);
}
};
/**
* Just call onComponents(null).
*/
NameEnumeration.prototype.processTimeout = function()
{
try {
this.onComponents(null);
} catch (ex) {
console.log("NameEnumeration: ignoring exception: " + ex);
}
};
/**
* Parse the content as a name enumeration response and return an array of components. This makes a copy of the component.
* @param {Uint8Array} content The content to parse.
* @returns {Array<Buffer>} The array of components.
*/
NameEnumeration.parseComponents = function(content)
{
var components = [];
var decoder = new BinaryXMLDecoder(content);
decoder.readElementStartDTag(NDNProtocolDTags.Collection);
while (decoder.peekDTag(NDNProtocolDTags.Link)) {
decoder.readElementStartDTag(NDNProtocolDTags.Link);
decoder.readElementStartDTag(NDNProtocolDTags.Name);
components.push(new customBuf(decoder.readBinaryDTagElement(NDNProtocolDTags.Component)));
decoder.readElementClose();
decoder.readElementClose();
}
decoder.readElementClose();
return components;
};
/**
* Check if the last component in the name is a segment number.
* TODO: Move to Name class.
* @param {Name} name
* @returns {Boolean} True if the name ends with a segment number, otherwise false.
*/
NameEnumeration.endsWithSegmentNumber = function(name) {
return name.components != null && name.size() >= 1 &&
name.get(name.size() - 1).getValue().length >= 1 &&
name.get(name.size() - 1).getValue()[0] == 0;
};
}).call(this,require("buffer").Buffer)
},{"../buffer.js":25,"../encoding/binary-xml-decoder.js":28,"../encoding/data-utils.js":32,"../name.js":53,"./ndn-protoco-id-tags.js":62,"buffer":1}],62:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Meki Cheraoui
* See COPYING for copyright and distribution information.
* This class contains all NDNx tags
*/
var NDNProtocolDTags = {
/**
* Note if you add one of these, add it to the reverse string map as well.
* Emphasize getting the work done at compile time over trying to make something
* flexible and developer error-proof.
*/
Any : 13,
Name : 14,
Component : 15,
Certificate : 16,
Collection : 17,
CompleteName : 18,
Content : 19,
SignedInfo : 20,
ContentDigest : 21,
ContentHash : 22,
Count : 24,
Header : 25,
Interest : 26, /* 20090915 */
Key : 27,
KeyLocator : 28,
KeyName : 29,
Length : 30,
Link : 31,
LinkAuthenticator : 32,
NameComponentCount : 33, /* DeprecatedInInterest */
RootDigest : 36,
Signature : 37,
Start : 38,
Timestamp : 39,
Type : 40,
Nonce : 41,
Scope : 42,
Exclude : 43,
Bloom : 44,
BloomSeed : 45,
AnswerOriginKind : 47,
InterestLifetime : 48,
Witness : 53,
SignatureBits : 54,
DigestAlgorithm : 55,
BlockSize : 56,
FreshnessSeconds : 58,
FinalBlockID : 59,
PublisherPublicKeyDigest : 60,
PublisherCertificateDigest : 61,
PublisherIssuerKeyDigest : 62,
PublisherIssuerCertificateDigest : 63,
Data : 64, /* 20090915 */
WrappedKey : 65,
WrappingKeyIdentifier : 66,
WrapAlgorithm : 67,
KeyAlgorithm : 68,
Label : 69,
EncryptedKey : 70,
EncryptedNonceKey : 71,
WrappingKeyName : 72,
Action : 73,
FaceID : 74,
IPProto : 75,
Host : 76,
Port : 77,
MulticastInterface : 78,
ForwardingFlags : 79,
FaceInstance : 80,
ForwardingEntry : 81,
MulticastTTL : 82,
MinSuffixComponents : 83,
MaxSuffixComponents : 84,
ChildSelector : 85,
RepositoryInfo : 86,
Version : 87,
RepositoryVersion : 88,
GlobalPrefix : 89,
LocalName : 90,
Policy : 91,
Namespace : 92,
GlobalPrefixName : 93,
PolicyVersion : 94,
KeyValueSet : 95,
KeyValuePair : 96,
IntegerValue : 97,
DecimalValue : 98,
StringValue : 99,
BinaryValue : 100,
NameValue : 101,
Entry : 102,
ACL : 103,
ParameterizedName : 104,
Prefix : 105,
Suffix : 106,
Root : 107,
ProfileName : 108,
Parameters : 109,
InfoString : 110,
// 111 unallocated
StatusResponse : 112,
StatusCode : 113,
StatusText : 114,
// Sync protocol
SyncNode : 115,
SyncNodeKind : 116,
SyncNodeElement : 117,
SyncVersion : 118,
SyncNodeElements : 119,
SyncContentHash : 120,
SyncLeafCount : 121,
SyncTreeDepth : 122,
SyncByteCount : 123,
ConfigSlice : 124,
ConfigSliceList : 125,
ConfigSliceOp : 126,
// Remember to keep in sync with schema/tagnames.csvsdict
NDNProtocolDataUnit : 17702112,
NDNPROTOCOL_DATA_UNIT : "NDNProtocolDataUnit"
};
exports.NDNProtocolDTags = NDNProtocolDTags;
var NDNProtocolDTagsStrings = [
null, null, null, null, null, null, null, null, null, null, null,
null, null,
"Any", "Name", "Component", "Certificate", "Collection", "CompleteName",
"Content", "SignedInfo", "ContentDigest", "ContentHash", null, "Count", "Header",
"Interest", "Key", "KeyLocator", "KeyName", "Length", "Link", "LinkAuthenticator",
"NameComponentCount", null, null, "RootDigest", "Signature", "Start", "Timestamp", "Type",
"Nonce", "Scope", "Exclude", "Bloom", "BloomSeed", null, "AnswerOriginKind",
"InterestLifetime", null, null, null, null, "Witness", "SignatureBits", "DigestAlgorithm", "BlockSize",
null, "FreshnessSeconds", "FinalBlockID", "PublisherPublicKeyDigest", "PublisherCertificateDigest",
"PublisherIssuerKeyDigest", "PublisherIssuerCertificateDigest", "Data",
"WrappedKey", "WrappingKeyIdentifier", "WrapAlgorithm", "KeyAlgorithm", "Label",
"EncryptedKey", "EncryptedNonceKey", "WrappingKeyName", "Action", "FaceID", "IPProto",
"Host", "Port", "MulticastInterface", "ForwardingFlags", "FaceInstance",
"ForwardingEntry", "MulticastTTL", "MinSuffixComponents", "MaxSuffixComponents", "ChildSelector",
"RepositoryInfo", "Version", "RepositoryVersion", "GlobalPrefix", "LocalName",
"Policy", "Namespace", "GlobalPrefixName", "PolicyVersion", "KeyValueSet", "KeyValuePair",
"IntegerValue", "DecimalValue", "StringValue", "BinaryValue", "NameValue", "Entry",
"ACL", "ParameterizedName", "Prefix", "Suffix", "Root", "ProfileName", "Parameters",
"InfoString", null,
"StatusResponse", "StatusCode", "StatusText", "SyncNode", "SyncNodeKind", "SyncNodeElement",
"SyncVersion", "SyncNodeElements", "SyncContentHash", "SyncLeafCount", "SyncTreeDepth", "SyncByteCount",
"ConfigSlice", "ConfigSliceList", "ConfigSliceOp" ];
exports.NDNProtocolDTagsStrings = NDNProtocolDTagsStrings;
},{}],63:[function(require,module,exports){
/**
* Copyright (C) 2013-2014 Regents of the University of California.
* @author: Meki Cheraoui
* See COPYING for copyright and distribution information.
* This class represents NDNTime Objects
*/
var LOG = require('../log.js').Log.LOG;
/**
* @constructor
*/
var NDNTime = function NDNTime(input)
{
this.NANOS_MAX = 999877929;
if (typeof input =='number')
this.msec = input;
else {
if (LOG > 1) console.log('UNRECOGNIZED TYPE FOR TIME');
}
};
exports.NDNTime = NDNTime;
NDNTime.prototype.getJavascriptDate = function()
{
var d = new Date();
d.setTime(this.msec);
return d
};
},{"../log.js":51}],64:[function(require,module,exports){
/**
* Copyright (C) 2013 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
* See COPYING for copyright and distribution information.
*/
var customBuf = require('../buffer.js').Buffer
var Blob = require('./blob.js').Blob;
/**
* A SignedBlob extends Blob to keep the offsets of a signed portion (e.g., the
* bytes of Data packet). This inherits from Blob, including Blob.size and Blob.buf.
* @param {Blob|Buffer|Array<number>} value (optional) If value is a Blob, take
* another pointer to the customBuf without copying. If value is a customBuf or byte
* array, copy to create a new customBuf. If omitted, buf() will return null.
* @param {number} signedPortionBeginOffset (optional) The offset in the
* encoding of the beginning of the signed portion. If omitted, set to 0.
* @param {number} signedPortionEndOffset (optional) The offset in the encoding
* of the end of the signed portion. If omitted, set to 0.
*/
var SignedBlob = function SignedBlob(value, signedPortionBeginOffset, signedPortionEndOffset)
{
// Call the base constructor.
Blob.call(this, value);
if (this.buffer == null) {
this.signedPortionBeginOffset = 0;
this.signedPortionEndOffset = 0;
}
else if (typeof value === 'object' && value instanceof SignedBlob) {
// Copy the SignedBlob, allowing override for offsets.
this.signedPortionBeginOffset = signedPortionBeginOffset == null ?
value.signedPortionBeginOffset : signedPortionBeginOffset;
this.signedPortionEndOffset = signedPortionEndOffset == null ?
value.signedPortionEndOffset : signedPortionEndOffset;
}
else {
this.signedPortionBeginOffset = signedPortionBeginOffset || 0;
this.signedPortionEndOffset = signedPortionEndOffset || 0;
}
if (this.buffer == null)
this.signedBuffer = null;
else
this.signedBuffer = this.buffer.slice
(this.signedPortionBeginOffset, this.signedPortionEndOffset);
};
SignedBlob.prototype = new Blob();
SignedBlob.prototype.name = "SignedBlob";
exports.SignedBlob = SignedBlob;
/**
* Return the length of the signed portion of the immutable byte array.
* @returns {number} The length of the signed portion. If signedBuf() is null,
* return 0.
*/
SignedBlob.prototype.signedSize = function()
{
if (this.signedBuffer != null)
return this.signedBuffer.length;
else
return 0;
};
/**
* Return a the signed portion of the immutable byte array.
* @returns {Buffer} A slice into the customBuf which is the signed portion.
* If the pointer to the array is null, return null.
*/
SignedBlob.prototype.signedBuf = function()
{
if (this.signedBuffer != null)
return this.signedBuffer;
else
return null;
};
/**
* Return the offset in the array of the beginning of the signed portion.
* @returns {number} The offset in the array.
*/
SignedBlob.prototype.getSignedPortionBeginOffset = function()
{
return this.signedPortionBeginOffset;
};
/**
* Return the offset in the array of the end of the signed portion.
* @returns {number} The offset in the array.
*/
SignedBlob.prototype.getSignedPortionEndOffset = function()
{
return this.signedPortionEndOffset;
};
},{"../buffer.js":25,"./blob.js":59}],65:[function(require,module,exports){
(function(){
// Copyright (c) 2005 Tom Wu
// All Rights Reserved.
// See "LICENSE" for details.
// Basic JavaScript BN library - subset useful for RSA encryption.
// Bits per digit
var dbits;
// JavaScript engine analysis
var canary = 0xdeadbeefcafe;
var j_lm = ((canary&0xffffff)==0xefcafe);
// (public) Constructor
function BigInteger(a,b,c) {
if(a != null)
if("number" == typeof a) this.fromNumber(a,b,c);
else if(b == null && "string" != typeof a) this.fromString(a,256);
else this.fromString(a,b);
}
// return new, unset BigInteger
function nbi() { return new BigInteger(null); }
// am: Compute w_j += (x*this_i), propagate carries,
// c is initial carry, returns final carry.
// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
// We need to select the fastest one that works in this environment.
// am1: use a single mult and divide to get the high bits,
// max digit bits should be 26 because
// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
function am1(i,x,w,j,c,n) {
while(--n >= 0) {
var v = x*this[i++]+w[j]+c;
c = Math.floor(v/0x4000000);
w[j++] = v&0x3ffffff;
}
return c;
}
// am2 avoids a big mult-and-extract completely.
// Max digit bits should be <= 30 because we do bitwise ops
// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
function am2(i,x,w,j,c,n) {
var xl = x&0x7fff, xh = x>>15;
while(--n >= 0) {
var l = this[i]&0x7fff;
var h = this[i++]>>15;
var m = xh*l+h*xl;
l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
w[j++] = l&0x3fffffff;
}
return c;
}
// Alternately, set max digit bits to 28 since some
// browsers slow down when dealing with 32-bit numbers.
function am3(i,x,w,j,c,n) {
var xl = x&0x3fff, xh = x>>14;
while(--n >= 0) {
var l = this[i]&0x3fff;
var h = this[i++]>>14;
var m = xh*l+h*xl;
l = xl*l+((m&0x3fff)<<14)+w[j]+c;
c = (l>>28)+(m>>14)+xh*h;
w[j++] = l&0xfffffff;
}
return c;
}
var inBrowser = typeof navigator !== "undefined";
if(inBrowser && j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
BigInteger.prototype.am = am2;
dbits = 30;
}
else if(inBrowser && j_lm && (navigator.appName != "Netscape")) {
BigInteger.prototype.am = am1;
dbits = 26;
}
else { // Mozilla/Netscape seems to prefer am3
BigInteger.prototype.am = am3;
dbits = 28;
}
BigInteger.prototype.DB = dbits;
BigInteger.prototype.DM = ((1<<dbits)-1);
BigInteger.prototype.DV = (1<<dbits);
var BI_FP = 52;
BigInteger.prototype.FV = Math.pow(2,BI_FP);
BigInteger.prototype.F1 = BI_FP-dbits;
BigInteger.prototype.F2 = 2*dbits-BI_FP;
// Digit conversions
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
var BI_RC = new Array();
var rr,vv;
rr = "0".charCodeAt(0);
for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
rr = "a".charCodeAt(0);
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
rr = "A".charCodeAt(0);
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
function int2char(n) { return BI_RM.charAt(n); }
function intAt(s,i) {
var c = BI_RC[s.charCodeAt(i)];
return (c==null)?-1:c;
}
// (protected) copy this to r
function bnpCopyTo(r) {
for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
r.t = this.t;
r.s = this.s;
}
// (protected) set from integer value x, -DV <= x < DV
function bnpFromInt(x) {
this.t = 1;
this.s = (x<0)?-1:0;
if(x > 0) this[0] = x;
else if(x < -1) this[0] = x+DV;
else this.t = 0;
}
// return bigint initialized to value
function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
// (protected) set from string and radix
function bnpFromString(s,b) {
var k;
if(b == 16) k = 4;
else if(b == 8) k = 3;
else if(b == 256) k = 8; // byte array
else if(b == 2) k = 1;
else if(b == 32) k = 5;
else if(b == 4) k = 2;
else { this.fromRadix(s,b); return; }
this.t = 0;
this.s = 0;
var i = s.length, mi = false, sh = 0;
while(--i >= 0) {
var x = (k==8)?s[i]&0xff:intAt(s,i);
if(x < 0) {
if(s.charAt(i) == "-") mi = true;
continue;
}
mi = false;
if(sh == 0)
this[this.t++] = x;
else if(sh+k > this.DB) {
this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
this[this.t++] = (x>>(this.DB-sh));
}
else
this[this.t-1] |= x<<sh;
sh += k;
if(sh >= this.DB) sh -= this.DB;
}
if(k == 8 && (s[0]&0x80) != 0) {
this.s = -1;
if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
}
this.clamp();
if(mi) BigInteger.ZERO.subTo(this,this);
}
// (protected) clamp off excess high words
function bnpClamp() {
var c = this.s&this.DM;
while(this.t > 0 && this[this.t-1] == c) --this.t;
}
// (public) return string representation in given radix
function bnToString(b) {
if(this.s < 0) return "-"+this.negate().toString(b);
var k;
if(b == 16) k = 4;
else if(b == 8) k = 3;
else if(b == 2) k = 1;
else if(b == 32) k = 5;
else if(b == 4) k = 2;
else return this.toRadix(b);
var km = (1<<k)-1, d, m = false, r = "", i = this.t;
var p = this.DB-(i*this.DB)%k;
if(i-- > 0) {
if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
while(i >= 0) {
if(p < k) {
d = (this[i]&((1<<p)-1))<<(k-p);
d |= this[--i]>>(p+=this.DB-k);
}
else {
d = (this[i]>>(p-=k))&km;
if(p <= 0) { p += this.DB; --i; }
}
if(d > 0) m = true;
if(m) r += int2char(d);
}
}
return m?r:"0";
}
// (public) -this
function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
// (public) |this|
function bnAbs() { return (this.s<0)?this.negate():this; }
// (public) return + if this > a, - if this < a, 0 if equal
function bnCompareTo(a) {
var r = this.s-a.s;
if(r != 0) return r;
var i = this.t;
r = i-a.t;
if(r != 0) return (this.s<0)?-r:r;
while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
return 0;
}
// returns bit length of the integer x
function nbits(x) {
var r = 1, t;
if((t=x>>>16) != 0) { x = t; r += 16; }
if((t=x>>8) != 0) { x = t; r += 8; }
if((t=x>>4) != 0) { x = t; r += 4; }
if((t=x>>2) != 0) { x = t; r += 2; }
if((t=x>>1) != 0) { x = t; r += 1; }
return r;
}
// (public) return the number of bits in "this"
function bnBitLength() {
if(this.t <= 0) return 0;
return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
}
// (protected) r = this << n*DB
function bnpDLShiftTo(n,r) {
var i;
for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
for(i = n-1; i >= 0; --i) r[i] = 0;
r.t = this.t+n;
r.s = this.s;
}
// (protected) r = this >> n*DB
function bnpDRShiftTo(n,r) {
for(var i = n; i < this.t; ++i) r[i-n] = this[i];
r.t = Math.max(this.t-n,0);
r.s = this.s;
}
// (protected) r = this << n
function bnpLShiftTo(n,r) {
var bs = n%this.DB;
var cbs = this.DB-bs;
var bm = (1<<cbs)-1;
var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
for(i = this.t-1; i >= 0; --i) {
r[i+ds+1] = (this[i]>>cbs)|c;
c = (this[i]&bm)<<bs;
}
for(i = ds-1; i >= 0; --i) r[i] = 0;
r[ds] = c;
r.t = this.t+ds+1;
r.s = this.s;
r.clamp();
}
// (protected) r = this >> n
function bnpRShiftTo(n,r) {
r.s = this.s;
var ds = Math.floor(n/this.DB);
if(ds >= this.t) { r.t = 0; return; }
var bs = n%this.DB;
var cbs = this.DB-bs;
var bm = (1<<bs)-1;
r[0] = this[ds]>>bs;
for(var i = ds+1; i < this.t; ++i) {
r[i-ds-1] |= (this[i]&bm)<<cbs;
r[i-ds] = this[i]>>bs;
}
if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
r.t = this.t-ds;
r.clamp();
}
// (protected) r = this - a
function bnpSubTo(a,r) {
var i = 0, c = 0, m = Math.min(a.t,this.t);
while(i < m) {
c += this[i]-a[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
if(a.t < this.t) {
c -= a.s;
while(i < this.t) {
c += this[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
c += this.s;
}
else {
c += this.s;
while(i < a.t) {
c -= a[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
c -= a.s;
}
r.s = (c<0)?-1:0;
if(c < -1) r[i++] = this.DV+c;
else if(c > 0) r[i++] = c;
r.t = i;
r.clamp();
}
// (protected) r = this * a, r != this,a (HAC 14.12)
// "this" should be the larger one if appropriate.
function bnpMultiplyTo(a,r) {
var x = this.abs(), y = a.abs();
var i = x.t;
r.t = i+y.t;
while(--i >= 0) r[i] = 0;
for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
r.s = 0;
r.clamp();
if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
}
// (protected) r = this^2, r != this (HAC 14.16)
function bnpSquareTo(r) {
var x = this.abs();
var i = r.t = 2*x.t;
while(--i >= 0) r[i] = 0;
for(i = 0; i < x.t-1; ++i) {
var c = x.am(i,x[i],r,2*i,0,1);
if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
r[i+x.t] -= x.DV;
r[i+x.t+1] = 1;
}
}
if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
r.s = 0;
r.clamp();
}
// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
// r != q, this != m. q or r may be null.
function bnpDivRemTo(m,q,r) {
var pm = m.abs();
if(pm.t <= 0) return;
var pt = this.abs();
if(pt.t < pm.t) {
if(q != null) q.fromInt(0);
if(r != null) this.copyTo(r);
return;
}
if(r == null) r = nbi();
var y = nbi(), ts = this.s, ms = m.s;
var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus
if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
else { pm.copyTo(y); pt.copyTo(r); }
var ys = y.t;
var y0 = y[ys-1];
if(y0 == 0) return;
var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
var i = r.t, j = i-ys, t = (q==null)?nbi():q;
y.dlShiftTo(j,t);
if(r.compareTo(t) >= 0) {
r[r.t++] = 1;
r.subTo(t,r);
}
BigInteger.ONE.dlShiftTo(ys,t);
t.subTo(y,y); // "negative" y so we can replace sub with am later
while(y.t < ys) y[y.t++] = 0;
while(--j >= 0) {
// Estimate quotient digit
var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out
y.dlShiftTo(j,t);
r.subTo(t,r);
while(r[i] < --qd) r.subTo(t,r);
}
}
if(q != null) {
r.drShiftTo(ys,q);
if(ts != ms) BigInteger.ZERO.subTo(q,q);
}
r.t = ys;
r.clamp();
if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
if(ts < 0) BigInteger.ZERO.subTo(r,r);
}
// (public) this mod a
function bnMod(a) {
var r = nbi();
this.abs().divRemTo(a,null,r);
if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
return r;
}
// Modular reduction using "classic" algorithm
function Classic(m) { this.m = m; }
function cConvert(x) {
if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
else return x;
}
function cRevert(x) { return x; }
function cReduce(x) { x.divRemTo(this.m,null,x); }
function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
Classic.prototype.convert = cConvert;
Classic.prototype.revert = cRevert;
Classic.prototype.reduce = cReduce;
Classic.prototype.mulTo = cMulTo;
Classic.prototype.sqrTo = cSqrTo;
// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
// justification:
// xy == 1 (mod m)
// xy = 1+km
// xy(2-xy) = (1+km)(1-km)
// x[y(2-xy)] = 1-k^2m^2
// x[y(2-xy)] == 1 (mod m^2)
// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
// JS multiply "overflows" differently from C/C++, so care is needed here.
function bnpInvDigit() {
if(this.t < 1) return 0;
var x = this[0];
if((x&1) == 0) return 0;
var y = x&3; // y == 1/x mod 2^2
y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8
y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16
// last step - calculate inverse mod DV directly;
// assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits
// we really want the negative inverse, and -DV < y < DV
return (y>0)?this.DV-y:-y;
}
// Montgomery reduction
function Montgomery(m) {
this.m = m;
this.mp = m.invDigit();
this.mpl = this.mp&0x7fff;
this.mph = this.mp>>15;
this.um = (1<<(m.DB-15))-1;
this.mt2 = 2*m.t;
}
// xR mod m
function montConvert(x) {
var r = nbi();
x.abs().dlShiftTo(this.m.t,r);
r.divRemTo(this.m,null,r);
if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
return r;
}
// x/R mod m
function montRevert(x) {
var r = nbi();
x.copyTo(r);
this.reduce(r);
return r;
}
// x = x/R mod m (HAC 14.32)
function montReduce(x) {
while(x.t <= this.mt2) // pad x so am has enough room later
x[x.t++] = 0;
for(var i = 0; i < this.m.t; ++i) {
// faster way of calculating u0 = x[i]*mp mod DV
var j = x[i]&0x7fff;
var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
// use am to combine the multiply-shift-add into one call
j = i+this.m.t;
x[j] += this.m.am(0,u0,x,i,0,this.m.t);
// propagate carry
while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
}
x.clamp();
x.drShiftTo(this.m.t,x);
if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
}
// r = "x^2/R mod m"; x != r
function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
// r = "xy/R mod m"; x,y != r
function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
Montgomery.prototype.convert = montConvert;
Montgomery.prototype.revert = montRevert;
Montgomery.prototype.reduce = montReduce;
Montgomery.prototype.mulTo = montMulTo;
Montgomery.prototype.sqrTo = montSqrTo;
// (protected) true iff this is even
function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
function bnpExp(e,z) {
if(e > 0xffffffff || e < 1) return BigInteger.ONE;
var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
g.copyTo(r);
while(--i >= 0) {
z.sqrTo(r,r2);
if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
else { var t = r; r = r2; r2 = t; }
}
return z.revert(r);
}
// (public) this^e % m, 0 <= e < 2^32
function bnModPowInt(e,m) {
var z;
if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
return this.exp(e,z);
}
// protected
BigInteger.prototype.copyTo = bnpCopyTo;
BigInteger.prototype.fromInt = bnpFromInt;
BigInteger.prototype.fromString = bnpFromString;
BigInteger.prototype.clamp = bnpClamp;
BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
BigInteger.prototype.drShiftTo = bnpDRShiftTo;
BigInteger.prototype.lShiftTo = bnpLShiftTo;
BigInteger.prototype.rShiftTo = bnpRShiftTo;
BigInteger.prototype.subTo = bnpSubTo;
BigInteger.prototype.multiplyTo = bnpMultiplyTo;
BigInteger.prototype.squareTo = bnpSquareTo;
BigInteger.prototype.divRemTo = bnpDivRemTo;
BigInteger.prototype.invDigit = bnpInvDigit;
BigInteger.prototype.isEven = bnpIsEven;
BigInteger.prototype.exp = bnpExp;
// public
BigInteger.prototype.toString = bnToString;
BigInteger.prototype.negate = bnNegate;
BigInteger.prototype.abs = bnAbs;
BigInteger.prototype.compareTo = bnCompareTo;
BigInteger.prototype.bitLength = bnBitLength;
BigInteger.prototype.mod = bnMod;
BigInteger.prototype.modPowInt = bnModPowInt;
// "constants"
BigInteger.ZERO = nbv(0);
BigInteger.ONE = nbv(1);
// Copyright (c) 2005-2009 Tom Wu
// All Rights Reserved.
// See "LICENSE" for details.
// Extended JavaScript BN functions, required for RSA private ops.
// Version 1.1: new BigInteger("0", 10) returns "proper" zero
// Version 1.2: square() API, isProbablePrime fix
// (public)
function bnClone() { var r = nbi(); this.copyTo(r); return r; }
// (public) return value as integer
function bnIntValue() {
if(this.s < 0) {
if(this.t == 1) return this[0]-this.DV;
else if(this.t == 0) return -1;
}
else if(this.t == 1) return this[0];
else if(this.t == 0) return 0;
// assumes 16 < DB < 32
return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
}
// (public) return value as byte
function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }
// (public) return value as short (assumes DB>=16)
function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
// (protected) return x s.t. r^x < DV
function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
// (public) 0 if this == 0, 1 if this > 0
function bnSigNum() {
if(this.s < 0) return -1;
else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
else return 1;
}
// (protected) convert to radix string
function bnpToRadix(b) {
if(b == null) b = 10;
if(this.signum() == 0 || b < 2 || b > 36) return "0";
var cs = this.chunkSize(b);
var a = Math.pow(b,cs);
var d = nbv(a), y = nbi(), z = nbi(), r = "";
this.divRemTo(d,y,z);
while(y.signum() > 0) {
r = (a+z.intValue()).toString(b).substr(1) + r;
y.divRemTo(d,y,z);
}
return z.intValue().toString(b) + r;
}
// (protected) convert from radix string
function bnpFromRadix(s,b) {
this.fromInt(0);
if(b == null) b = 10;
var cs = this.chunkSize(b);
var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
for(var i = 0; i < s.length; ++i) {
var x = intAt(s,i);
if(x < 0) {
if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
continue;
}
w = b*w+x;
if(++j >= cs) {
this.dMultiply(d);
this.dAddOffset(w,0);
j = 0;
w = 0;
}
}
if(j > 0) {
this.dMultiply(Math.pow(b,j));
this.dAddOffset(w,0);
}
if(mi) BigInteger.ZERO.subTo(this,this);
}
// (protected) alternate constructor
function bnpFromNumber(a,b,c) {
if("number" == typeof b) {
// new BigInteger(int,int,RNG)
if(a < 2) this.fromInt(1);
else {
this.fromNumber(a,c);
if(!this.testBit(a-1)) // force MSB set
this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
if(this.isEven()) this.dAddOffset(1,0); // force odd
while(!this.isProbablePrime(b)) {
this.dAddOffset(2,0);
if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
}
}
}
else {
// new BigInteger(int,RNG)
var x = new Array(), t = a&7;
x.length = (a>>3)+1;
b.nextBytes(x);
if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
this.fromString(x,256);
}
}
// (public) convert to bigendian byte array
function bnToByteArray() {
var i = this.t, r = new Array();
r[0] = this.s;
var p = this.DB-(i*this.DB)%8, d, k = 0;
if(i-- > 0) {
if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
r[k++] = d|(this.s<<(this.DB-p));
while(i >= 0) {
if(p < 8) {
d = (this[i]&((1<<p)-1))<<(8-p);
d |= this[--i]>>(p+=this.DB-8);
}
else {
d = (this[i]>>(p-=8))&0xff;
if(p <= 0) { p += this.DB; --i; }
}
if((d&0x80) != 0) d |= -256;
if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
if(k > 0 || d != this.s) r[k++] = d;
}
}
return r;
}
function bnEquals(a) { return(this.compareTo(a)==0); }
function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
// (protected) r = this op a (bitwise)
function bnpBitwiseTo(a,op,r) {
var i, f, m = Math.min(a.t,this.t);
for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
if(a.t < this.t) {
f = a.s&this.DM;
for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
r.t = this.t;
}
else {
f = this.s&this.DM;
for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
r.t = a.t;
}
r.s = op(this.s,a.s);
r.clamp();
}
// (public) this & a
function op_and(x,y) { return x&y; }
function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
// (public) this | a
function op_or(x,y) { return x|y; }
function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
// (public) this ^ a
function op_xor(x,y) { return x^y; }
function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
// (public) this & ~a
function op_andnot(x,y) { return x&~y; }
function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
// (public) ~this
function bnNot() {
var r = nbi();
for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
r.t = this.t;
r.s = ~this.s;
return r;
}
// (public) this << n
function bnShiftLeft(n) {
var r = nbi();
if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
return r;
}
// (public) this >> n
function bnShiftRight(n) {
var r = nbi();
if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
return r;
}
// return index of lowest 1-bit in x, x < 2^31
function lbit(x) {
if(x == 0) return -1;
var r = 0;
if((x&0xffff) == 0) { x >>= 16; r += 16; }
if((x&0xff) == 0) { x >>= 8; r += 8; }
if((x&0xf) == 0) { x >>= 4; r += 4; }
if((x&3) == 0) { x >>= 2; r += 2; }
if((x&1) == 0) ++r;
return r;
}
// (public) returns index of lowest 1-bit (or -1 if none)
function bnGetLowestSetBit() {
for(var i = 0; i < this.t; ++i)
if(this[i] != 0) return i*this.DB+lbit(this[i]);
if(this.s < 0) return this.t*this.DB;
return -1;
}
// return number of 1 bits in x
function cbit(x) {
var r = 0;
while(x != 0) { x &= x-1; ++r; }
return r;
}
// (public) return number of set bits
function bnBitCount() {
var r = 0, x = this.s&this.DM;
for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
return r;
}
// (public) true iff nth bit is set
function bnTestBit(n) {
var j = Math.floor(n/this.DB);
if(j >= this.t) return(this.s!=0);
return((this[j]&(1<<(n%this.DB)))!=0);
}
// (protected) this op (1<<n)
function bnpChangeBit(n,op) {
var r = BigInteger.ONE.shiftLeft(n);
this.bitwiseTo(r,op,r);
return r;
}
// (public) this | (1<<n)
function bnSetBit(n) { return this.changeBit(n,op_or); }
// (public) this & ~(1<<n)
function bnClearBit(n) { return this.changeBit(n,op_andnot); }
// (public) this ^ (1<<n)
function bnFlipBit(n) { return this.changeBit(n,op_xor); }
// (protected) r = this + a
function bnpAddTo(a,r) {
var i = 0, c = 0, m = Math.min(a.t,this.t);
while(i < m) {
c += this[i]+a[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
if(a.t < this.t) {
c += a.s;
while(i < this.t) {
c += this[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
c += this.s;
}
else {
c += this.s;
while(i < a.t) {
c += a[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
c += a.s;
}
r.s = (c<0)?-1:0;
if(c > 0) r[i++] = c;
else if(c < -1) r[i++] = this.DV+c;
r.t = i;
r.clamp();
}
// (public) this + a
function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
// (public) this - a
function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
// (public) this * a
function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
// (public) this^2
function bnSquare() { var r = nbi(); this.squareTo(r); return r; }
// (public) this / a
function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
// (public) this % a
function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
// (public) [this/a,this%a]
function bnDivideAndRemainder(a) {
var q = nbi(), r = nbi();
this.divRemTo(a,q,r);
return new Array(q,r);
}
// (protected) this *= n, this >= 0, 1 < n < DV
function bnpDMultiply(n) {
this[this.t] = this.am(0,n-1,this,0,0,this.t);
++this.t;
this.clamp();
}
// (protected) this += n << w words, this >= 0
function bnpDAddOffset(n,w) {
if(n == 0) return;
while(this.t <= w) this[this.t++] = 0;
this[w] += n;
while(this[w] >= this.DV) {
this[w] -= this.DV;
if(++w >= this.t) this[this.t++] = 0;
++this[w];
}
}
// A "null" reducer
function NullExp() {}
function nNop(x) { return x; }
function nMulTo(x,y,r) { x.multiplyTo(y,r); }
function nSqrTo(x,r) { x.squareTo(r); }
NullExp.prototype.convert = nNop;
NullExp.prototype.revert = nNop;
NullExp.prototype.mulTo = nMulTo;
NullExp.prototype.sqrTo = nSqrTo;
// (public) this^e
function bnPow(e) { return this.exp(e,new NullExp()); }
// (protected) r = lower n words of "this * a", a.t <= n
// "this" should be the larger one if appropriate.
function bnpMultiplyLowerTo(a,n,r) {
var i = Math.min(this.t+a.t,n);
r.s = 0; // assumes a,this >= 0
r.t = i;
while(i > 0) r[--i] = 0;
var j;
for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
r.clamp();
}
// (protected) r = "this * a" without lower n words, n > 0
// "this" should be the larger one if appropriate.
function bnpMultiplyUpperTo(a,n,r) {
--n;
var i = r.t = this.t+a.t-n;
r.s = 0; // assumes a,this >= 0
while(--i >= 0) r[i] = 0;
for(i = Math.max(n-this.t,0); i < a.t; ++i)
r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
r.clamp();
r.drShiftTo(1,r);
}
// Barrett modular reduction
function Barrett(m) {
// setup Barrett
this.r2 = nbi();
this.q3 = nbi();
BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
this.mu = this.r2.divide(m);
this.m = m;
}
function barrettConvert(x) {
if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
else if(x.compareTo(this.m) < 0) return x;
else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
}
function barrettRevert(x) { return x; }
// x = x mod m (HAC 14.42)
function barrettReduce(x) {
x.drShiftTo(this.m.t-1,this.r2);
if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
x.subTo(this.r2,x);
while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
}
// r = x^2 mod m; x != r
function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
// r = x*y mod m; x,y != r
function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
Barrett.prototype.convert = barrettConvert;
Barrett.prototype.revert = barrettRevert;
Barrett.prototype.reduce = barrettReduce;
Barrett.prototype.mulTo = barrettMulTo;
Barrett.prototype.sqrTo = barrettSqrTo;
// (public) this^e % m (HAC 14.85)
function bnModPow(e,m) {
var i = e.bitLength(), k, r = nbv(1), z;
if(i <= 0) return r;
else if(i < 18) k = 1;
else if(i < 48) k = 3;
else if(i < 144) k = 4;
else if(i < 768) k = 5;
else k = 6;
if(i < 8)
z = new Classic(m);
else if(m.isEven())
z = new Barrett(m);
else
z = new Montgomery(m);
// precomputation
var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;
g[1] = z.convert(this);
if(k > 1) {
var g2 = nbi();
z.sqrTo(g[1],g2);
while(n <= km) {
g[n] = nbi();
z.mulTo(g2,g[n-2],g[n]);
n += 2;
}
}
var j = e.t-1, w, is1 = true, r2 = nbi(), t;
i = nbits(e[j])-1;
while(j >= 0) {
if(i >= k1) w = (e[j]>>(i-k1))&km;
else {
w = (e[j]&((1<<(i+1))-1))<<(k1-i);
if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
}
n = k;
while((w&1) == 0) { w >>= 1; --n; }
if((i -= n) < 0) { i += this.DB; --j; }
if(is1) { // ret == 1, don't bother squaring or multiplying it
g[w].copyTo(r);
is1 = false;
}
else {
while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
z.mulTo(r2,g[w],r);
}
while(j >= 0 && (e[j]&(1<<i)) == 0) {
z.sqrTo(r,r2); t = r; r = r2; r2 = t;
if(--i < 0) { i = this.DB-1; --j; }
}
}
return z.revert(r);
}
// (public) gcd(this,a) (HAC 14.54)
function bnGCD(a) {
var x = (this.s<0)?this.negate():this.clone();
var y = (a.s<0)?a.negate():a.clone();
if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
var i = x.getLowestSetBit(), g = y.getLowestSetBit();
if(g < 0) return x;
if(i < g) g = i;
if(g > 0) {
x.rShiftTo(g,x);
y.rShiftTo(g,y);
}
while(x.signum() > 0) {
if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
if(x.compareTo(y) >= 0) {
x.subTo(y,x);
x.rShiftTo(1,x);
}
else {
y.subTo(x,y);
y.rShiftTo(1,y);
}
}
if(g > 0) y.lShiftTo(g,y);
return y;
}
// (protected) this % n, n < 2^26
function bnpModInt(n) {
if(n <= 0) return 0;
var d = this.DV%n, r = (this.s<0)?n-1:0;
if(this.t > 0)
if(d == 0) r = this[0]%n;
else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
return r;
}
// (public) 1/this % m (HAC 14.61)
function bnModInverse(m) {
var ac = m.isEven();
if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
var u = m.clone(), v = this.clone();
var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
while(u.signum() != 0) {
while(u.isEven()) {
u.rShiftTo(1,u);
if(ac) {
if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
a.rShiftTo(1,a);
}
else if(!b.isEven()) b.subTo(m,b);
b.rShiftTo(1,b);
}
while(v.isEven()) {
v.rShiftTo(1,v);
if(ac) {
if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
c.rShiftTo(1,c);
}
else if(!d.isEven()) d.subTo(m,d);
d.rShiftTo(1,d);
}
if(u.compareTo(v) >= 0) {
u.subTo(v,u);
if(ac) a.subTo(c,a);
b.subTo(d,b);
}
else {
v.subTo(u,v);
if(ac) c.subTo(a,c);
d.subTo(b,d);
}
}
if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
if(d.compareTo(m) >= 0) return d.subtract(m);
if(d.signum() < 0) d.addTo(m,d); else return d;
if(d.signum() < 0) return d.add(m); else return d;
}
var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];
var lplim = (1<<26)/lowprimes[lowprimes.length-1];
// (public) test primality with certainty >= 1-.5^t
function bnIsProbablePrime(t) {
var i, x = this.abs();
if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
for(i = 0; i < lowprimes.length; ++i)
if(x[0] == lowprimes[i]) return true;
return false;
}
if(x.isEven()) return false;
i = 1;
while(i < lowprimes.length) {
var m = lowprimes[i], j = i+1;
while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
m = x.modInt(m);
while(i < j) if(m%lowprimes[i++] == 0) return false;
}
return x.millerRabin(t);
}
// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
function bnpMillerRabin(t) {
var n1 = this.subtract(BigInteger.ONE);
var k = n1.getLowestSetBit();
if(k <= 0) return false;
var r = n1.shiftRight(k);
t = (t+1)>>1;
if(t > lowprimes.length) t = lowprimes.length;
var a = nbi();
for(var i = 0; i < t; ++i) {
//Pick bases at random, instead of starting at 2
a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);
var y = a.modPow(r,this);
if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
var j = 1;
while(j++ < k && y.compareTo(n1) != 0) {
y = y.modPowInt(2,this);
if(y.compareTo(BigInteger.ONE) == 0) return false;
}
if(y.compareTo(n1) != 0) return false;
}
}
return true;
}
// protected
BigInteger.prototype.chunkSize = bnpChunkSize;
BigInteger.prototype.toRadix = bnpToRadix;
BigInteger.prototype.fromRadix = bnpFromRadix;
BigInteger.prototype.fromNumber = bnpFromNumber;
BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
BigInteger.prototype.changeBit = bnpChangeBit;
BigInteger.prototype.addTo = bnpAddTo;
BigInteger.prototype.dMultiply = bnpDMultiply;
BigInteger.prototype.dAddOffset = bnpDAddOffset;
BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
BigInteger.prototype.modInt = bnpModInt;
BigInteger.prototype.millerRabin = bnpMillerRabin;
// public
BigInteger.prototype.clone = bnClone;
BigInteger.prototype.intValue = bnIntValue;
BigInteger.prototype.byteValue = bnByteValue;
BigInteger.prototype.shortValue = bnShortValue;
BigInteger.prototype.signum = bnSigNum;
BigInteger.prototype.toByteArray = bnToByteArray;
BigInteger.prototype.equals = bnEquals;
BigInteger.prototype.min = bnMin;
BigInteger.prototype.max = bnMax;
BigInteger.prototype.and = bnAnd;
BigInteger.prototype.or = bnOr;
BigInteger.prototype.xor = bnXor;
BigInteger.prototype.andNot = bnAndNot;
BigInteger.prototype.not = bnNot;
BigInteger.prototype.shiftLeft = bnShiftLeft;
BigInteger.prototype.shiftRight = bnShiftRight;
BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
BigInteger.prototype.bitCount = bnBitCount;
BigInteger.prototype.testBit = bnTestBit;
BigInteger.prototype.setBit = bnSetBit;
BigInteger.prototype.clearBit = bnClearBit;
BigInteger.prototype.flipBit = bnFlipBit;
BigInteger.prototype.add = bnAdd;
BigInteger.prototype.subtract = bnSubtract;
BigInteger.prototype.multiply = bnMultiply;
BigInteger.prototype.divide = bnDivide;
BigInteger.prototype.remainder = bnRemainder;
BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
BigInteger.prototype.modPow = bnModPow;
BigInteger.prototype.modInverse = bnModInverse;
BigInteger.prototype.pow = bnPow;
BigInteger.prototype.gcd = bnGCD;
BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
// JSBN-specific extension
BigInteger.prototype.square = bnSquare;
// BigInteger interfaces not implemented in jsbn:
// BigInteger(int signum, byte[] magnitude)
// double doubleValue()
// float floatValue()
// int hashCode()
// long longValue()
// static BigInteger valueOf(long val)
if (typeof exports !== 'undefined') {
exports = module.exports = BigInteger;
} else {
this.BigInteger = BigInteger;
}
}).call(this);
},{}]},{},[11])