Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/README.md
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/README.md	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/README.md	(working copy)
@@ -1,21 +1,22 @@
 # is-my-json-valid
 
-A [JSONSchema](http://json-schema.org/) validator that uses code generation
-to be extremely fast
-
-```
-npm install is-my-json-valid
-```
+A [JSONSchema](https://json-schema.org/) validator that uses code generation to be extremely fast.
 
 It passes the entire JSONSchema v4 test suite except for `remoteRefs` and `maxLength`/`minLength` when using unicode surrogate pairs.
 
-[![build status](http://img.shields.io/travis/mafintosh/is-my-json-valid.svg?style=flat)](http://travis-ci.org/mafintosh/is-my-json-valid)
+[![build status](https://img.shields.io/travis/mafintosh/is-my-json-valid.svg?style=flat)](https://travis-ci.org/mafintosh/is-my-json-valid)
+
+## Installation
+
+```sh
+npm install --save is-my-json-valid
+```
 
 ## Usage
 
 Simply pass a schema to compile it
 
-``` js
+```js
 var validator = require('is-my-json-valid')
 
 var validate = validator({
@@ -39,13 +40,13 @@
 
 You can also pass the schema as a string
 
-``` js
+```js
 var validate = validator('{"type": ... }')
 ```
 
 Optionally you can use the require submodule to load a schema from `__dirname`
 
-``` js
+```js
 var validator = require('is-my-json-valid/require')
 var validate = validator('my-schema.json')
 ```
@@ -55,7 +56,7 @@
 is-my-json-valid supports the formats specified in JSON schema v4 (such as date-time).
 If you want to add your own custom formats pass them as the formats options to the validator
 
-``` js
+```js
 var validate = validator({
   type: 'string',
   required: true,
@@ -74,7 +75,7 @@
 
 You can pass in external schemas that you reference using the `$ref` attribute as the `schemas` option
 
-``` js
+```js
 var ext = {
   required: true,
   type: 'string'
@@ -95,7 +96,7 @@
 
 is-my-json-valid supports filtering away properties not in the schema
 
-``` js
+```js
 var filter = validator.filter({
   required: true,
   type: 'object',
@@ -109,12 +110,15 @@
 console.log(filter(doc)) // {hello: 'world'}
 ```
 
-## Verbose mode outputs the value on errors
+## Verbose mode shows more information about the source of the error
 
-is-my-json-valid outputs the value causing an error when verbose is set to true
+When the `verbose` options is set to `true`, `is-my-json-valid` also outputs:
 
-``` js
-var validate = validator({
+- `value`: The data value that caused the error
+- `schemaPath`: an array of keys indicating which sub-schema failed
+
+```js
+var schema = {
   required: true,
   type: 'object',
   properties: {
@@ -123,12 +127,34 @@
       type: 'string'
     }
   }
-}, {
+}
+var validate = validator(schema, {
   verbose: true
 })
 
 validate({hello: 100});
-console.log(validate.errors) // {field: 'data.hello', message: 'is the wrong type', value: 100, type: 'string'}
+console.log(validate.errors)
+// [ { field: 'data.hello',
+//     message: 'is the wrong type',
+//     value: 100,
+//     type: 'string',
+//     schemaPath: [ 'properties', 'hello' ] } ]
+```
+
+Many popular libraries make it easy to retrieve the failing rule with the `schemaPath`:
+
+```js
+var schemaPath = validate.errors[0].schemaPath
+var R = require('ramda')
+
+console.log( 'All evaluate to the same thing: ', R.equals(
+  schema.properties.hello,
+  { required: true, type: 'string' },
+  R.path(schemaPath, schema),
+  require('lodash').get(schema, schemaPath),
+  require('jsonpointer').get(schema, [""].concat(schemaPath))
+))
+// All evaluate to the same thing: true
 ```
 
 ## Greedy mode tries to validate as much as possible
@@ -136,7 +162,7 @@
 By default is-my-json-valid bails on first validation error but when greedy is
 set to true it tries to validate as much as possible:
 
-``` js
+```js
 var validate = validator({
   type: 'object',
   properties: {
@@ -154,20 +180,84 @@
                              //  {field: 'data.x', message: 'is the wrong type'}]
 ```
 
+## Error messages
+
+Here is a list of possible `message` values for errors:
+
+- `is required`
+- `is the wrong type`
+- `has additional items`
+- `must be FORMAT format` (FORMAT is the `format` property from the schema)
+- `must be unique`
+- `must be an enum value`
+- `dependencies not set`
+- `has additional properties`
+- `referenced schema does not match`
+- `negative schema matches`
+- `pattern mismatch`
+- `no schemas match`
+- `no (or more than one) schemas match`
+- `has a remainder`
+- `has more properties than allowed`
+- `has less properties than allowed`
+- `has more items than allowed`
+- `has less items than allowed`
+- `has longer length than allowed`
+- `has less length than allowed`
+- `is less than minimum`
+- `is more than maximum`
+
 ## Performance
 
 is-my-json-valid uses code generation to turn your JSON schema into basic javascript code that is easily optimizeable by v8.
 
-At the time of writing, is-my-json-valid is the __fastest validator__ when running
+At the time of writing, is-my-json-valid is the **fastest validator** when running
 
-* [json-schema-benchmark](https://github.com/Muscula/json-schema-benchmark)
-* [cosmicreals.com benchmark](http://cosmicrealms.com/blog/2014/08/29/benchmark-of-node-dot-js-json-validation-modules-part-3/)
-* [jsck benchmark](https://github.com/pandastrike/jsck/issues/72#issuecomment-70992684)
-* [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)
-* [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)
+- [json-schema-benchmark](https://github.com/Muscula/json-schema-benchmark)
+- [cosmicreals.com benchmark](http://cosmicrealms.com/blog/2014/08/29/benchmark-of-node-dot-js-json-validation-modules-part-3/)
+- [jsck benchmark](https://github.com/pandastrike/jsck/issues/72#issuecomment-70992684)
+- [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)
+- [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)
 
 If you know any other relevant benchmarks open a PR and I'll add them.
 
+## TypeScript support
+
+This library ships with TypeScript typings. They are still early on and not perfect at the moment, but should hopefully handle the most common cases. If you find anything that doesn't work, please open an issue and we'll try to solve it.
+
+The typings are using `unknown` and thus require TypeScript 3.0 or later.
+
+Here is a quick sample of usage together with express:
+
+```typescript
+import createError = require('http-errors')
+import createValidator = require('is-my-json-valid')
+import { Request, Response, NextFunction } from 'express'
+
+const personValidator = createValidator({
+  type: 'object',
+  properties: {
+    name: { type: 'string' },
+    age: { type: 'number' },
+  },
+  required: [
+    'name'
+  ]
+})
+
+export function post (req: Request, res: Response, next: NextFunction) {
+  // Here req.body is typed as: any
+
+  if (!personValidator(req.body)) {
+    throw createError(400, { errors: personValidator.errors })
+  }
+
+  // Here req.body is typed as: { name: string, age: number | undefined }
+}
+```
+
+As you can see, the typings for is-my-json-valid will contruct an interface from the schema passed in. This allows you to work with your incoming json body in a type safe way.
+
 ## License
 
 MIT
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/formats.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/formats.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/formats.js	(working copy)
@@ -1,14 +1,40 @@
-exports['date-time'] = /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}[tT ]\d{2}:\d{2}:\d{2}(\.\d+)?([zZ]|[+-]\d{2}:\d{2})$/
+var createIpValidator = require('is-my-ip-valid')
+
+var reEmailWhitespace = /\s/
+var reHostnameFirstPass = /^[a-zA-Z0-9.-]+$/
+var reHostnamePart = /^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])$/
+var rePhoneFirstPass = /^\+[0-9][0-9 ]{5,27}[0-9]$/
+var rePhoneDoubleSpace = / {2}/
+var rePhoneGlobalSpace = / /g
+
+exports['date-time'] = /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}[tT ]\d{2}:\d{2}:\d{2}(?:\.\d+|)([zZ]|[+-]\d{2}:\d{2})$/
 exports['date'] = /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}$/
 exports['time'] = /^\d{2}:\d{2}:\d{2}$/
-exports['email'] = /^\S+@\S+$/
-exports['ip-address'] = exports['ipv4'] = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
-exports['ipv6'] = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/
-exports['uri'] = /^[a-zA-Z][a-zA-Z0-9+-.]*:[^\s]*$/
+exports['email'] = function (input) { return (input.indexOf('@') !== -1) && (!reEmailWhitespace.test(input)) }
+exports['ip-address'] = exports['ipv4'] = createIpValidator({ version: 4 })
+exports['ipv6'] = createIpValidator({ version: 6 })
+exports['uri'] = /^[a-zA-Z][a-zA-Z0-9+\-.]*:[^\s]*$/
 exports['color'] = /(#?([0-9A-Fa-f]{3,6})\b)|(aqua)|(black)|(blue)|(fuchsia)|(gray)|(green)|(lime)|(maroon)|(navy)|(olive)|(orange)|(purple)|(red)|(silver)|(teal)|(white)|(yellow)|(rgb\(\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\))/
-exports['hostname'] = /^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$/
+exports['hostname'] = function (input) {
+  if (!(reHostnameFirstPass.test(input))) return false
+
+  var parts = input.split('.')
+
+  for (var i = 0; i < parts.length; i++) {
+    if (!(reHostnamePart.test(parts[i]))) return false
+  }
+
+  return true
+}
 exports['alpha'] = /^[a-zA-Z]+$/
 exports['alphanumeric'] = /^[a-zA-Z0-9]+$/
-exports['style'] = /\s*(.+?):\s*([^;]+);?/g
-exports['phone'] = /^\+(?:[0-9] ?){6,14}[0-9]$/
+exports['style'] = /.:\s*[^;]/g
+exports['phone'] = function (input) {
+  if (!(rePhoneFirstPass.test(input))) return false
+  if (rePhoneDoubleSpace.test(input)) return false
+
+  var digits = input.substring(1).replace(rePhoneGlobalSpace, '').length
+
+  return (digits >= 7 && digits <= 15)
+}
 exports['utc-millisec'] = /^[0-9]{1,15}\.?[0-9]{0,15}$/
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/index.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/index.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/index.js	(working copy)
@@ -45,13 +45,6 @@
   }
 }
 
-var formatName = function(field) {
-  field = JSON.stringify(field)
-  var pattern = /\[([^\[\]"]+)\]/
-  while (pattern.test(field)) field = field.replace(pattern, '."+$1+"')
-  return field
-}
-
 var types = {}
 
 types.any = function() {
@@ -75,7 +68,7 @@
 }
 
 types.number = function(name) {
-  return 'typeof '+name+' === "number"'
+  return 'typeof '+name+' === "number" && isFinite('+name+')'
 }
 
 types.integer = function(name) {
@@ -86,9 +79,10 @@
   return 'typeof '+name+' === "string"'
 }
 
-var unique = function(array) {
+var unique = function(array, len) {
+  len = Math.min(len === -1 ? array.length : len, array.length)
   var list = []
-  for (var i = 0; i < array.length; i++) {
+  for (var i = 0; i < len; i++) {
     list.push(typeof array[i] === 'object' ? JSON.stringify(array[i]) : array[i])
   }
   for (var i = 1; i < list.length; i++) {
@@ -109,20 +103,40 @@
   return !res;
 }
 
-var toType = function(node) {
-  return node.type
+var testLimitedRegex = function (r, s, maxLength) {
+  if (maxLength > -1 && s.length > maxLength) return true
+  return r.test(s)
 }
 
 var compile = function(schema, cache, root, reporter, opts) {
   var fmts = opts ? xtend(formats, opts.formats) : formats
-  var scope = {unique:unique, formats:fmts, isMultipleOf:isMultipleOf}
+  var scope = {unique:unique, formats:fmts, isMultipleOf:isMultipleOf, testLimitedRegex:testLimitedRegex}
   var verbose = opts ? !!opts.verbose : false;
   var greedy = opts && opts.greedy !== undefined ?
     opts.greedy : false;
 
   var syms = {}
+  var allocated = []
   var gensym = function(name) {
-    return name+(syms[name] = (syms[name] || 0)+1)
+    var res = name+(syms[name] = (syms[name] || 0)+1)
+    allocated.push(res)
+    return res
+  }
+
+  var formatName = function(field) {
+    var s = JSON.stringify(field)
+    try {
+      var pattern = /\[([^\[\]"]+)\]/
+      while (pattern.test(s)) s = s.replace(pattern, replacer)
+      return s
+    } catch (_) {
+      return JSON.stringify(field)
+    }
+
+    function replacer (match, v) {
+      if (allocated.indexOf(v) === -1) throw new Error('Unreplaceable')
+      return '." + ' + v + ' + "'
+    }
   }
 
   var reversePatterns = {}
@@ -138,10 +152,11 @@
   var genloop = function() {
     var v = vars.shift()
     vars.push(v+v[0])
+    allocated.push(v)
     return v
   }
 
-  var visit = function(name, node, reporter, filter) {
+  var visit = function(name, node, reporter, filter, schemaPath) {
     var properties = node.properties
     var type = node.type
     var tuple = false
@@ -161,7 +176,14 @@
       if (reporter === true) {
         validate('if (validate.errors === null) validate.errors = []')
         if (verbose) {
-          validate('validate.errors.push({field:%s,message:%s,value:%s,type:%s})', formatName(prop || name), JSON.stringify(msg), value || name, JSON.stringify(type))
+          validate(
+            'validate.errors.push({field:%s,message:%s,value:%s,type:%s,schemaPath:%s})',
+            formatName(prop || name),
+            JSON.stringify(msg),
+            value || name,
+            JSON.stringify(type),
+            JSON.stringify(schemaPath)
+          )
         } else {
           validate('validate.errors.push({field:%s,message:%s})', formatName(prop || name), JSON.stringify(msg))
         }
@@ -180,6 +202,10 @@
 
     var valid = [].concat(type)
       .map(function(t) {
+        if (t && !types.hasOwnProperty(t)) {
+          throw new Error('Unknown type: ' + t)
+        }
+
         return types[t || 'any'](name)
       })
       .join(' || ') || 'true'
@@ -199,7 +225,7 @@
       } else if (node.additionalItems) {
         var i = genloop()
         validate('for (var %s = %d; %s < %s.length; %s++) {', i, node.items.length, i, name, i)
-        visit(name+'['+i+']', node.additionalItems, reporter, filter)
+        visit(name+'['+i+']', node.additionalItems, reporter, filter, schemaPath.concat('additionalItems'))
         validate('}')
       }
     }
@@ -210,37 +236,34 @@
       scope[n] = fmts[node.format]
 
       if (typeof scope[n] === 'function') validate('if (!%s(%s)) {', n, name)
-      else validate('if (!%s.test(%s)) {', n, name)
+      else validate('if (!testLimitedRegex(%s, %s, %d)) {', n, name, typeof node.maxLength === 'undefined' ? -1 : node.maxLength)
       error('must be '+node.format+' format')
       validate('}')
       if (type !== 'string' && formats[node.format]) validate('}')
     }
 
     if (Array.isArray(node.required)) {
-      var isUndefined = function(req) {
-        return genobj(name, req) + ' === undefined'
-      }
-
+      var n = gensym('missing')
+      validate('var %s = 0', n)
       var checkRequired = function (req) {
         var prop = genobj(name, req);
         validate('if (%s === undefined) {', prop)
         error('is required', prop)
-        validate('missing++')
+        validate('%s++', n)
         validate('}')
       }
       validate('if ((%s)) {', type !== 'object' ? types.object(name) : 'true')
-      validate('var missing = 0')
       node.required.map(checkRequired)
       validate('}');
       if (!greedy) {
-        validate('if (missing === 0) {')
+        validate('if (%s === 0) {', n)
         indent++
       }
     }
 
     if (node.uniqueItems) {
       if (type !== 'array') validate('if (%s) {', types.array(name))
-      validate('if (!(unique(%s))) {', name)
+      validate('if (!(unique(%s, %d))) {', name, node.maxItems || -1)
       error('must be unique')
       validate('}')
       if (type !== 'array') validate('}')
@@ -282,7 +305,7 @@
         }
         if (typeof deps === 'object') {
           validate('if (%s !== undefined) {', genobj(name, key))
-          visit(name, deps, reporter, filter)
+          visit(name, deps, reporter, filter, schemaPath.concat(['dependencies', key]))
           validate('}')
         }
       })
@@ -316,7 +339,7 @@
         if (filter) validate('delete %s', name+'['+keys+'['+i+']]')
         error('has additional properties', null, JSON.stringify(name+'.') + ' + ' + keys + '['+i+']')
       } else {
-        visit(name+'['+keys+'['+i+']]', node.additionalProperties, reporter, filter)
+        visit(name+'['+keys+'['+i+']]', node.additionalProperties, reporter, filter, schemaPath.concat(['additionalProperties']))
       }
 
       validate
@@ -347,7 +370,7 @@
     if (node.not) {
       var prev = gensym('prev')
       validate('var %s = errors', prev)
-      visit(name, node.not, false, filter)
+      visit(name, node.not, false, filter, schemaPath.concat('not'))
       validate('if (%s === errors) {', prev)
       error('negative schema matches')
       validate('} else {')
@@ -360,7 +383,7 @@
 
       var i = genloop()
       validate('for (var %s = 0; %s < %s.length; %s++) {', i, i, name, i)
-      visit(name+'['+i+']', node.items, reporter, filter)
+      visit(name+'['+i+']', node.items, reporter, filter, schemaPath.concat('items'))
       validate('}')
 
       if (type !== 'array') validate('}')
@@ -377,7 +400,7 @@
       Object.keys(node.patternProperties).forEach(function(key) {
         var p = patterns(key)
         validate('if (%s.test(%s)) {', p, keys+'['+i+']')
-        visit(name+'['+keys+'['+i+']]', node.patternProperties[key], reporter, filter)
+        visit(name+'['+keys+'['+i+']]', node.patternProperties[key], reporter, filter, schemaPath.concat(['patternProperties', key]))
         validate('}')
       })
 
@@ -388,15 +411,15 @@
     if (node.pattern) {
       var p = patterns(node.pattern)
       if (type !== 'string') validate('if (%s) {', types.string(name))
-      validate('if (!(%s.test(%s))) {', p, name)
+      validate('if (!(testLimitedRegex(%s, %s, %d))) {', p, name, typeof node.maxLength === 'undefined' ? -1 : node.maxLength)
       error('pattern mismatch')
       validate('}')
       if (type !== 'string') validate('}')
     }
 
     if (node.allOf) {
-      node.allOf.forEach(function(sch) {
-        visit(name, sch, reporter, filter)
+      node.allOf.forEach(function(sch, key) {
+        visit(name, sch, reporter, filter, schemaPath.concat(['allOf', key]))
       })
     }
 
@@ -410,7 +433,7 @@
           validate('if (errors !== %s) {', prev)
             ('errors = %s', prev)
         }
-        visit(name, sch, false, false)
+        visit(name, sch, false, false, schemaPath)
       })
       node.anyOf.forEach(function(sch, i) {
         if (i) validate('}')
@@ -429,7 +452,7 @@
         ('var %s = 0', passes)
 
       node.oneOf.forEach(function(sch, i) {
-        visit(name, sch, false, false)
+        visit(name, sch, false, false, schemaPath)
         validate('if (%s === errors) {', prev)
           ('%s++', passes)
         ('} else {')
@@ -537,7 +560,13 @@
       Object.keys(properties).forEach(function(p) {
         if (Array.isArray(type) && type.indexOf('null') !== -1) validate('if (%s !== null) {', name)
 
-        visit(genobj(name, p), properties[p], reporter, filter)
+        visit(
+          genobj(name, p),
+          properties[p],
+          reporter,
+          filter,
+          schemaPath.concat(tuple ? p : ['properties', p])
+        )
 
         if (Array.isArray(type) && type.indexOf('null') !== -1) validate('}')
       })
@@ -553,7 +582,7 @@
       ('validate.errors = null')
       ('var errors = 0')
 
-  visit('data', schema, reporter, opts && opts.filter)
+  visit('data', schema, reporter, opts && opts.filter, [])
 
   validate
       ('return errors === 0')
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/node_modules/jsonpointer/README.md
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/node_modules/jsonpointer/README.md	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/node_modules/jsonpointer/README.md	(working copy)
@@ -1,6 +1,10 @@
-# JSON Pointer for nodejs
+# JSON Pointer for Node.js
 
-This is an implementation of [JSON Pointer](http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-08).
+This is an implementation of [JSON Pointer](https://tools.ietf.org/html/rfc6901).
+
+## CLI
+
+Looking to filter JSON from the command line? Check out [jsonpointer-cli](https://github.com/joeyespo/jsonpointer-cli).
 
 ## Usage
 ```javascript
@@ -12,7 +16,7 @@
 jsonpointer.get(obj, '/qux/0');   // returns 3
 jsonpointer.get(obj, '/qux/1');   // returns 4
 jsonpointer.get(obj, '/qux/2');   // returns 5
-jsonpointer.get(obj, '/quo');     // returns null
+jsonpointer.get(obj, '/quo');     // returns undefined
 
 jsonpointer.set(obj, '/foo', 6);  // sets obj.foo = 6;
 jsonpointer.set(obj, '/qux/-', 6) // sets obj.qux = [3, 4, 5, 6]
@@ -24,15 +28,17 @@
 
 ## Testing
 
-    $ node test.js
+    $ npm test
     All tests pass.
     $
 
-[![Build Status](https://travis-ci.org/janl/node-jsonpointer.png?branch=master)](https://travis-ci.org/janl/node-jsonpointer)
+[![Node.js CI](https://github.com/janl/node-jsonpointer/actions/workflows/node.js.yml/badge.svg)](https://github.com/janl/node-jsonpointer/actions/workflows/node.js.yml)
 
 ## Author
 
-(c) 2011-2015 Jan Lehnardt <jan@apache.org> & Marc Bachmann <https://github.com/marcbachmann>
+(c) 2011-2021 Jan Lehnardt <jan@apache.org> & Marc Bachmann <https://github.com/marcbachmann>
+
+Thanks to all contributors.
 
 ## License
 
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/node_modules/jsonpointer/jsonpointer.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/node_modules/jsonpointer/jsonpointer.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/node_modules/jsonpointer/jsonpointer.js	(working copy)
@@ -18,6 +18,8 @@
   var hasNextPart
 
   for (var p = 1, len = pointer.length; p < len;) {
+    if (pointer[p] === 'constructor' || pointer[p] === 'prototype' || pointer[p] === '__proto__') return obj
+
     part = untilde(pointer[p++])
     hasNextPart = len > p
 
@@ -50,6 +52,11 @@
     if (pointer[0] === '') return pointer
     throw new Error('Invalid JSON pointer.')
   } else if (Array.isArray(pointer)) {
+    for (const part of pointer) {
+      if (typeof part !== 'string' && typeof part !== 'number') {
+        throw new Error('Invalid JSON pointer. Must be of type string or number.')
+      }
+    }
     return pointer
   }
 
@@ -65,7 +72,7 @@
   for (var p = 1; p < len;) {
     obj = obj[untilde(pointer[p++])]
     if (len === p) return obj
-    if (typeof obj !== 'object') return undefined
+    if (typeof obj !== 'object' || obj === null) return undefined
   }
 }
 
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/node_modules/jsonpointer/package.json
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/node_modules/jsonpointer/package.json	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/node_modules/jsonpointer/package.json	(working copy)
@@ -7,24 +7,15 @@
     "util",
     "utility"
   ],
-  "version": "4.0.0",
-  "author": {
-    "name": "Jan Lehnardt",
-    "email": "jan@apache.org"
-  },
+  "version": "5.0.0",
+  "author": "Jan Lehnardt <jan@apache.org>",
   "contributors": [
-    {
-      "name": "Joe Hildebrand",
-      "email": "joe-github@cursive.net"
-    },
-    {
-      "name": "Marc Bachmann",
-      "email": "marc.brookman@gmail.com"
-    }
+    "Joe Hildebrand <joe-github@cursive.net>",
+    "Marc Bachmann <marc.brookman@gmail.com>"
   ],
   "repository": {
     "type": "git",
-    "url": "http://github.com/janl/node-jsonpointer.git"
+    "url": "https://github.com/janl/node-jsonpointer.git"
   },
   "bugs": {
     "url": "http://github.com/janl/node-jsonpointer/issues"
@@ -33,19 +24,25 @@
     "node": ">=0.10.0"
   },
   "main": "./jsonpointer",
+  "typings": "jsonpointer.d.ts",
+  "files": [
+    "jsonpointer.js",
+    "jsonpointer.d.ts"
+  ],
   "scripts": {
-    "test": "standard && node test.js"
+    "test": "npm run test:standard && npm run test:all",
+    "test:standard": "standard",
+    "test:all": "node test.js",
+    "semantic-release": "semantic-release pre && npm publish && semantic-release post"
   },
   "license": "MIT",
   "devDependencies": {
-    "standard": "^5.3.1"
-  },
-  "readme": "# JSON Pointer for nodejs\n\nThis is an implementation of [JSON Pointer](http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-08).\n\n## Usage\n```javascript\nvar jsonpointer = require('jsonpointer');\nvar obj = { foo: 1, bar: { baz: 2}, qux: [3, 4, 5]};\n\njsonpointer.get(obj, '/foo');     // returns 1\njsonpointer.get(obj, '/bar/baz'); // returns 2\njsonpointer.get(obj, '/qux/0');   // returns 3\njsonpointer.get(obj, '/qux/1');   // returns 4\njsonpointer.get(obj, '/qux/2');   // returns 5\njsonpointer.get(obj, '/quo');     // returns null\n\njsonpointer.set(obj, '/foo', 6);  // sets obj.foo = 6;\njsonpointer.set(obj, '/qux/-', 6) // sets obj.qux = [3, 4, 5, 6]\n\nvar pointer = jsonpointer.compile('/foo')\npointer.get(obj)    // returns 1\npointer.set(obj, 1) // sets obj.foo = 1\n```\n\n## Testing\n\n    $ node test.js\n    All tests pass.\n    $\n\n[![Build Status](https://travis-ci.org/janl/node-jsonpointer.png?branch=master)](https://travis-ci.org/janl/node-jsonpointer)\n\n## Author\n\n(c) 2011-2015 Jan Lehnardt <jan@apache.org> & Marc Bachmann <https://github.com/marcbachmann>\n\n## License\n\nMIT License.\n",
-  "readmeFilename": "README.md",
-  "_id": "jsonpointer@4.0.0",
-  "dist": {
-    "shasum": "55a52fc3e8dfb746b0db2716bc6d4af1b811dd95"
+    "semantic-release": "^18.0.0",
+    "standard": "^16.0.4"
   },
-  "_from": "jsonpointer@^4.0.0",
-  "_resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.0.tgz"
+  "standard": {
+    "ignore": [
+      "test.js"
+    ]
+  }
 }
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/node_modules/jsonpointer/test.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/node_modules/jsonpointer/test.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/node_modules/jsonpointer/test.js	(working copy)
@@ -8,45 +8,43 @@
   },
   d: {
     e: [{ a: 3 }, { b: 4 }, { c: 5 }]
-  }
+  },
+  nullValue: null
 }
 
-assert.equal(jsonpointer.get(obj, '/a'), 1)
-assert.equal(jsonpointer.get(obj, '/b/c'), 2)
-assert.equal(jsonpointer.get(obj, '/d/e/0/a'), 3)
-assert.equal(jsonpointer.get(obj, '/d/e/1/b'), 4)
-assert.equal(jsonpointer.get(obj, '/d/e/2/c'), 5)
+assert.strictEqual(jsonpointer.get(obj, '/nullValue'), null)
+assert.strictEqual(jsonpointer.get(obj, '/nullValue/e'), undefined)
 
 // set returns old value
-assert.equal(jsonpointer.set(obj, '/a', 2), 1)
-assert.equal(jsonpointer.set(obj, '/b/c', 3), 2)
-assert.equal(jsonpointer.set(obj, '/d/e/0/a', 4), 3)
-assert.equal(jsonpointer.set(obj, '/d/e/1/b', 5), 4)
-assert.equal(jsonpointer.set(obj, '/d/e/2/c', 6), 5)
+assert.strictEqual(jsonpointer.set(obj, '/a', 2), 1)
+assert.strictEqual(jsonpointer.set(obj, '/b/c', 3), 2)
+assert.strictEqual(jsonpointer.set(obj, '/d/e/0/a', 4), 3)
+assert.strictEqual(jsonpointer.set(obj, '/d/e/1/b', 5), 4)
+assert.strictEqual(jsonpointer.set(obj, '/d/e/2/c', 6), 5)
 
 // set nested properties
-assert.equal(jsonpointer.set(obj, '/f/g/h/i', 6), undefined)
-assert.equal(jsonpointer.get(obj, '/f/g/h/i'), 6)
+assert.strictEqual(jsonpointer.set(obj, '/f/g/h/i', 6), undefined)
+assert.strictEqual(jsonpointer.get(obj, '/f/g/h/i'), 6)
 
 // set an array
-assert.equal(jsonpointer.set(obj, '/f/g/h/foo/-', 'test'), undefined)
+assert.strictEqual(jsonpointer.set(obj, '/f/g/h/foo/-', 'test'), undefined)
 var arr = jsonpointer.get(obj, '/f/g/h/foo')
 assert(Array.isArray(arr), 'set /- creates an array.')
-assert.equal(arr[0], 'test')
+assert.strictEqual(arr[0], 'test')
 
-assert.equal(jsonpointer.get(obj, '/a'), 2)
-assert.equal(jsonpointer.get(obj, '/b/c'), 3)
-assert.equal(jsonpointer.get(obj, '/d/e/0/a'), 4)
-assert.equal(jsonpointer.get(obj, '/d/e/1/b'), 5)
-assert.equal(jsonpointer.get(obj, '/d/e/2/c'), 6)
+assert.strictEqual(jsonpointer.get(obj, '/a'), 2)
+assert.strictEqual(jsonpointer.get(obj, '/b/c'), 3)
+assert.strictEqual(jsonpointer.get(obj, '/d/e/0/a'), 4)
+assert.strictEqual(jsonpointer.get(obj, '/d/e/1/b'), 5)
+assert.strictEqual(jsonpointer.get(obj, '/d/e/2/c'), 6)
 
 // can set `null` as a value
-assert.equal(jsonpointer.set(obj, '/f/g/h/foo/0', null), 'test')
+assert.strictEqual(jsonpointer.set(obj, '/f/g/h/foo/0', null), 'test')
 assert.strictEqual(jsonpointer.get(obj, '/f/g/h/foo/0'), null)
-assert.equal(jsonpointer.set(obj, '/b/c', null), 3)
+assert.strictEqual(jsonpointer.set(obj, '/b/c', null), 3)
 assert.strictEqual(jsonpointer.get(obj, '/b/c'), null)
 
-assert.equal(jsonpointer.get(obj, ''), obj)
+assert.strictEqual(jsonpointer.get(obj, ''), obj)
 assert.throws(function () { jsonpointer.get(obj, 'a') }, validateError)
 assert.throws(function () { jsonpointer.get(obj, 'a/') }, validateError)
 
@@ -76,23 +74,23 @@
   '01': 4
 }
 
-assert.equal(jsonpointer.get(complexKeys, '/a~1b/c'), 1)
-assert.equal(jsonpointer.get(complexKeys, '/d/e~1f'), 2)
-assert.equal(jsonpointer.get(complexKeys, '/~01'), 3)
-assert.equal(jsonpointer.get(complexKeys, '/01'), 4)
-assert.equal(jsonpointer.get(complexKeys, '/a/b/c'), null)
-assert.equal(jsonpointer.get(complexKeys, '/~1'), null)
+assert.strictEqual(jsonpointer.get(complexKeys, '/a~1b/c'), 1)
+assert.strictEqual(jsonpointer.get(complexKeys, '/d/e~1f'), 2)
+assert.strictEqual(jsonpointer.get(complexKeys, '/~01'), 3)
+assert.strictEqual(jsonpointer.get(complexKeys, '/01'), 4)
+assert.strictEqual(jsonpointer.get(complexKeys, '/a/b/c'), undefined)
+assert.strictEqual(jsonpointer.get(complexKeys, '/~1'), undefined)
 
 // draft-ietf-appsawg-json-pointer-08 has special array rules
-var ary = [ 'zero', 'one', 'two' ]
-assert.equal(jsonpointer.get(ary, '/01'), null)
+var ary = ['zero', 'one', 'two']
+assert.strictEqual(jsonpointer.get(ary, '/01'), undefined)
 
-assert.equal(jsonpointer.set(ary, '/-', 'three'), null)
-assert.equal(ary[3], 'three')
+assert.strictEqual(jsonpointer.set(ary, '/-', 'three'), undefined)
+assert.strictEqual(ary[3], 'three')
 
 // Examples from the draft:
 var example = {
-  'foo': ['bar', 'baz'],
+  foo: ['bar', 'baz'],
   '': 0,
   'a/b': 1,
   'c%d': 2,
@@ -104,28 +102,64 @@
   'm~n': 8
 }
 
-assert.equal(jsonpointer.get(example, ''), example)
+assert.strictEqual(jsonpointer.get(example, ''), example)
 var ans = jsonpointer.get(example, '/foo')
-assert.equal(ans.length, 2)
-assert.equal(ans[0], 'bar')
-assert.equal(ans[1], 'baz')
-assert.equal(jsonpointer.get(example, '/foo/0'), 'bar')
-assert.equal(jsonpointer.get(example, '/'), 0)
-assert.equal(jsonpointer.get(example, '/a~1b'), 1)
-assert.equal(jsonpointer.get(example, '/c%d'), 2)
-assert.equal(jsonpointer.get(example, '/e^f'), 3)
-assert.equal(jsonpointer.get(example, '/g|h'), 4)
-assert.equal(jsonpointer.get(example, '/i\\j'), 5)
-assert.equal(jsonpointer.get(example, '/k\'l'), 6)
-assert.equal(jsonpointer.get(example, '/ '), 7)
-assert.equal(jsonpointer.get(example, '/m~0n'), 8)
+assert.strictEqual(ans.length, 2)
+assert.strictEqual(ans[0], 'bar')
+assert.strictEqual(ans[1], 'baz')
+assert.strictEqual(jsonpointer.get(example, '/foo/0'), 'bar')
+assert.strictEqual(jsonpointer.get(example, '/'), 0)
+assert.strictEqual(jsonpointer.get(example, '/a~1b'), 1)
+assert.strictEqual(jsonpointer.get(example, '/c%d'), 2)
+assert.strictEqual(jsonpointer.get(example, '/e^f'), 3)
+assert.strictEqual(jsonpointer.get(example, '/g|h'), 4)
+assert.strictEqual(jsonpointer.get(example, '/i\\j'), 5)
+assert.strictEqual(jsonpointer.get(example, '/k\'l'), 6)
+assert.strictEqual(jsonpointer.get(example, '/ '), 7)
+assert.strictEqual(jsonpointer.get(example, '/m~0n'), 8)
 
 // jsonpointer.compile(path)
-var a = {foo: 'bar'}
+var a = { foo: 'bar', foo2: null }
 var pointer = jsonpointer.compile('/foo')
-assert.equal(pointer.get(a), 'bar')
-assert.equal(pointer.set(a, 'test'), 'bar')
-assert.equal(pointer.get(a), 'test')
-assert.deepEqual(a, {foo: 'test'})
+assert.strictEqual(pointer.get(a), 'bar')
+assert.strictEqual(pointer.set(a, 'test'), 'bar')
+assert.strictEqual(pointer.get(a), 'test')
+assert.deepEqual(a, { foo: 'test', foo2: null })
+
+// Read subproperty of null value
+var pointerNullValue = jsonpointer.compile('/foo2/baz')
+assert.strictEqual(pointerNullValue.get(a), undefined)
+
+var b = {}
+jsonpointer.set({}, '/constructor/prototype/boo', 'polluted')
+assert(!b.boo, 'should not boo')
+
+var c = {}
+jsonpointer.set({}, '/__proto__/boo', 'polluted')
+assert(!c.boo, 'should not boo')
+
+var d = {}
+jsonpointer.set({}, '/foo/__proto__/boo', 'polluted')
+assert(!d.boo, 'should not boo')
+
+jsonpointer.set({}, '/foo/__proto__/__proto__/boo', 'polluted')
+assert(!d.boo, 'should not boo')
+
+var e = {}
+jsonpointer.set({}, '/foo/constructor/prototype/boo', 'polluted')
+assert(!e.boo, 'should not boo')
+
+jsonpointer.set({}, '/foo/constructor/constructor/prototype/boo', 'polluted')
+assert(!e.boo, 'should not boo')
+
+assert.throws(function () { jsonpointer.set({}, [['__proto__'], 'boo'], 'polluted')}, validateError)
+assert.throws(function () { jsonpointer.set({}, [[['__proto__']], 'boo'], 'polluted')}, validateError)
+assert.throws(function () { jsonpointer.set({}, [['__proto__'], ['__proto__'], 'boo'], 'polluted')}, validateError)
+assert.throws(function () { jsonpointer.set({}, [[['__proto__']], [['__proto__']], 'boo'], 'polluted')}, validateError)
+assert.throws(function () { jsonpointer.set({}, [['__proto__'], ['__proto__'], ['__proto__'], 'boo'], 'polluted')}, validateError)
+assert.throws(function () { jsonpointer.set({}, [['foo'], ['__proto__'], 'boo'], 'polluted')}, validateError)
+assert.throws(function () { jsonpointer.set({}, [['foo'], ['__proto__'], ['__proto__'], 'boo'], 'polluted')}, validateError)
+assert.throws(function () { jsonpointer.set({}, [['constructor'], ['prototype'], 'boo'], 'polluted')}, validateError)
+assert.throws(function () { jsonpointer.set({}, [['constructor'], ['constructor'], ['prototype'], 'boo'], 'polluted')}, validateError)
 
 console.log('All tests pass.')
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/package.json
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/package.json	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/har-validator/node_modules/is-my-json-valid/package.json	(working copy)
@@ -1,44 +1,33 @@
 {
   "name": "is-my-json-valid",
-  "version": "2.15.0",
-  "description": "A JSONSchema validator that uses code generation to be extremely fast",
-  "main": "index.js",
+  "version": "2.20.6",
+  "license": "MIT",
+  "repository": "mafintosh/is-my-json-valid",
+  "files": [
+    "formats.js",
+    "index.d.ts",
+    "index.js",
+    "require.js"
+  ],
+  "scripts": {
+    "test": "tape test/*.js && tsc"
+  },
   "dependencies": {
     "generate-function": "^2.0.0",
     "generate-object-property": "^1.1.0",
-    "jsonpointer": "^4.0.0",
+    "is-my-ip-valid": "^1.0.0",
+    "jsonpointer": "^5.0.0",
     "xtend": "^4.0.0"
   },
   "devDependencies": {
-    "tape": "^2.13.4"
-  },
-  "scripts": {
-    "test": "tape test/*.js"
-  },
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/mafintosh/is-my-json-valid"
+    "safe-regex": "^1.1.0",
+    "tape": "^2.13.4",
+    "typescript": "^3.0.1"
   },
   "keywords": [
     "json",
     "schema",
     "orderly",
     "jsonschema"
-  ],
-  "author": {
-    "name": "Mathias Buus"
-  },
-  "license": "MIT",
-  "bugs": {
-    "url": "https://github.com/mafintosh/is-my-json-valid/issues"
-  },
-  "homepage": "https://github.com/mafintosh/is-my-json-valid",
-  "readme": "# is-my-json-valid\n\nA [JSONSchema](http://json-schema.org/) validator that uses code generation\nto be extremely fast\n\n```\nnpm install is-my-json-valid\n```\n\nIt passes the entire JSONSchema v4 test suite except for `remoteRefs` and `maxLength`/`minLength` when using unicode surrogate pairs.\n\n[![build status](http://img.shields.io/travis/mafintosh/is-my-json-valid.svg?style=flat)](http://travis-ci.org/mafintosh/is-my-json-valid)\n\n## Usage\n\nSimply pass a schema to compile it\n\n``` js\nvar validator = require('is-my-json-valid')\n\nvar validate = validator({\n  required: true,\n  type: 'object',\n  properties: {\n    hello: {\n      required: true,\n      type: 'string'\n    }\n  }\n})\n\nconsole.log('should be valid', validate({hello: 'world'}))\nconsole.log('should not be valid', validate({}))\n\n// get the last list of errors by checking validate.errors\n// the following will print [{field: 'data.hello', message: 'is required'}]\nconsole.log(validate.errors)\n```\n\nYou can also pass the schema as a string\n\n``` js\nvar validate = validator('{\"type\": ... }')\n```\n\nOptionally you can use the require submodule to load a schema from `__dirname`\n\n``` js\nvar validator = require('is-my-json-valid/require')\nvar validate = validator('my-schema.json')\n```\n\n## Custom formats\n\nis-my-json-valid supports the formats specified in JSON schema v4 (such as date-time).\nIf you want to add your own custom formats pass them as the formats options to the validator\n\n``` js\nvar validate = validator({\n  type: 'string',\n  required: true,\n  format: 'only-a'\n}, {\n  formats: {\n    'only-a': /^a+$/\n  }\n})\n\nconsole.log(validate('aa')) // true\nconsole.log(validate('ab')) // false\n```\n\n## External schemas\n\nYou can pass in external schemas that you reference using the `$ref` attribute as the `schemas` option\n\n``` js\nvar ext = {\n  required: true,\n  type: 'string'\n}\n\nvar schema = {\n  $ref: '#ext' // references another schema called ext\n}\n\n// pass the external schemas as an option\nvar validate = validator(schema, {schemas: {ext: ext}})\n\nvalidate('hello') // returns true\nvalidate(42) // return false\n```\n\n## Filtering away additional properties\n\nis-my-json-valid supports filtering away properties not in the schema\n\n``` js\nvar filter = validator.filter({\n  required: true,\n  type: 'object',\n  properties: {\n    hello: {type: 'string', required: true}\n  },\n  additionalProperties: false\n})\n\nvar doc = {hello: 'world', notInSchema: true}\nconsole.log(filter(doc)) // {hello: 'world'}\n```\n\n## Verbose mode outputs the value on errors\n\nis-my-json-valid outputs the value causing an error when verbose is set to true\n\n``` js\nvar validate = validator({\n  required: true,\n  type: 'object',\n  properties: {\n    hello: {\n      required: true,\n      type: 'string'\n    }\n  }\n}, {\n  verbose: true\n})\n\nvalidate({hello: 100});\nconsole.log(validate.errors) // {field: 'data.hello', message: 'is the wrong type', value: 100, type: 'string'}\n```\n\n## Greedy mode tries to validate as much as possible\n\nBy default is-my-json-valid bails on first validation error but when greedy is\nset to true it tries to validate as much as possible:\n\n``` js\nvar validate = validator({\n  type: 'object',\n  properties: {\n    x: {\n      type: 'number'\n    }\n  },\n  required: ['x', 'y']\n}, {\n  greedy: true\n});\n\nvalidate({x: 'string'});\nconsole.log(validate.errors) // [{field: 'data.y', message: 'is required'},\n                             //  {field: 'data.x', message: 'is the wrong type'}]\n```\n\n## Performance\n\nis-my-json-valid uses code generation to turn your JSON schema into basic javascript code that is easily optimizeable by v8.\n\nAt the time of writing, is-my-json-valid is the __fastest validator__ when running\n\n* [json-schema-benchmark](https://github.com/Muscula/json-schema-benchmark)\n* [cosmicreals.com benchmark](http://cosmicrealms.com/blog/2014/08/29/benchmark-of-node-dot-js-json-validation-modules-part-3/)\n* [jsck benchmark](https://github.com/pandastrike/jsck/issues/72#issuecomment-70992684)\n* [themis benchmark](https://cdn.rawgit.com/playlyfe/themis/master/benchmark/results.html)\n* [z-schema benchmark](https://rawgit.com/zaggino/z-schema/master/benchmark/results.html)\n\nIf you know any other relevant benchmarks open a PR and I'll add them.\n\n## License\n\nMIT\n",
-  "readmeFilename": "README.md",
-  "_id": "is-my-json-valid@2.15.0",
-  "dist": {
-    "shasum": "0a83b04f01947c448fa691a7cbb5d372c2db74d1"
-  },
-  "_from": "is-my-json-valid@^2.12.4",
-  "_resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz"
+  ]
 }
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/README.md
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/README.md	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/README.md	(working copy)
@@ -1,634 +1,19 @@
-![hawk Logo](https://raw.github.com/hueniverse/hawk/master/images/hawk.png)
-
-<img align="right" src="https://raw.github.com/hueniverse/hawk/master/images/logo.png" /> **Hawk** is an HTTP authentication scheme using a message authentication code (MAC) algorithm to provide partial
-HTTP request cryptographic verification. For more complex use cases such as access delegation, see [Oz](https://github.com/hueniverse/oz).
-
-Current version: **3.x**
-
-Note: 3.x and 2.x are the same exact protocol as 1.1. The version increments reflect changes in the node API.
-
-[![Build Status](https://secure.travis-ci.org/hueniverse/hawk.png)](http://travis-ci.org/hueniverse/hawk)
-
-# Table of Content
-
-- [**Introduction**](#introduction)
-  - [Replay Protection](#replay-protection)
-  - [Usage Example](#usage-example)
-  - [Protocol Example](#protocol-example)
-    - [Payload Validation](#payload-validation)
-    - [Response Payload Validation](#response-payload-validation)
-  - [Browser Support and Considerations](#browser-support-and-considerations)
-<p></p>
-- [**Single URI Authorization**](#single-uri-authorization)
-  - [Usage Example](#bewit-usage-example)
-<p></p>
-- [**Security Considerations**](#security-considerations)
-  - [MAC Keys Transmission](#mac-keys-transmission)
-  - [Confidentiality of Requests](#confidentiality-of-requests)
-  - [Spoofing by Counterfeit Servers](#spoofing-by-counterfeit-servers)
-  - [Plaintext Storage of Credentials](#plaintext-storage-of-credentials)
-  - [Entropy of Keys](#entropy-of-keys)
-  - [Coverage Limitations](#coverage-limitations)
-  - [Future Time Manipulation](#future-time-manipulation)
-  - [Client Clock Poisoning](#client-clock-poisoning)
-  - [Bewit Limitations](#bewit-limitations)
-  - [Host Header Forgery](#host-header-forgery)
-<p></p>
-- [**Frequently Asked Questions**](#frequently-asked-questions)
-<p></p>
-- [**Implementations**](#implementations)
-- [**Acknowledgements**](#acknowledgements)
-
-# Introduction
-
-**Hawk** is an HTTP authentication scheme providing mechanisms for making authenticated HTTP requests with
-partial cryptographic verification of the request and response, covering the HTTP method, request URI, host,
-and optionally the request payload.
-
-Similar to the HTTP [Digest access authentication schemes](http://www.ietf.org/rfc/rfc2617.txt), **Hawk** uses a set of
-client credentials which include an identifier (e.g. username) and key (e.g. password). Likewise, just as with the Digest scheme,
-the key is never included in authenticated requests. Instead, it is used to calculate a request MAC value which is
-included in its place.
-
-However, **Hawk** has several differences from Digest. In particular, while both use a nonce to limit the possibility of
-replay attacks, in **Hawk** the client generates the nonce and uses it in combination with a timestamp, leading to less
-"chattiness" (interaction with the server).
-
-Also unlike Digest, this scheme is not intended to protect the key itself (the password in Digest) because
-the client and server must both have access to the key material in the clear.
-
-The primary design goals of this scheme are to:
-* simplify and improve HTTP authentication for services that are unwilling or unable to deploy TLS for all resources,
-* secure credentials against leakage (e.g., when the client uses some form of dynamic configuration to determine where
-  to send an authenticated request), and
-* avoid the exposure of credentials sent to a malicious server over an unauthenticated secure channel due to client
-  failure to validate the server's identity as part of its TLS handshake.
-
-In addition, **Hawk** supports a method for granting third-parties temporary access to individual resources using
-a query parameter called _bewit_ (in falconry, a leather strap used to attach a tracking device to the leg of a hawk).
-
-The **Hawk** scheme requires the establishment of a shared symmetric key between the client and the server,
-which is beyond the scope of this module. Typically, the shared credentials are established via an initial
-TLS-protected phase or derived from some other shared confidential information available to both the client
-and the server.
-
-
-## Replay Protection
-
-Without replay protection, an attacker can use a compromised (but otherwise valid and authenticated) request more 
-than once, gaining access to a protected resource. To mitigate this, clients include both a nonce and a timestamp when 
-making requests. This gives the server enough information to prevent replay attacks.
-
-The nonce is generated by the client, and is a string unique across all requests with the same timestamp and
-key identifier combination. 
-
-The timestamp enables the server to restrict the validity period of the credentials where requests occuring afterwards
-are rejected. It also removes the need for the server to retain an unbounded number of nonce values for future checks.
-By default, **Hawk** uses a time window of 1 minute to allow for time skew between the client and server (which in
-practice translates to a maximum of 2 minutes as the skew can be positive or negative).
-
-Using a timestamp requires the client's clock to be in sync with the server's clock. **Hawk** requires both the client
-clock and the server clock to use NTP to ensure synchronization. However, given the limitations of some client types
-(e.g. browsers) to deploy NTP, the server provides the client with its current time (in seconds precision) in response
-to a bad timestamp.
-
-There is no expectation that the client will adjust its system clock to match the server (in fact, this would be a
-potential attack vector). Instead, the client only uses the server's time to calculate an offset used only
-for communications with that particular server. The protocol rewards clients with synchronized clocks by reducing
-the number of round trips required to authenticate the first request.
-
-
-## Usage Example
-
-Server code:
-
-```javascript
-var Http = require('http');
-var Hawk = require('hawk');
-
-
-// Credentials lookup function
-
-var credentialsFunc = function (id, callback) {
-
-    var credentials = {
-        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-        algorithm: 'sha256',
-        user: 'Steve'
-    };
-
-    return callback(null, credentials);
-};
-
-// Create HTTP server
-
-var handler = function (req, res) {
-
-    // Authenticate incoming request
-
-    Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-        // Prepare response
-
-        var payload = (!err ? 'Hello ' + credentials.user + ' ' + artifacts.ext : 'Shoosh!');
-        var headers = { 'Content-Type': 'text/plain' };
-
-        // Generate Server-Authorization response header
-
-        var header = Hawk.server.header(credentials, artifacts, { payload: payload, contentType: headers['Content-Type'] });
-        headers['Server-Authorization'] = header;
-
-        // Send the response back
-
-        res.writeHead(!err ? 200 : 401, headers);
-        res.end(payload);
-    });
-};
-
-// Start server
-
-Http.createServer(handler).listen(8000, 'example.com');
-```
-
-Client code:
-
-```javascript
-var Request = require('request');
-var Hawk = require('hawk');
-
-
-// Client credentials
-
-var credentials = {
-    id: 'dh37fgj492je',
-    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-    algorithm: 'sha256'
-}
-
-// Request options
-
-var requestOptions = {
-    uri: 'http://example.com:8000/resource/1?b=1&a=2',
-    method: 'GET',
-    headers: {}
-};
-
-// Generate Authorization request header
-
-var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', { credentials: credentials, ext: 'some-app-data' });
-requestOptions.headers.Authorization = header.field;
-
-// Send authenticated request
-
-Request(requestOptions, function (error, response, body) {
-
-    // Authenticate the server's response
-
-    var isValid = Hawk.client.authenticate(response, credentials, header.artifacts, { payload: body });
-
-    // Output results
-
-    console.log(response.statusCode + ': ' + body + (isValid ? ' (valid)' : ' (invalid)'));
-});
-```
-
-**Hawk** utilized the [**SNTP**](https://github.com/hueniverse/sntp) module for time sync management. By default, the local
-machine time is used. To automatically retrieve and synchronice the clock within the application, use the SNTP 'start()' method.
-
-```javascript
-Hawk.sntp.start();
-```
-
-
-## Protocol Example
-
-The client attempts to access a protected resource without authentication, sending the following HTTP request to
-the resource server:
-
-```
-GET /resource/1?b=1&a=2 HTTP/1.1
-Host: example.com:8000
-```
-
-The resource server returns an authentication challenge.
-
-```
-HTTP/1.1 401 Unauthorized
-WWW-Authenticate: Hawk
-```
-
-The client has previously obtained a set of **Hawk** credentials for accessing resources on the "http://example.com/"
-server. The **Hawk** credentials issued to the client include the following attributes:
-
-* Key identifier: dh37fgj492je
-* Key: werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn
-* Algorithm: sha256
-
-The client generates the authentication header by calculating a timestamp (e.g. the number of seconds since January 1,
-1970 00:00:00 GMT), generating a nonce, and constructing the normalized request string (each value followed by a newline
-character):
-
-```
-hawk.1.header
-1353832234
-j4h3g2
-GET
-/resource/1?b=1&a=2
-example.com
-8000
-
-some-app-ext-data
-
-```
-
-The request MAC is calculated using HMAC with the specified hash algorithm "sha256" and the key over the normalized request string.
-The result is base64-encoded to produce the request MAC:
-
-```
-6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=
-```
-
-The client includes the **Hawk** key identifier, timestamp, nonce, application specific data, and request MAC with the request using
-the HTTP `Authorization` request header field:
-
-```
-GET /resource/1?b=1&a=2 HTTP/1.1
-Host: example.com:8000
-Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="
-```
-
-The server validates the request by calculating the request MAC again based on the request received and verifies the validity
-and scope of the **Hawk** credentials. If valid, the server responds with the requested resource.
-
-
-### Payload Validation
-
-**Hawk** provides optional payload validation. When generating the authentication header, the client calculates a payload hash
-using the specified hash algorithm. The hash is calculated over the concatenated value of (each followed by a newline character):
-* `hawk.1.payload`
-* the content-type in lowercase, without any parameters (e.g. `application/json`)
-* the request payload prior to any content encoding (the exact representation requirements should be specified by the server for payloads other than simple single-part ascii to ensure interoperability)
-
-For example:
-
-* Payload: `Thank you for flying Hawk`
-* Content Type: `text/plain`
-* Hash (sha256): `Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=`
-
-Results in the following input to the payload hash function (newline terminated values):
-
-```
-hawk.1.payload
-text/plain
-Thank you for flying Hawk
-
-```
-
-Which produces the following hash value:
-
-```
-Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=
-```
-
-The client constructs the normalized request string (newline terminated values):
-
-```
-hawk.1.header
-1353832234
-j4h3g2
-POST
-/resource/1?a=1&b=2
-example.com
-8000
-Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=
-some-app-ext-data
-
-```
-
-Then calculates the request MAC and includes the **Hawk** key identifier, timestamp, nonce, payload hash, application specific data,
-and request MAC, with the request using the HTTP `Authorization` request header field:
-
-```
-POST /resource/1?a=1&b=2 HTTP/1.1
-Host: example.com:8000
-Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=", ext="some-app-ext-data", mac="aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw="
-```
-
-It is up to the server if and when it validates the payload for any given request, based solely on it's security policy
-and the nature of the data included.
-
-If the payload is available at the time of authentication, the server uses the hash value provided by the client to construct
-the normalized string and validates the MAC. If the MAC is valid, the server calculates the payload hash and compares the value
-with the provided payload hash in the header. In many cases, checking the MAC first is faster than calculating the payload hash.
-
-However, if the payload is not available at authentication time (e.g. too large to fit in memory, streamed elsewhere, or processed
-at a different stage in the application), the server may choose to defer payload validation for later by retaining the hash value
-provided by the client after validating the MAC.
-
-It is important to note that MAC validation does not mean the hash value provided by the client is valid, only that the value
-included in the header was not modified. Without calculating the payload hash on the server and comparing it to the value provided
-by the client, the payload may be modified by an attacker.
-
-
-## Response Payload Validation
-
-**Hawk** provides partial response payload validation. The server includes the `Server-Authorization` response header which enables the
-client to authenticate the response and ensure it is talking to the right server. **Hawk** defines the HTTP `Server-Authorization` header
-as a response header using the exact same syntax as the `Authorization` request header field.
-
-The header is contructed using the same process as the client's request header. The server uses the same credentials and other
-artifacts provided by the client to constructs the normalized request string. The `ext` and `hash` values are replaced with
-new values based on the server response. The rest as identical to those used by the client.
-
-The result MAC digest is included with the optional `hash` and `ext` values:
-
-```
-Server-Authorization: Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"
-```
-
-
-## Browser Support and Considerations
-
-A browser script is provided for including using a `<script>` tag in [lib/browser.js](/lib/browser.js). It's also a [component](http://component.io/hueniverse/hawk).
-
-**Hawk** relies on the _Server-Authorization_ and _WWW-Authenticate_ headers in its response to communicate with the client.
-Therefore, in case of CORS requests, it is important to consider sending _Access-Control-Expose-Headers_ with the value
-_"WWW-Authenticate, Server-Authorization"_ on each response from your server. As explained in the
-[specifications](http://www.w3.org/TR/cors/#access-control-expose-headers-response-header), it will indicate that these headers
-can safely be accessed by the client (using getResponseHeader() on the XmlHttpRequest object). Otherwise you will be met with a
-["simple response header"](http://www.w3.org/TR/cors/#simple-response-header) which excludes these fields and would prevent the
-Hawk client from authenticating the requests.You can read more about the why and how in this
-[article](http://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server)
-
-
-# Single URI Authorization
-
-There are cases in which limited and short-term access to a protected resource is granted to a third party which does not
-have access to the shared credentials. For example, displaying a protected image on a web page accessed by anyone. **Hawk**
-provides limited support for such URIs in the form of a _bewit_ - a URI query parameter appended to the request URI which contains
-the necessary credentials to authenticate the request.
-
-Because of the significant security risks involved in issuing such access, bewit usage is purposely limited only to GET requests
-and for a finite period of time. Both the client and server can issue bewit credentials, however, the server should not use the same
-credentials as the client to maintain clear traceability as to who issued which credentials.
-
-In order to simplify implementation, bewit credentials do not support single-use policy and can be replayed multiple times within
-the granted access timeframe. 
-
-
-## Bewit Usage Example
-
-Server code:
-
-```javascript
-var Http = require('http');
-var Hawk = require('hawk');
-
-
-// Credentials lookup function
-
-var credentialsFunc = function (id, callback) {
-
-    var credentials = {
-        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-        algorithm: 'sha256'
-    };
-
-    return callback(null, credentials);
-};
-
-// Create HTTP server
-
-var handler = function (req, res) {
-
-    Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-        res.writeHead(!err ? 200 : 401, { 'Content-Type': 'text/plain' });
-        res.end(!err ? 'Access granted' : 'Shoosh!');
-    });
-};
-
-Http.createServer(handler).listen(8000, 'example.com');
-```
-
-Bewit code generation:
-
-```javascript
-var Request = require('request');
-var Hawk = require('hawk');
-
-
-// Client credentials
-
-var credentials = {
-    id: 'dh37fgj492je',
-    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-    algorithm: 'sha256'
-}
-
-// Generate bewit
-
-var duration = 60 * 5;      // 5 Minutes
-var bewit = Hawk.uri.getBewit('http://example.com:8080/resource/1?b=1&a=2', { credentials: credentials, ttlSec: duration, ext: 'some-app-data' });
-var uri = 'http://example.com:8000/resource/1?b=1&a=2' + '&bewit=' + bewit;
-```
-
-
-# Security Considerations
-
-The greatest sources of security risks are usually found not in **Hawk** but in the policies and procedures surrounding its use.
-Implementers are strongly encouraged to assess how this module addresses their security requirements. This section includes
-an incomplete list of security considerations that must be reviewed and understood before deploying **Hawk** on the server.
-Many of the protections provided in **Hawk** depends on whether and how they are used.
-
-### MAC Keys Transmission
-
-**Hawk** does not provide any mechanism for obtaining or transmitting the set of shared credentials required. Any mechanism used
-to obtain **Hawk** credentials must ensure that these transmissions are protected using transport-layer mechanisms such as TLS.
-
-### Confidentiality of Requests
-
-While **Hawk** provides a mechanism for verifying the integrity of HTTP requests, it provides no guarantee of request
-confidentiality. Unless other precautions are taken, eavesdroppers will have full access to the request content. Servers should
-carefully consider the types of data likely to be sent as part of such requests, and employ transport-layer security mechanisms
-to protect sensitive resources.
-
-### Spoofing by Counterfeit Servers
-
-**Hawk** provides limited verification of the server authenticity. When receiving a response back from the server, the server
-may choose to include a response `Server-Authorization` header which the client can use to verify the response. However, it is up to
-the server to determine when such measure is included, to up to the client to enforce that policy.
-
-A hostile party could take advantage of this by intercepting the client's requests and returning misleading or otherwise
-incorrect responses. Service providers should consider such attacks when developing services using this protocol, and should
-require transport-layer security for any requests where the authenticity of the resource server or of server responses is an issue.
-
-### Plaintext Storage of Credentials
-
-The **Hawk** key functions the same way passwords do in traditional authentication systems. In order to compute the request MAC,
-the server must have access to the key in plaintext form. This is in contrast, for example, to modern operating systems, which
-store only a one-way hash of user credentials.
-
-If an attacker were to gain access to these keys - or worse, to the server's database of all such keys - he or she would be able
-to perform any action on behalf of any resource owner. Accordingly, it is critical that servers protect these keys from unauthorized
-access.
-
-### Entropy of Keys
-
-Unless a transport-layer security protocol is used, eavesdroppers will have full access to authenticated requests and request
-MAC values, and will thus be able to mount offline brute-force attacks to recover the key used. Servers should be careful to
-assign keys which are long enough, and random enough, to resist such attacks for at least the length of time that the **Hawk**
-credentials are valid.
-
-For example, if the credentials are valid for two weeks, servers should ensure that it is not possible to mount a brute force
-attack that recovers the key in less than two weeks. Of course, servers are urged to err on the side of caution, and use the
-longest key reasonable.
-
-It is equally important that the pseudo-random number generator (PRNG) used to generate these keys be of sufficiently high
-quality. Many PRNG implementations generate number sequences that may appear to be random, but which nevertheless exhibit
-patterns or other weaknesses which make cryptanalysis or brute force attacks easier. Implementers should be careful to use
-cryptographically secure PRNGs to avoid these problems.
-
-### Coverage Limitations
-
-The request MAC only covers the HTTP `Host` header and optionally the `Content-Type` header. It does not cover any other headers
-which can often affect how the request body is interpreted by the server. If the server behavior is influenced by the presence
-or value of such headers, an attacker can manipulate the request headers without being detected. Implementers should use the
-`ext` feature to pass application-specific information via the `Authorization` header which is protected by the request MAC.
-
-The response authentication, when performed, only covers the response payload, content-type, and the request information 
-provided by the client in it's request (method, resource, timestamp, nonce, etc.). It does not cover the HTTP status code or
-any other response header field (e.g. Location) which can affect the client's behaviour.
-
-### Future Time Manipulation
-
-The protocol relies on a clock sync between the client and server. To accomplish this, the server informs the client of its
-current time when an invalid timestamp is received.
-
-If an attacker is able to manipulate this information and cause the client to use an incorrect time, it would be able to cause
-the client to generate authenticated requests using time in the future. Such requests will fail when sent by the client, and will
-not likely leave a trace on the server (given the common implementation of nonce, if at all enforced). The attacker will then
-be able to replay the request at the correct time without detection.
-
-The client must only use the time information provided by the server if:
-* it was delivered over a TLS connection and the server identity has been verified, or
-* the `tsm` MAC digest calculated using the same client credentials over the timestamp has been verified.
-
-### Client Clock Poisoning
-
-When receiving a request with a bad timestamp, the server provides the client with its current time. The client must never use
-the time received from the server to adjust its own clock, and must only use it to calculate an offset for communicating with
-that particular server.
-
-### Bewit Limitations
-
-Special care must be taken when issuing bewit credentials to third parties. Bewit credentials are valid until expiration and cannot
-be revoked or limited without using other means. Whatever resource they grant access to will be completely exposed to anyone with
-access to the bewit credentials which act as bearer credentials for that particular resource. While bewit usage is limited to GET
-requests only and therefore cannot be used to perform transactions or change server state, it can still be used to expose private
-and sensitive information.
-
-### Host Header Forgery
-
-Hawk validates the incoming request MAC against the incoming HTTP Host header. However, unless the optional `host` and `port`
-options are used with `server.authenticate()`, a malicous client can mint new host names pointing to the server's IP address and
-use that to craft an attack by sending a valid request that's meant for another hostname than the one used by the server. Server
-implementors must manually verify that the host header received matches their expectation (or use the options mentioned above).
-
-# Frequently Asked Questions
-
-### Where is the protocol specification?
-
-If you are looking for some prose explaining how all this works, **this is it**. **Hawk** is being developed as an open source
-project instead of a standard. In other words, the [code](/hueniverse/hawk/tree/master/lib) is the specification. Not sure about
-something? Open an issue!
-
-### Is it done?
-
-As of version 0.10.0, **Hawk** is feature-complete. However, until this module reaches version 1.0.0 it is considered experimental
-and is likely to change. This also means your feedback and contribution are very welcome. Feel free to open issues with questions
-and suggestions.
-
-### Where can I find **Hawk** implementations in other languages?
-
-**Hawk**'s only reference implementation is provided in JavaScript as a node.js module. However, it has been ported to other languages.
-The full list is maintained [here](https://github.com/hueniverse/hawk/issues?labels=port&state=closed). Please add an issue if you are
-working on another port. A cross-platform test-suite is in the works.
-
-### Why isn't the algorithm part of the challenge or dynamically negotiated?
-
-The algorithm used is closely related to the key issued as different algorithms require different key sizes (and other
-requirements). While some keys can be used for multiple algorithm, the protocol is designed to closely bind the key and algorithm
-together as part of the issued credentials.
-
-### Why is Host and Content-Type the only headers covered by the request MAC?
-
-It is really hard to include other headers. Headers can be changed by proxies and other intermediaries and there is no
-well-established way to normalize them. Many platforms change the case of header field names and values. The only
-straight-forward solution is to include the headers in some blob (say, base64 encoded JSON) and include that with the request,
-an approach taken by JWT and other such formats. However, that design violates the HTTP header boundaries, repeats information,
-and introduces other security issues because firewalls will not be aware of these "hidden" headers. In addition, any information
-repeated must be compared to the duplicated information in the header and therefore only moves the problem elsewhere.
-
-### Why not just use HTTP Digest?
-
-Digest requires pre-negotiation to establish a nonce. This means you can't just make a request - you must first send
-a protocol handshake to the server. This pattern has become unacceptable for most web services, especially mobile
-where extra round-trip are costly.
-
-### Why bother with all this nonce and timestamp business?
-
-**Hawk** is an attempt to find a reasonable, practical compromise between security and usability. OAuth 1.0 got timestamp
-and nonces halfway right but failed when it came to scalability and consistent developer experience. **Hawk** addresses
-it by requiring the client to sync its clock, but provides it with tools to accomplish it.
-
-In general, replay protection is a matter of application-specific threat model. It is less of an issue on a TLS-protected
-system where the clients are implemented using best practices and are under the control of the server. Instead of dropping
-replay protection, **Hawk** offers a required time window and an optional nonce verification. Together, it provides developers
-with the ability to decide how to enforce their security policy without impacting the client's implementation.
-
-### What are `app` and `dlg` in the authorization header and normalized mac string?
-
-The original motivation for **Hawk** was to replace the OAuth 1.0 use cases. This included both a simple client-server mode which
-this module is specifically designed for, and a delegated access mode which is being developed separately in
-[Oz](https://github.com/hueniverse/oz). In addition to the **Hawk** use cases, Oz requires another attribute: the application id `app`.
-This provides binding between the credentials and the application in a way that prevents an attacker from tricking an application
-to use credentials issued to someone else. It also has an optional 'delegated-by' attribute `dlg` which is the application id of the
-application the credentials were directly issued to. The goal of these two additions is to allow Oz to utilize **Hawk** directly,
-but with the additional security of delegated credentials.
-
-### What is the purpose of the static strings used in each normalized MAC input?
-
-When calculating a hash or MAC, a static prefix (tag) is added. The prefix is used to prevent MAC values from being
-used or reused for a purpose other than what they were created for (i.e. prevents switching MAC values between a request,
-response, and a bewit use cases). It also protects against exploits created after a potential change in how the protocol
-creates the normalized string. For example, if a future version would switch the order of nonce and timestamp, it
-can create an exploit opportunity for cases where the nonce is similar in format to a timestamp.
-
-### Does **Hawk** have anything to do with OAuth?
-
-Short answer: no.
-
-**Hawk** was originally proposed as the OAuth MAC Token specification. However, the OAuth working group in its consistent
-incompetence failed to produce a final, usable solution to address one of the most popular use cases of OAuth 1.0 - using it
-to authenticate simple client-server transactions (i.e. two-legged). As you can guess, the OAuth working group is still hard
-at work to produce more garbage.
-
-**Hawk** provides a simple HTTP authentication scheme for making client-server requests. It does not address the OAuth use case
-of delegating access to a third party. If you are looking for an OAuth alternative, check out [Oz](https://github.com/hueniverse/oz).
-
-# Implementations
-
-- [Logibit Hawk in F#/.Net](https://github.com/logibit/logibit.hawk/)
-- [Tent Hawk in Ruby](https://github.com/tent/hawk-ruby)
-- [Wealdtech in Java](https://github.com/wealdtech/hawk)
-- [Kumar's Mohawk in Python](https://github.com/kumar303/mohawk/)
-
-# Acknowledgements
-
-**Hawk** is a derivative work of the [HTTP MAC Authentication Scheme](http://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05) proposal
-co-authored by Ben Adida, Adam Barth, and Eran Hammer, which in turn was based on the OAuth 1.0 community specification.
-
-Special thanks to Ben Laurie for his always insightful feedback and advice.
-
-The **Hawk** logo was created by [Chris Carrasco](http://chriscarrasco.com).
+# hawk
+
+#### HTTP Holder-Of-Key Authentication Scheme.
+
+Documentation of the protocol, and the JS API, is in https://github.com/mozilla/hawk/blob/main/API.md.
+
+## Ownership Changes
+
+This was once `hueniverse/hawk` and relased as `hawk`.
+Then, after the 7.0.10 release, it was moved to the `hapijs/hawk` repository and released as `@hapi/hawk`.
+Hapi later de-supported the library, after releasing version 8.0.0.
+It has since been moved to `mozilla/hawk` and is again released as `hawk`.
+All of the intermediate versions are also relased as `hawk`.
+
+Changes are represented in GitHub releases on this repository.
+
+Mozilla maintains several Hawk implementations in different langauages, so it is likely to stay at Mozilla for some time.
+
+This library is in "maintenance mode" -- no features will be added, and only security-related bugfixes will be applied.
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/lib/client.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/lib/client.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/lib/client.js	(working copy)
@@ -1,369 +1,374 @@
-// Load modules
-
-var Url = require('url');
-var Hoek = require('hoek');
-var Cryptiles = require('cryptiles');
-var Crypto = require('./crypto');
-var Utils = require('./utils');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Generate an Authorization header for a given request
-
-/*
-    uri: 'http://example.com/resource?a=b' or object from Url.parse()
-    method: HTTP verb (e.g. 'GET', 'POST')
-    options: {
-
-        // Required
-
-        credentials: {
-            id: 'dh37fgj492je',
-            key: 'aoijedoaijsdlaksjdl',
-            algorithm: 'sha256'                                 // 'sha1', 'sha256'
-        },
-
-        // Optional
-
-        ext: 'application-specific',                        // Application specific data sent via the ext attribute
-        timestamp: Date.now(),                              // A pre-calculated timestamp
-        nonce: '2334f34f',                                  // A pre-generated nonce
-        localtimeOffsetMsec: 400,                           // Time offset to sync with server time (ignored if timestamp provided)
-        payload: '{"some":"payload"}',                      // UTF-8 encoded string for body hash generation (ignored if hash provided)
-        contentType: 'application/json',                    // Payload content-type (ignored if hash provided)
-        hash: 'U4MKKSmiVxk37JCCrAVIjV=',                    // Pre-calculated payload hash
-        app: '24s23423f34dx',                               // Oz application id
-        dlg: '234sz34tww3sd'                                // Oz delegated-by application id
-    }
-*/
-
-exports.header = function (uri, method, options) {
-
-    var result = {
-        field: '',
-        artifacts: {}
-    };
-
-    // Validate inputs
-
-    if (!uri || (typeof uri !== 'string' && typeof uri !== 'object') ||
-        !method || typeof method !== 'string' ||
-        !options || typeof options !== 'object') {
-
-        result.err = 'Invalid argument type';
-        return result;
-    }
-
-    // Application time
-
-    var timestamp = options.timestamp || Utils.nowSecs(options.localtimeOffsetMsec);
-
-    // Validate credentials
-
-    var credentials = options.credentials;
-    if (!credentials ||
-        !credentials.id ||
-        !credentials.key ||
-        !credentials.algorithm) {
-
-        result.err = 'Invalid credential object';
-        return result;
-    }
-
-    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-        result.err = 'Unknown algorithm';
-        return result;
-    }
-
-    // Parse URI
-
-    if (typeof uri === 'string') {
-        uri = Url.parse(uri);
-    }
-
-    // Calculate signature
-
-    var artifacts = {
-        ts: timestamp,
-        nonce: options.nonce || Cryptiles.randomString(6),
-        method: method,
-        resource: uri.pathname + (uri.search || ''),                            // Maintain trailing '?'
-        host: uri.hostname,
-        port: uri.port || (uri.protocol === 'http:' ? 80 : 443),
-        hash: options.hash,
-        ext: options.ext,
-        app: options.app,
-        dlg: options.dlg
-    };
-
-    result.artifacts = artifacts;
-
-    // Calculate payload hash
-
-    if (!artifacts.hash &&
-        (options.payload || options.payload === '')) {
-
-        artifacts.hash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
-    }
-
-    var mac = Crypto.calculateMac('header', credentials, artifacts);
-
-    // Construct header
-
-    var hasExt = artifacts.ext !== null && artifacts.ext !== undefined && artifacts.ext !== '';       // Other falsey values allowed
-    var header = 'Hawk id="' + credentials.id +
-                 '", ts="' + artifacts.ts +
-                 '", nonce="' + artifacts.nonce +
-                 (artifacts.hash ? '", hash="' + artifacts.hash : '') +
-                 (hasExt ? '", ext="' + Hoek.escapeHeaderAttribute(artifacts.ext) : '') +
-                 '", mac="' + mac + '"';
-
-    if (artifacts.app) {
-        header += ', app="' + artifacts.app +
-                  (artifacts.dlg ? '", dlg="' + artifacts.dlg : '') + '"';
-    }
-
-    result.field = header;
-
-    return result;
-};
-
-
-// Validate server response
-
-/*
-    res:        node's response object
-    artifacts:  object received from header().artifacts
-    options: {
-        payload:    optional payload received
-        required:   specifies if a Server-Authorization header is required. Defaults to 'false'
-    }
-*/
-
-exports.authenticate = function (res, credentials, artifacts, options) {
-
-    artifacts = Hoek.clone(artifacts);
-    options = options || {};
-
-    if (res.headers['www-authenticate']) {
-
-        // Parse HTTP WWW-Authenticate header
-
-        var wwwAttributes = Utils.parseAuthorizationHeader(res.headers['www-authenticate'], ['ts', 'tsm', 'error']);
-        if (wwwAttributes instanceof Error) {
-            return false;
-        }
-
-        // Validate server timestamp (not used to update clock since it is done via the SNPT client)
-
-        if (wwwAttributes.ts) {
-            var tsm = Crypto.calculateTsMac(wwwAttributes.ts, credentials);
-            if (tsm !== wwwAttributes.tsm) {
-                return false;
-            }
-        }
-    }
-
-    // Parse HTTP Server-Authorization header
-
-    if (!res.headers['server-authorization'] &&
-        !options.required) {
-
-        return true;
-    }
-
-    var attributes = Utils.parseAuthorizationHeader(res.headers['server-authorization'], ['mac', 'ext', 'hash']);
-    if (attributes instanceof Error) {
-        return false;
-    }
-
-    artifacts.ext = attributes.ext;
-    artifacts.hash = attributes.hash;
-
-    var mac = Crypto.calculateMac('response', credentials, artifacts);
-    if (mac !== attributes.mac) {
-        return false;
-    }
-
-    if (!options.payload &&
-        options.payload !== '') {
-
-        return true;
-    }
-
-    if (!attributes.hash) {
-        return false;
-    }
-
-    var calculatedHash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, res.headers['content-type']);
-    return (calculatedHash === attributes.hash);
-};
-
-
-// Generate a bewit value for a given URI
-
-/*
-    uri: 'http://example.com/resource?a=b' or object from Url.parse()
-    options: {
-
-        // Required
-
-        credentials: {
-            id: 'dh37fgj492je',
-            key: 'aoijedoaijsdlaksjdl',
-            algorithm: 'sha256'                             // 'sha1', 'sha256'
-        },
-        ttlSec: 60 * 60,                                    // TTL in seconds
-
-        // Optional
-
-        ext: 'application-specific',                        // Application specific data sent via the ext attribute
-        localtimeOffsetMsec: 400                            // Time offset to sync with server time
-    };
-*/
-
-exports.getBewit = function (uri, options) {
-
-    // Validate inputs
-
-    if (!uri ||
-        (typeof uri !== 'string' && typeof uri !== 'object') ||
-        !options ||
-        typeof options !== 'object' ||
-        !options.ttlSec) {
-
-        return '';
-    }
-
-    options.ext = (options.ext === null || options.ext === undefined ? '' : options.ext);       // Zero is valid value
-
-    // Application time
-
-    var now = Utils.now(options.localtimeOffsetMsec);
-
-    // Validate credentials
-
-    var credentials = options.credentials;
-    if (!credentials ||
-        !credentials.id ||
-        !credentials.key ||
-        !credentials.algorithm) {
-
-        return '';
-    }
-
-    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-        return '';
-    }
-
-    // Parse URI
-
-    if (typeof uri === 'string') {
-        uri = Url.parse(uri);
-    }
-
-    // Calculate signature
-
-    var exp = Math.floor(now / 1000) + options.ttlSec;
-    var mac = Crypto.calculateMac('bewit', credentials, {
-        ts: exp,
-        nonce: '',
-        method: 'GET',
-        resource: uri.pathname + (uri.search || ''),                            // Maintain trailing '?'
-        host: uri.hostname,
-        port: uri.port || (uri.protocol === 'http:' ? 80 : 443),
-        ext: options.ext
-    });
-
-    // Construct bewit: id\exp\mac\ext
-
-    var bewit = credentials.id + '\\' + exp + '\\' + mac + '\\' + options.ext;
-    return Hoek.base64urlEncode(bewit);
-};
-
-
-// Generate an authorization string for a message
-
-/*
-    host: 'example.com',
-    port: 8000,
-    message: '{"some":"payload"}',                          // UTF-8 encoded string for body hash generation
-    options: {
-
-        // Required
-
-        credentials: {
-            id: 'dh37fgj492je',
-            key: 'aoijedoaijsdlaksjdl',
-            algorithm: 'sha256'                             // 'sha1', 'sha256'
-        },
-
-        // Optional
-
-        timestamp: Date.now(),                              // A pre-calculated timestamp
-        nonce: '2334f34f',                                  // A pre-generated nonce
-        localtimeOffsetMsec: 400,                           // Time offset to sync with server time (ignored if timestamp provided)
-    }
-*/
-
-exports.message = function (host, port, message, options) {
-
-    // Validate inputs
-
-    if (!host || typeof host !== 'string' ||
-        !port || typeof port !== 'number' ||
-        message === null || message === undefined || typeof message !== 'string' ||
-        !options || typeof options !== 'object') {
-
-        return null;
-    }
-
-    // Application time
-
-    var timestamp = options.timestamp || Utils.nowSecs(options.localtimeOffsetMsec);
-
-    // Validate credentials
-
-    var credentials = options.credentials;
-    if (!credentials ||
-        !credentials.id ||
-        !credentials.key ||
-        !credentials.algorithm) {
-
-        // Invalid credential object
-        return null;
-    }
-
-    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-        return null;
-    }
-
-    // Calculate signature
-
-    var artifacts = {
-        ts: timestamp,
-        nonce: options.nonce || Cryptiles.randomString(6),
-        host: host,
-        port: port,
-        hash: Crypto.calculatePayloadHash(message, credentials.algorithm)
-    };
-
-    // Construct authorization
-
-    var result = {
-        id: credentials.id,
-        ts: artifacts.ts,
-        nonce: artifacts.nonce,
-        hash: artifacts.hash,
-        mac: Crypto.calculateMac('message', credentials, artifacts)
-    };
-
-    return result;
-};
-
-
-
+'use strict';
+
+const Url = require('url');
+
+const B64 = require('@hapi/b64');
+const Boom = require('@hapi/boom');
+const Cryptiles = require('@hapi/cryptiles');
+const Hoek = require('@hapi/hoek');
+
+const Crypto = require('./crypto');
+const Utils = require('./utils');
+
+
+const internals = {};
+
+
+// Generate an Authorization header for a given request
+
+/*
+    uri: 'http://example.com/resource?a=b' or object from Url.parse()
+    method: HTTP verb (e.g. 'GET', 'POST')
+    options: {
+
+        // Required
+
+        credentials: {
+            id: 'dh37fgj492je',
+            key: 'aoijedoaijsdlaksjdl',
+            algorithm: 'sha256'                                 // 'sha1', 'sha256'
+        },
+
+        // Optional
+
+        ext: 'application-specific',                        // Application specific data sent via the ext attribute
+        timestamp: Date.now() / 1000,                       // A pre-calculated timestamp in seconds
+        nonce: '2334f34f',                                  // A pre-generated nonce
+        localtimeOffsetMsec: 400,                           // Time offset to sync with server time (ignored if timestamp provided)
+        payload: '{"some":"payload"}',                      // UTF-8 encoded string for body hash generation (ignored if hash provided)
+        contentType: 'application/json',                    // Payload content-type (ignored if hash provided)
+        hash: 'U4MKKSmiVxk37JCCrAVIjV=',                    // Pre-calculated payload hash
+        app: '24s23423f34dx',                               // Oz application id
+        dlg: '234sz34tww3sd'                                // Oz delegated-by application id
+    }
+*/
+
+exports.header = function (uri, method, options) {
+
+    // Validate inputs
+
+    if (!uri || (typeof uri !== 'string' && typeof uri !== 'object') ||
+        !method || typeof method !== 'string' ||
+        !options || typeof options !== 'object') {
+
+        throw new Boom.Boom('Invalid argument type');
+    }
+
+    // Application time
+
+    const timestamp = options.timestamp || Utils.nowSecs(options.localtimeOffsetMsec);
+
+    // Validate credentials
+
+    const credentials = options.credentials;
+    if (!credentials ||
+        !credentials.id ||
+        !credentials.key ||
+        !credentials.algorithm) {
+
+        throw new Boom.Boom('Invalid credentials');
+    }
+
+    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
+        throw new Boom.Boom('Unknown algorithm');
+    }
+
+    // Parse URI
+
+    if (typeof uri === 'string') {
+        uri = Url.parse(uri);
+    }
+
+    // Calculate signature
+
+    const artifacts = {
+        ts: timestamp,
+        nonce: options.nonce || Cryptiles.randomString(6),
+        method,
+        resource: uri.pathname + (uri.search || ''),                            // Maintain trailing '?'
+        host: uri.hostname,
+        port: uri.port || (uri.protocol === 'http:' ? 80 : 443),
+        hash: options.hash,
+        ext: options.ext,
+        app: options.app,
+        dlg: options.dlg
+    };
+
+    // Calculate payload hash
+
+    if (!artifacts.hash &&
+        (options.payload || options.payload === '')) {
+
+        artifacts.hash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
+    }
+
+    const mac = Crypto.generateRequestMac('header', credentials, artifacts);
+
+    // Construct header
+
+    const hasExt = artifacts.ext !== null && artifacts.ext !== undefined && artifacts.ext !== '';       // Other falsey values allowed
+    let header = 'Hawk id="' + credentials.id +
+        '", ts="' + artifacts.ts +
+        '", nonce="' + artifacts.nonce +
+        (artifacts.hash ? '", hash="' + artifacts.hash : '') +
+        (hasExt ? '", ext="' + Hoek.escapeHeaderAttribute(artifacts.ext) : '') +
+        '", mac="' + mac + '"';
+
+    if (artifacts.app) {
+        header = header + ', app="' + artifacts.app +
+            (artifacts.dlg ? '", dlg="' + artifacts.dlg : '') + '"';
+    }
+
+    return { header, artifacts };
+};
+
+
+// Validate server response
+
+/*
+    res:        node's response object
+    artifacts:  object received from header().artifacts
+    options: {
+        payload:    optional payload received
+        required:   specifies if a Server-Authorization header is required. Defaults to 'false'
+    }
+*/
+
+exports.authenticate = function (res, credentials, artifacts, options) {
+
+    options = options || {};
+
+    artifacts = Hoek.clone(artifacts);
+
+    const result = { headers: {} };
+
+    if (res.headers['www-authenticate']) {
+
+        // Parse HTTP WWW-Authenticate header
+
+        try {
+            var wwwAttributes = Utils.parseAuthorizationHeader(res.headers['www-authenticate'], ['ts', 'tsm', 'error']);
+        }
+        catch (err) {
+            throw new Boom.Boom('Invalid WWW-Authenticate header');
+        }
+
+        result.headers['www-authenticate'] = wwwAttributes;
+
+        // Validate server timestamp (not used to update clock since it is done via the SNPT client)
+
+        if (wwwAttributes.ts) {
+            const tsm = Crypto.calculateTsMac(wwwAttributes.ts, credentials);
+            if (tsm !== wwwAttributes.tsm) {
+                throw new Boom.Boom('Invalid server timestamp hash', { decorate: result });
+            }
+        }
+    }
+
+    // Parse HTTP Server-Authorization header
+
+    if (!res.headers['server-authorization']) {
+        if (options.required) {
+            throw new Boom.Boom('Missing Server-Authorization header', { decorate: result });
+        }
+
+        return result;
+    }
+
+    try {
+        var serverAuthAttributes = Utils.parseAuthorizationHeader(res.headers['server-authorization'], ['mac', 'ext', 'hash']);
+    }
+    catch (err) {
+        throw new Boom.Boom('Invalid Server-Authorization header', { decorate: result });
+    }
+
+    result.headers['server-authorization'] = serverAuthAttributes;
+
+    artifacts.ext = serverAuthAttributes.ext;
+    artifacts.hash = serverAuthAttributes.hash;
+
+    const mac = Crypto.generateRequestMac('response', credentials, artifacts);
+    if (mac !== serverAuthAttributes.mac) {
+        throw new Boom.Boom('Bad response mac', { decorate: result });
+    }
+
+    if (options.payload === null ||
+        options.payload === undefined) {
+
+        return result;
+    }
+
+    if (!serverAuthAttributes.hash) {
+        throw new Boom.Boom('Missing response hash attribute', { decorate: result });
+    }
+
+    const calculatedHash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, res.headers['content-type']);
+    if (calculatedHash !== serverAuthAttributes.hash) {
+        throw new Boom.Boom('Bad response payload mac', { decorate: result });
+    }
+
+    return result;
+};
+
+
+// Generate a bewit value for a given URI
+
+/*
+    uri: 'http://example.com/resource?a=b' or object from Url.parse()
+    options: {
+
+        // Required
+
+        credentials: {
+            id: 'dh37fgj492je',
+            key: 'aoijedoaijsdlaksjdl',
+            algorithm: 'sha256'                             // 'sha1', 'sha256'
+        },
+        ttlSec: 60 * 60,                                    // TTL in seconds
+
+        // Optional
+
+        ext: 'application-specific',                        // Application specific data sent via the ext attribute
+        localtimeOffsetMsec: 400                            // Time offset to sync with server time
+    };
+*/
+
+exports.getBewit = function (uri, options) {
+
+    // Validate inputs
+
+    if (!uri ||
+        (typeof uri !== 'string' && typeof uri !== 'object') ||
+        !options ||
+        typeof options !== 'object' ||
+        !options.ttlSec) {
+
+        throw new Boom.Boom('Invalid inputs');
+    }
+
+    const ext = (options.ext === null || options.ext === undefined ? '' : options.ext);       // Zero is valid value
+
+    // Application time
+
+    const now = Utils.now(options.localtimeOffsetMsec);
+
+    // Validate credentials
+
+    const credentials = options.credentials;
+    if (!credentials ||
+        !credentials.id ||
+        !credentials.key ||
+        !credentials.algorithm) {
+
+        throw new Boom.Boom('Invalid credentials');
+    }
+
+    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
+        throw new Boom.Boom('Unknown algorithm');
+    }
+
+    // Parse URI
+
+    if (typeof uri === 'string') {
+        uri = Url.parse(uri);
+    }
+
+    // Calculate signature
+
+    const exp = Math.floor(now / 1000) + options.ttlSec;
+    const mac = Crypto.generateRequestMac('bewit', credentials, {
+        ts: exp,
+        nonce: '',
+        method: 'GET',
+        resource: uri.pathname + (uri.search || ''),                            // Maintain trailing '?'
+        host: uri.hostname,
+        port: uri.port || (uri.protocol === 'http:' ? 80 : 443),
+        ext
+    });
+
+    // Construct bewit: id\exp\mac\ext
+
+    const bewit = credentials.id + '\\' + exp + '\\' + mac + '\\' + ext;
+    return B64.base64urlEncode(bewit);
+};
+
+
+// Generate an authorization string for a message
+
+/*
+    host: 'example.com',
+    port: 8000,
+    message: '{"some":"payload"}',                          // UTF-8 encoded string for body hash generation
+    options: {
+
+        // Required
+
+        credentials: {
+            id: 'dh37fgj492je',
+            key: 'aoijedoaijsdlaksjdl',
+            algorithm: 'sha256'                             // 'sha1', 'sha256'
+        },
+
+        // Optional
+
+        timestamp: Date.now() / 1000,                       // A pre-calculated timestamp in seconds
+        nonce: '2334f34f',                                  // A pre-generated nonce
+        localtimeOffsetMsec: 400,                           // Time offset to sync with server time (ignored if timestamp provided)
+    }
+*/
+
+exports.message = function (host, port, message, options) {
+
+    options = options || {};
+
+    // Validate inputs
+
+    if (!host || typeof host !== 'string' ||
+        !port || typeof port !== 'number' ||
+        message === null || message === undefined || typeof message !== 'string' ||
+        typeof options !== 'object') {
+
+        throw new Boom.Boom('Invalid inputs');
+    }
+
+    // Application time
+
+    const timestamp = options.timestamp || Utils.nowSecs(options.localtimeOffsetMsec);
+
+    // Validate credentials
+
+    const credentials = options.credentials;
+    if (!credentials ||
+        !credentials.id ||
+        !credentials.key ||
+        !credentials.algorithm) {
+
+        throw new Boom.Boom('Invalid credentials');
+    }
+
+    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
+        throw new Boom.Boom('Unknown algorithm');
+    }
+
+    // Calculate signature
+
+    const artifacts = {
+        ts: timestamp,
+        nonce: options.nonce || Cryptiles.randomString(6),
+        host,
+        port,
+        hash: Crypto.calculatePayloadHash(message, credentials.algorithm)
+    };
+
+    // Construct authorization
+
+    const result = {
+        id: credentials.id,
+        ts: artifacts.ts,
+        nonce: artifacts.nonce,
+        hash: artifacts.hash,
+        mac: Crypto.generateRequestMac('message', credentials, artifacts)
+    };
+
+    return result;
+};
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/lib/crypto.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/lib/crypto.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/lib/crypto.js	(working copy)
@@ -1,126 +1,174 @@
-// Load modules
-
-var Crypto = require('crypto');
-var Url = require('url');
-var Utils = require('./utils');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// MAC normalization format version
-
-exports.headerVersion = '1';                        // Prevent comparison of mac values generated with different normalized string formats
-
-
-// Supported HMAC algorithms
-
-exports.algorithms = ['sha1', 'sha256'];
-
-
-// Calculate the request MAC
-
-/*
-    type: 'header',                                 // 'header', 'bewit', 'response'
-    credentials: {
-        key: 'aoijedoaijsdlaksjdl',
-        algorithm: 'sha256'                         // 'sha1', 'sha256'
-    },
-    options: {
-        method: 'GET',
-        resource: '/resource?a=1&b=2',
-        host: 'example.com',
-        port: 8080,
-        ts: 1357718381034,
-        nonce: 'd3d345f',
-        hash: 'U4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=',
-        ext: 'app-specific-data',
-        app: 'hf48hd83qwkj',                        // Application id (Oz)
-        dlg: 'd8djwekds9cj'                         // Delegated by application id (Oz), requires options.app
-    }
-*/
-
-exports.calculateMac = function (type, credentials, options) {
-
-    var normalized = exports.generateNormalizedString(type, options);
-
-    var hmac = Crypto.createHmac(credentials.algorithm, credentials.key).update(normalized);
-    var digest = hmac.digest('base64');
-    return digest;
-};
-
-
-exports.generateNormalizedString = function (type, options) {
-
-    var resource = options.resource || '';
-    if (resource &&
-        resource[0] !== '/') {
-
-        var url = Url.parse(resource, false);
-        resource = url.path;                        // Includes query
-    }
-
-    var normalized = 'hawk.' + exports.headerVersion + '.' + type + '\n' +
-                     options.ts + '\n' +
-                     options.nonce + '\n' +
-                     (options.method || '').toUpperCase() + '\n' +
-                     resource + '\n' +
-                     options.host.toLowerCase() + '\n' +
-                     options.port + '\n' +
-                     (options.hash || '') + '\n';
-
-    if (options.ext) {
-        normalized += options.ext.replace('\\', '\\\\').replace('\n', '\\n');
-    }
-
-    normalized += '\n';
-
-    if (options.app) {
-        normalized += options.app + '\n' +
-                      (options.dlg || '') + '\n';
-    }
-
-    return normalized;
-};
-
-
-exports.calculatePayloadHash = function (payload, algorithm, contentType) {
-
-    var hash = exports.initializePayloadHash(algorithm, contentType);
-    hash.update(payload || '');
-    return exports.finalizePayloadHash(hash);
-};
-
-
-exports.initializePayloadHash = function (algorithm, contentType) {
-
-    var hash = Crypto.createHash(algorithm);
-    hash.update('hawk.' + exports.headerVersion + '.payload\n');
-    hash.update(Utils.parseContentType(contentType) + '\n');
-    return hash;
-};
-
-
-exports.finalizePayloadHash = function (hash) {
-
-    hash.update('\n');
-    return hash.digest('base64');
-};
-
-
-exports.calculateTsMac = function (ts, credentials) {
-
-    var hmac = Crypto.createHmac(credentials.algorithm, credentials.key);
-    hmac.update('hawk.' + exports.headerVersion + '.ts\n' + ts + '\n');
-    return hmac.digest('base64');
-};
-
-
-exports.timestampMessage = function (credentials, localtimeOffsetMsec) {
-
-    var now = Utils.nowSecs(localtimeOffsetMsec);
-    var tsm = exports.calculateTsMac(now, credentials);
-    return { ts: now, tsm: tsm };
-};
+'use strict';
+
+const Crypto = require('crypto');
+const Url = require('url');
+
+const Utils = require('./utils');
+
+
+const internals = {};
+
+
+// MAC normalization format version
+
+exports.headerVersion = '1';                        // Prevent comparison of mac values generated with different normalized string formats
+
+
+// Supported HMAC algorithms
+
+exports.algorithms = ['sha1', 'sha256'];
+
+
+// Generates the request MAC
+
+/*
+    type: 'header',                                 // 'header', 'bewit', 'response'
+    credentials: {
+        key: 'aoijedoaijsdlaksjdl',
+        algorithm: 'sha256'                         // 'sha1', 'sha256'
+    },
+    options: {
+        method: 'GET',
+        resource: '/resource?a=1&b=2',
+        host: 'example.com',
+        port: 8080,
+        ts: 1357718381034,
+        nonce: 'd3d345f',
+        hash: 'U4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=',
+        ext: 'app-specific-data',
+        app: 'hf48hd83qwkj',                        // Application id (Oz)
+        dlg: 'd8djwekds9cj'                         // Delegated by application id (Oz), requires options.app
+    }
+*/
+
+exports.generateRequestMac = function (type, credentials, options) {
+
+    const normalized = exports.generateNormalizedString(type, options);
+
+    const hmac = Crypto.createHmac(credentials.algorithm, credentials.key).update(normalized);
+    const digest = hmac.digest('base64');
+    return digest;
+};
+
+
+// Calculate the request MAC for verification
+
+/*
+    type: 'header',                                 // 'header', 'bewit', 'response'
+    credentials: {
+        key: 'aoijedoaijsdlaksjdl',
+        algorithm: 'sha256'                         // 'sha1', 'sha256'
+    },
+    options: {
+        method: 'GET',
+        resource: '/resource?a=1&b=2',
+        host: 'example.com',
+        port: 8080,
+        ts: 1357718381034,
+        nonce: 'd3d345f',
+        hash: 'U4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=',
+        ext: 'app-specific-data',
+        app: 'hf48hd83qwkj',                        // Application id (Oz)
+        dlg: 'd8djwekds9cj'                         // Delegated by application id (Oz), requires options.app
+    }
+*/
+
+exports.calculateServerMac = function (type, credentials, options, payload, contentType) {
+
+    if (options.hash) {
+        if (!payload) {
+            console.warn(`Security Warning: calculateServerMac was called trusting the client payload hash which provides no integrity checking and is insecure`);
+        }
+        else {
+            // never trust client provided hash, always calculate server side
+            options.hash = exports.calculatePayloadHash(payload, credentials.algorithm, contentType);
+        }
+    }
+
+    const normalized = exports.generateNormalizedString(type, options);
+
+    const hmac = Crypto.createHmac(credentials.algorithm, credentials.key).update(normalized);
+    const digest = hmac.digest('base64');
+    return digest;
+};
+
+
+exports.calculateMac = function (type, credentials, options) {
+
+    console.warn(`Deprecation Warning: calculateMac() is replaced by either calculateServerMac() or generateRequestMac()`);
+    return exports.generateRequestMac(type, credentials, options);
+};
+
+
+exports.generateNormalizedString = function (type, options) {
+
+    let resource = options.resource || '';
+    if (resource &&
+        resource[0] !== '/') {
+
+        const url = Url.parse(resource, false);
+        resource = url.path;                        // Includes query
+    }
+
+    let normalized = 'hawk.' + exports.headerVersion + '.' + type + '\n' +
+                     options.ts + '\n' +
+                     options.nonce + '\n' +
+                     (options.method || '').toUpperCase() + '\n' +
+                     resource + '\n' +
+                     options.host.toLowerCase() + '\n' +
+                     options.port + '\n' +
+                     (options.hash || '') + '\n';
+
+    if (options.ext) {
+        normalized = normalized + options.ext.replace(/\\/g, '\\\\').replace(/\n/g, '\\n');
+    }
+
+    normalized = normalized + '\n';
+
+    if (options.app) {
+        normalized = normalized + options.app + '\n' +
+                                  (options.dlg || '') + '\n';
+    }
+
+    return normalized;
+};
+
+
+exports.calculatePayloadHash = function (payload, algorithm, contentType) {
+
+    const hash = exports.initializePayloadHash(algorithm, contentType);
+    hash.update(payload || '');
+    return exports.finalizePayloadHash(hash);
+};
+
+
+exports.initializePayloadHash = function (algorithm, contentType) {
+
+    const hash = Crypto.createHash(algorithm);
+    hash.update('hawk.' + exports.headerVersion + '.payload\n');
+    hash.update(Utils.parseContentType(contentType) + '\n');
+    return hash;
+};
+
+
+exports.finalizePayloadHash = function (hash) {
+
+    hash.update('\n');
+    return hash.digest('base64');
+};
+
+
+exports.calculateTsMac = function (ts, credentials) {
+
+    const hmac = Crypto.createHmac(credentials.algorithm, credentials.key);
+    hmac.update('hawk.' + exports.headerVersion + '.ts\n' + ts + '\n');
+    return hmac.digest('base64');
+};
+
+
+exports.timestampMessage = function (credentials, localtimeOffsetMsec) {
+
+    const now = Utils.nowSecs(localtimeOffsetMsec);
+    const tsm = exports.calculateTsMac(now, credentials);
+    return { ts: now, tsm };
+};
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/lib/index.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/lib/index.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/lib/index.js	(working copy)
@@ -1,15 +1,15 @@
-// Export sub-modules
-
-exports.error = exports.Error = require('boom');
-exports.sntp = require('sntp');
-
-exports.server = require('./server');
-exports.client = require('./client');
-exports.crypto = require('./crypto');
-exports.utils = require('./utils');
-
-exports.uri = {
-    authenticate: exports.server.authenticateBewit,
-    getBewit: exports.client.getBewit
-};
-
+'use strict';
+
+
+exports.server = require('./server');
+
+exports.client = require('./client');
+
+exports.crypto = require('./crypto');
+
+exports.utils = require('./utils');
+
+exports.uri = {
+    authenticate: exports.server.authenticateBewit,
+    getBewit: exports.client.getBewit
+};
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/lib/server.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/lib/server.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/lib/server.js	(working copy)
@@ -1,548 +1,543 @@
-// Load modules
-
-var Boom = require('boom');
-var Hoek = require('hoek');
-var Cryptiles = require('cryptiles');
-var Crypto = require('./crypto');
-var Utils = require('./utils');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Hawk authentication
-
-/*
-   req:                 node's HTTP request object or an object as follows:
-
-                        var request = {
-                            method: 'GET',
-                            url: '/resource/4?a=1&b=2',
-                            host: 'example.com',
-                            port: 8080,
-                            authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="'
-                        };
-
-   credentialsFunc:     required function to lookup the set of Hawk credentials based on the provided credentials id.
-                        The credentials include the MAC key, MAC algorithm, and other attributes (such as username)
-                        needed by the application. This function is the equivalent of verifying the username and
-                        password in Basic authentication.
-
-                        var credentialsFunc = function (id, callback) {
-
-                            // Lookup credentials in database
-                            db.lookup(id, function (err, item) {
-
-                                if (err || !item) {
-                                    return callback(err);
-                                }
-
-                                var credentials = {
-                                    // Required
-                                    key: item.key,
-                                    algorithm: item.algorithm,
-                                    // Application specific
-                                    user: item.user
-                                };
-
-                                return callback(null, credentials);
-                            });
-                        };
-
-   options: {
-
-        hostHeaderName:        optional header field name, used to override the default 'Host' header when used
-                               behind a cache of a proxy. Apache2 changes the value of the 'Host' header while preserving
-                               the original (which is what the module must verify) in the 'x-forwarded-host' header field.
-                               Only used when passed a node Http.ServerRequest object.
-
-        nonceFunc:             optional nonce validation function. The function signature is function(key, nonce, ts, callback)
-                               where 'callback' must be called using the signature function(err).
-
-        timestampSkewSec:      optional number of seconds of permitted clock skew for incoming timestamps. Defaults to 60 seconds.
-                               Provides a +/- skew which means actual allowed window is double the number of seconds.
-
-        localtimeOffsetMsec:   optional local clock time offset express in a number of milliseconds (positive or negative).
-                               Defaults to 0.
-
-        payload:               optional payload for validation. The client calculates the hash value and includes it via the 'hash'
-                               header attribute. The server always ensures the value provided has been included in the request
-                               MAC. When this option is provided, it validates the hash value itself. Validation is done by calculating
-                               a hash value over the entire payload (assuming it has already be normalized to the same format and
-                               encoding used by the client to calculate the hash on request). If the payload is not available at the time
-                               of authentication, the authenticatePayload() method can be used by passing it the credentials and
-                               attributes.hash returned in the authenticate callback.
-
-        host:                  optional host name override. Only used when passed a node request object.
-        port:                  optional port override. Only used when passed a node request object.
-    }
-
-    callback: function (err, credentials, artifacts) { }
- */
-
-exports.authenticate = function (req, credentialsFunc, options, callback) {
-
-    callback = Hoek.nextTick(callback);
-
-    // Default options
-
-    options.nonceFunc = options.nonceFunc || internals.nonceFunc;
-    options.timestampSkewSec = options.timestampSkewSec || 60;                                                  // 60 seconds
-
-    // Application time
-
-    var now = Utils.now(options.localtimeOffsetMsec);                           // Measure now before any other processing
-
-    // Convert node Http request object to a request configuration object
-
-    var request = Utils.parseRequest(req, options);
-    if (request instanceof Error) {
-        return callback(Boom.badRequest(request.message));
-    }
-
-    // Parse HTTP Authorization header
-
-    var attributes = Utils.parseAuthorizationHeader(request.authorization);
-    if (attributes instanceof Error) {
-        return callback(attributes);
-    }
-
-    // Construct artifacts container
-
-    var artifacts = {
-        method: request.method,
-        host: request.host,
-        port: request.port,
-        resource: request.url,
-        ts: attributes.ts,
-        nonce: attributes.nonce,
-        hash: attributes.hash,
-        ext: attributes.ext,
-        app: attributes.app,
-        dlg: attributes.dlg,
-        mac: attributes.mac,
-        id: attributes.id
-    };
-
-    // Verify required header attributes
-
-    if (!attributes.id ||
-        !attributes.ts ||
-        !attributes.nonce ||
-        !attributes.mac) {
-
-        return callback(Boom.badRequest('Missing attributes'), null, artifacts);
-    }
-
-    // Fetch Hawk credentials
-
-    credentialsFunc(attributes.id, function (err, credentials) {
-
-        if (err) {
-            return callback(err, credentials || null, artifacts);
-        }
-
-        if (!credentials) {
-            return callback(Boom.unauthorized('Unknown credentials', 'Hawk'), null, artifacts);
-        }
-
-        if (!credentials.key ||
-            !credentials.algorithm) {
-
-            return callback(Boom.internal('Invalid credentials'), credentials, artifacts);
-        }
-
-        if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-            return callback(Boom.internal('Unknown algorithm'), credentials, artifacts);
-        }
-
-        // Calculate MAC
-
-        var mac = Crypto.calculateMac('header', credentials, artifacts);
-        if (!Cryptiles.fixedTimeComparison(mac, attributes.mac)) {
-            return callback(Boom.unauthorized('Bad mac', 'Hawk'), credentials, artifacts);
-        }
-
-        // Check payload hash
-
-        if (options.payload ||
-            options.payload === '') {
-
-            if (!attributes.hash) {
-                return callback(Boom.unauthorized('Missing required payload hash', 'Hawk'), credentials, artifacts);
-            }
-
-            var hash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, request.contentType);
-            if (!Cryptiles.fixedTimeComparison(hash, attributes.hash)) {
-                return callback(Boom.unauthorized('Bad payload hash', 'Hawk'), credentials, artifacts);
-            }
-        }
-
-        // Check nonce
-
-        options.nonceFunc(credentials.key, attributes.nonce, attributes.ts, function (err) {
-
-            if (err) {
-                return callback(Boom.unauthorized('Invalid nonce', 'Hawk'), credentials, artifacts);
-            }
-
-            // Check timestamp staleness
-
-            if (Math.abs((attributes.ts * 1000) - now) > (options.timestampSkewSec * 1000)) {
-                var tsm = Crypto.timestampMessage(credentials, options.localtimeOffsetMsec);
-                return callback(Boom.unauthorized('Stale timestamp', 'Hawk', tsm), credentials, artifacts);
-            }
-
-            // Successful authentication
-
-            return callback(null, credentials, artifacts);
-        });
-    });
-};
-
-
-// Authenticate payload hash - used when payload cannot be provided during authenticate()
-
-/*
-    payload:        raw request payload
-    credentials:    from authenticate callback
-    artifacts:      from authenticate callback
-    contentType:    req.headers['content-type']
-*/
-
-exports.authenticatePayload = function (payload, credentials, artifacts, contentType) {
-
-    var calculatedHash = Crypto.calculatePayloadHash(payload, credentials.algorithm, contentType);
-    return Cryptiles.fixedTimeComparison(calculatedHash, artifacts.hash);
-};
-
-
-// Authenticate payload hash - used when payload cannot be provided during authenticate()
-
-/*
-    calculatedHash: the payload hash calculated using Crypto.calculatePayloadHash()
-    artifacts:      from authenticate callback
-*/
-
-exports.authenticatePayloadHash = function (calculatedHash, artifacts) {
-
-    return Cryptiles.fixedTimeComparison(calculatedHash, artifacts.hash);
-};
-
-
-// Generate a Server-Authorization header for a given response
-
-/*
-    credentials: {},                                        // Object received from authenticate()
-    artifacts: {}                                           // Object received from authenticate(); 'mac', 'hash', and 'ext' - ignored
-    options: {
-        ext: 'application-specific',                        // Application specific data sent via the ext attribute
-        payload: '{"some":"payload"}',                      // UTF-8 encoded string for body hash generation (ignored if hash provided)
-        contentType: 'application/json',                    // Payload content-type (ignored if hash provided)
-        hash: 'U4MKKSmiVxk37JCCrAVIjV='                     // Pre-calculated payload hash
-    }
-*/
-
-exports.header = function (credentials, artifacts, options) {
-
-    // Prepare inputs
-
-    options = options || {};
-
-    if (!artifacts ||
-        typeof artifacts !== 'object' ||
-        typeof options !== 'object') {
-
-        return '';
-    }
-
-    artifacts = Hoek.clone(artifacts);
-    delete artifacts.mac;
-    artifacts.hash = options.hash;
-    artifacts.ext = options.ext;
-
-    // Validate credentials
-
-    if (!credentials ||
-        !credentials.key ||
-        !credentials.algorithm) {
-
-        // Invalid credential object
-        return '';
-    }
-
-    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-        return '';
-    }
-
-    // Calculate payload hash
-
-    if (!artifacts.hash &&
-        (options.payload || options.payload === '')) {
-
-        artifacts.hash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
-    }
-
-    var mac = Crypto.calculateMac('response', credentials, artifacts);
-
-    // Construct header
-
-    var header = 'Hawk mac="' + mac + '"' +
-                 (artifacts.hash ? ', hash="' + artifacts.hash + '"' : '');
-
-    if (artifacts.ext !== null &&
-        artifacts.ext !== undefined &&
-        artifacts.ext !== '') {                       // Other falsey values allowed
-
-        header += ', ext="' + Hoek.escapeHeaderAttribute(artifacts.ext) + '"';
-    }
-
-    return header;
-};
-
-
-/*
- * Arguments and options are the same as authenticate() with the exception that the only supported options are:
- * 'hostHeaderName', 'localtimeOffsetMsec', 'host', 'port'
- */
-
-
-//                       1     2             3           4
-internals.bewitRegex = /^(\/.*)([\?&])bewit\=([^&$]*)(?:&(.+))?$/;
-
-
-exports.authenticateBewit = function (req, credentialsFunc, options, callback) {
-
-    callback = Hoek.nextTick(callback);
-
-    // Application time
-
-    var now = Utils.now(options.localtimeOffsetMsec);
-
-    // Convert node Http request object to a request configuration object
-
-    var request = Utils.parseRequest(req, options);
-    if (request instanceof Error) {
-        return callback(Boom.badRequest(request.message));
-    }
-
-    // Extract bewit
-
-    if (request.url.length > Utils.limits.maxMatchLength) {
-        return callback(Boom.badRequest('Resource path exceeds max length'));
-    }
-
-    var resource = request.url.match(internals.bewitRegex);
-    if (!resource) {
-        return callback(Boom.unauthorized(null, 'Hawk'));
-    }
-
-    // Bewit not empty
-
-    if (!resource[3]) {
-        return callback(Boom.unauthorized('Empty bewit', 'Hawk'));
-    }
-
-    // Verify method is GET
-
-    if (request.method !== 'GET' &&
-        request.method !== 'HEAD') {
-
-        return callback(Boom.unauthorized('Invalid method', 'Hawk'));
-    }
-
-    // No other authentication
-
-    if (request.authorization) {
-        return callback(Boom.badRequest('Multiple authentications'));
-    }
-
-    // Parse bewit
-
-    var bewitString = Hoek.base64urlDecode(resource[3]);
-    if (bewitString instanceof Error) {
-        return callback(Boom.badRequest('Invalid bewit encoding'));
-    }
-
-    // Bewit format: id\exp\mac\ext ('\' is used because it is a reserved header attribute character)
-
-    var bewitParts = bewitString.split('\\');
-    if (bewitParts.length !== 4) {
-        return callback(Boom.badRequest('Invalid bewit structure'));
-    }
-
-    var bewit = {
-        id: bewitParts[0],
-        exp: parseInt(bewitParts[1], 10),
-        mac: bewitParts[2],
-        ext: bewitParts[3] || ''
-    };
-
-    if (!bewit.id ||
-        !bewit.exp ||
-        !bewit.mac) {
-
-        return callback(Boom.badRequest('Missing bewit attributes'));
-    }
-
-    // Construct URL without bewit
-
-    var url = resource[1];
-    if (resource[4]) {
-        url += resource[2] + resource[4];
-    }
-
-    // Check expiration
-
-    if (bewit.exp * 1000 <= now) {
-        return callback(Boom.unauthorized('Access expired', 'Hawk'), null, bewit);
-    }
-
-    // Fetch Hawk credentials
-
-    credentialsFunc(bewit.id, function (err, credentials) {
-
-        if (err) {
-            return callback(err, credentials || null, bewit.ext);
-        }
-
-        if (!credentials) {
-            return callback(Boom.unauthorized('Unknown credentials', 'Hawk'), null, bewit);
-        }
-
-        if (!credentials.key ||
-            !credentials.algorithm) {
-
-            return callback(Boom.internal('Invalid credentials'), credentials, bewit);
-        }
-
-        if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-            return callback(Boom.internal('Unknown algorithm'), credentials, bewit);
-        }
-
-        // Calculate MAC
-
-        var mac = Crypto.calculateMac('bewit', credentials, {
-            ts: bewit.exp,
-            nonce: '',
-            method: 'GET',
-            resource: url,
-            host: request.host,
-            port: request.port,
-            ext: bewit.ext
-        });
-
-        if (!Cryptiles.fixedTimeComparison(mac, bewit.mac)) {
-            return callback(Boom.unauthorized('Bad mac', 'Hawk'), credentials, bewit);
-        }
-
-        // Successful authentication
-
-        return callback(null, credentials, bewit);
-    });
-};
-
-
-/*
- *  options are the same as authenticate() with the exception that the only supported options are:
- * 'nonceFunc', 'timestampSkewSec', 'localtimeOffsetMsec'
- */
-
-exports.authenticateMessage = function (host, port, message, authorization, credentialsFunc, options, callback) {
-
-    callback = Hoek.nextTick(callback);
-
-    // Default options
-
-    options.nonceFunc = options.nonceFunc || internals.nonceFunc;
-    options.timestampSkewSec = options.timestampSkewSec || 60;                                                  // 60 seconds
-
-    // Application time
-
-    var now = Utils.now(options.localtimeOffsetMsec);                       // Measure now before any other processing
-
-    // Validate authorization
-
-    if (!authorization.id ||
-        !authorization.ts ||
-        !authorization.nonce ||
-        !authorization.hash ||
-        !authorization.mac) {
-
-        return callback(Boom.badRequest('Invalid authorization'));
-    }
-
-    // Fetch Hawk credentials
-
-    credentialsFunc(authorization.id, function (err, credentials) {
-
-        if (err) {
-            return callback(err, credentials || null);
-        }
-
-        if (!credentials) {
-            return callback(Boom.unauthorized('Unknown credentials', 'Hawk'));
-        }
-
-        if (!credentials.key ||
-            !credentials.algorithm) {
-
-            return callback(Boom.internal('Invalid credentials'), credentials);
-        }
-
-        if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
-            return callback(Boom.internal('Unknown algorithm'), credentials);
-        }
-
-        // Construct artifacts container
-
-        var artifacts = {
-            ts: authorization.ts,
-            nonce: authorization.nonce,
-            host: host,
-            port: port,
-            hash: authorization.hash
-        };
-
-        // Calculate MAC
-
-        var mac = Crypto.calculateMac('message', credentials, artifacts);
-        if (!Cryptiles.fixedTimeComparison(mac, authorization.mac)) {
-            return callback(Boom.unauthorized('Bad mac', 'Hawk'), credentials);
-        }
-
-        // Check payload hash
-
-        var hash = Crypto.calculatePayloadHash(message, credentials.algorithm);
-        if (!Cryptiles.fixedTimeComparison(hash, authorization.hash)) {
-            return callback(Boom.unauthorized('Bad message hash', 'Hawk'), credentials);
-        }
-
-        // Check nonce
-
-        options.nonceFunc(credentials.key, authorization.nonce, authorization.ts, function (err) {
-
-            if (err) {
-                return callback(Boom.unauthorized('Invalid nonce', 'Hawk'), credentials);
-            }
-
-            // Check timestamp staleness
-
-            if (Math.abs((authorization.ts * 1000) - now) > (options.timestampSkewSec * 1000)) {
-                return callback(Boom.unauthorized('Stale timestamp'), credentials);
-            }
-
-            // Successful authentication
-
-            return callback(null, credentials);
-        });
-    });
-};
-
-
-internals.nonceFunc = function (key, nonce, ts, nonceCallback) {
-
-    return nonceCallback();         // No validation
-};
+'use strict';
+
+const B64 = require('@hapi/b64');
+const Boom = require('@hapi/boom');
+const Cryptiles = require('@hapi/cryptiles');
+const Hoek = require('@hapi/hoek');
+
+const Crypto = require('./crypto');
+const Utils = require('./utils');
+
+
+const internals = {};
+
+
+// Hawk authentication
+
+/*
+   req:                 node's HTTP request object or an object as follows:
+
+                        const request = {
+                            method: 'GET',
+                            url: '/resource/4?a=1&b=2',
+                            host: 'example.com',
+                            port: 8080,
+                            authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="'
+                        };
+
+   credentialsFunc:     required function to lookup the set of Hawk credentials based on the provided credentials id.
+                        The credentials include the MAC key, MAC algorithm, and other attributes (such as username)
+                        needed by the application. This function is the equivalent of verifying the username and
+                        password in Basic authentication.
+
+                        const credentialsFunc = async function (id) {
+
+                            // Lookup credentials in database
+
+                            const item = await db.lookup(id);       // Can throw errors
+                            if (!item) {
+                                return null;
+                            }
+
+                            const credentials = {
+                                // Required
+                                key: item.key,
+                                algorithm: item.algorithm,
+                                // Application specific
+                                user: item.user
+                            };
+
+                            return credentials;
+                        };
+
+   options: {
+
+        hostHeaderName:        optional header field name, used to override the default 'Host' header when used
+                               behind a cache of a proxy. Apache2 changes the value of the 'Host' header while preserving
+                               the original (which is what the module must verify) in the 'x-forwarded-host' header field.
+                               Only used when passed a node Http.ServerRequest object.
+
+        nonceFunc:             optional nonce validation function. The function signature is `async function(key, nonce, ts)`
+                               and it must return no value for success or throw an error for invalid state.
+
+        timestampSkewSec:      optional number of seconds of permitted clock skew for incoming timestamps. Defaults to 60 seconds.
+                               Provides a +/- skew which means actual allowed window is double the number of seconds.
+
+        localtimeOffsetMsec:   optional local clock time offset express in a number of milliseconds (positive or negative).
+                               Defaults to 0.
+
+        payload:               optional payload for validation. The client calculates the hash value and includes it via the 'hash'
+                               header attribute. The server always ensures the value provided has been included in the request
+                               MAC. When this option is provided, it validates the hash value itself. Validation is done by calculating
+                               a hash value over the entire payload (assuming it has already be normalized to the same format and
+                               encoding used by the client to calculate the hash on request). If the payload is not available at the time
+                               of authentication, the authenticatePayload() method can be used by passing it the credentials and
+                               attributes.hash returned from authenticate().
+
+        host:                  optional host name override. Only used when passed a node request object.
+        port:                  optional port override. Only used when passed a node request object.
+    }
+
+    Return value: { credentials, artifacts } or throws an error.
+ */
+
+exports.authenticate = async function (req, credentialsFunc, options) {
+
+    options = options || {};
+
+    // Default options
+
+    options.timestampSkewSec = options.timestampSkewSec || 60;                                                  // 60 seconds
+
+    // Application time
+
+    const now = Utils.now(options.localtimeOffsetMsec);                           // Measure now before any other processing
+
+    // Convert node Http request object to a request configuration object
+
+    const request = Utils.parseRequest(req, options);
+
+    // Parse HTTP Authorization header
+
+    const attributes = Utils.parseAuthorizationHeader(request.authorization);
+
+    // Construct artifacts container
+
+    const artifacts = {
+        method: request.method,
+        host: request.host,
+        port: request.port,
+        resource: request.url,
+        ts: attributes.ts,
+        nonce: attributes.nonce,
+        hash: attributes.hash,
+        ext: attributes.ext,
+        app: attributes.app,
+        dlg: attributes.dlg,
+        mac: attributes.mac,
+        id: attributes.id
+    };
+
+    // Verify required header attributes
+
+    if (!attributes.id ||
+        !attributes.ts ||
+        !attributes.nonce ||
+        !attributes.mac) {
+
+        throw Boom.badRequest('Missing attributes', { decorate: { artifacts } });
+    }
+
+    // Fetch Hawk credentials
+
+    try {
+        var credentials = await credentialsFunc(attributes.id);
+    }
+    catch (err) {
+        throw Boom.boomify(err, { decorate: { artifacts } });
+    }
+
+    if (!credentials) {
+        throw Object.assign(Utils.unauthorized('Unknown credentials'), { artifacts });
+    }
+
+    const result = { credentials, artifacts };
+
+    if (!credentials.key ||
+        !credentials.algorithm) {
+
+        throw new Boom.Boom('Invalid credentials', { decorate: result });
+    }
+
+    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
+        throw new Boom.Boom('Unknown algorithm', { decorate: result });
+    }
+
+    // Check payload hash
+
+    if (options.payload ||
+        options.payload === '') {
+
+        if (!attributes.hash) {
+            throw Object.assign(Utils.unauthorized('Missing required payload hash'), result);
+        }
+
+        const hash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, request.contentType);
+        if (!Cryptiles.fixedTimeComparison(hash, attributes.hash)) {
+            throw Object.assign(Utils.unauthorized('Bad payload hash'), result);
+        }
+    }
+
+    // Calculate MAC
+
+    const mac = Crypto.calculateServerMac('header', credentials, artifacts, options.payload, request.contentType);
+    if (!Cryptiles.fixedTimeComparison(mac, attributes.mac)) {
+        throw Object.assign(Utils.unauthorized('Bad mac'), result);
+    }
+
+    // Check nonce
+
+    if (options.nonceFunc) {
+        try {
+            await options.nonceFunc(credentials.key, attributes.nonce, attributes.ts);
+        }
+        catch (err) {
+            throw Object.assign(Utils.unauthorized('Invalid nonce'), result);
+        }
+    }
+
+    // Check timestamp staleness
+
+    if (Math.abs((attributes.ts * 1000) - now) > (options.timestampSkewSec * 1000)) {
+        const tsm = Crypto.timestampMessage(credentials, options.localtimeOffsetMsec);
+        throw Object.assign(Utils.unauthorized('Stale timestamp', tsm), result);
+    }
+
+    // Successful authentication
+
+    return result;
+};
+
+
+// Authenticate payload hash - used when payload cannot be provided during authenticate()
+
+/*
+    payload:        raw request payload
+    credentials:    from authenticate()
+    artifacts:      from authenticate()
+    contentType:    req.headers['content-type']
+
+    Return value: void or throws an error.
+*/
+
+exports.authenticatePayload = function (payload, credentials, artifacts, contentType) {
+
+    const calculatedHash = Crypto.calculatePayloadHash(payload, credentials.algorithm, contentType);
+    if (!Cryptiles.fixedTimeComparison(calculatedHash, artifacts.hash)) {
+        throw Object.assign(Utils.unauthorized('Bad payload hash'), { credentials, artifacts });
+    }
+};
+
+
+// Authenticate payload hash - used when payload cannot be provided during authenticate()
+
+/*
+    calculatedHash: the payload hash calculated using Crypto.calculatePayloadHash()
+    artifacts:      from authenticate()
+
+    Return value: void or throws an error.
+*/
+
+exports.authenticatePayloadHash = function (calculatedHash, artifacts) {
+
+    if (!Cryptiles.fixedTimeComparison(calculatedHash, artifacts.hash)) {
+        throw Object.assign(Utils.unauthorized('Bad payload hash'), { artifacts });
+    }
+};
+
+
+// Generate a Server-Authorization header for a given response
+
+/*
+    credentials: {},                                        // Object received from authenticate()
+    artifacts: {}                                           // Object received from authenticate(); 'mac', 'hash', and 'ext' - ignored
+    options: {
+        ext: 'application-specific',                        // Application specific data sent via the ext attribute
+        payload: '{"some":"payload"}',                      // UTF-8 encoded string for body hash generation (ignored if hash provided)
+        contentType: 'application/json',                    // Payload content-type (ignored if hash provided)
+        hash: 'U4MKKSmiVxk37JCCrAVIjV='                     // Pre-calculated payload hash
+    }
+*/
+
+exports.header = function (credentials, artifacts, options) {
+
+    options = options || {};
+
+    // Prepare inputs
+
+    if (!artifacts ||
+        typeof artifacts !== 'object' ||
+        typeof options !== 'object') {
+
+        throw new Boom.Boom('Invalid inputs');
+    }
+
+    artifacts = Hoek.clone(artifacts);
+    delete artifacts.mac;
+    artifacts.hash = options.hash;
+    artifacts.ext = options.ext;
+
+    // Validate credentials
+
+    if (!credentials ||
+        !credentials.key ||
+        !credentials.algorithm) {
+
+        throw new Boom.Boom('Invalid credentials');
+    }
+
+    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
+        throw new Boom.Boom('Unknown algorithm');
+    }
+
+    // Calculate payload hash
+
+    if (!artifacts.hash &&
+        (options.payload || options.payload === '')) {
+
+        artifacts.hash = Crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
+    }
+
+    const mac = Crypto.calculateServerMac('response', credentials, artifacts, options.payload, options.contentType);
+
+    // Construct header
+
+    let header = 'Hawk mac="' + mac + '"' +
+        (artifacts.hash ? ', hash="' + artifacts.hash + '"' : '');
+
+    if (artifacts.ext !== null &&
+        artifacts.ext !== undefined &&
+        artifacts.ext !== '') {                       // Other falsey values allowed
+
+        header = header + ', ext="' + Hoek.escapeHeaderAttribute(artifacts.ext) + '"';
+    }
+
+    return header;
+};
+
+
+/*
+ * Arguments and options are the same as authenticate() with the exception that the only supported options are:
+ * 'hostHeaderName', 'localtimeOffsetMsec', 'host', 'port'
+ */
+
+
+//                       1     2             3           4
+internals.bewitRegex = /^(\/.*)([\?&])bewit\=([^&$]*)(?:&(.+))?$/;
+
+
+exports.authenticateBewit = async function (req, credentialsFunc, options) {
+
+    options = options || {};
+
+    // Application time
+
+    const now = Utils.now(options.localtimeOffsetMsec);
+
+    // Convert node Http request object to a request configuration object
+
+    const request = Utils.parseRequest(req, options);
+
+    // Extract bewit
+
+    if (request.url.length > Utils.limits.maxMatchLength) {
+        throw Boom.badRequest('Resource path exceeds max length');
+    }
+
+    const resource = request.url.match(internals.bewitRegex);
+    if (!resource) {
+        throw Utils.unauthorized();
+    }
+
+    // Bewit not empty
+
+    if (!resource[3]) {
+        throw Utils.unauthorized('Empty bewit');
+    }
+
+    // Verify method is GET
+
+    if (request.method !== 'GET' &&
+        request.method !== 'HEAD') {
+
+        throw Utils.unauthorized('Invalid method');
+    }
+
+    // No other authentication
+
+    if (request.authorization) {
+        throw Boom.badRequest('Multiple authentications');
+    }
+
+    // Parse bewit
+
+    try {
+        var bewitString = B64.base64urlDecode(resource[3]);
+    }
+    catch (err) {
+        throw Boom.badRequest('Invalid bewit encoding');
+    }
+
+    // Bewit format: id\exp\mac\ext ('\' is used because it is a reserved header attribute character)
+
+    const bewitParts = bewitString.split('\\');
+    if (bewitParts.length !== 4) {
+        throw Boom.badRequest('Invalid bewit structure');
+    }
+
+    const bewit = {
+        id: bewitParts[0],
+        exp: bewitParts[1],
+        mac: bewitParts[2],
+        ext: bewitParts[3] || ''
+    };
+
+    if (!bewit.id ||
+        !bewit.exp ||
+        !bewit.mac) {
+
+        throw Boom.badRequest('Missing bewit attributes');
+    }
+
+    // Construct URL without bewit
+
+    let url = resource[1];
+    if (resource[4]) {
+        url = url + resource[2] + resource[4];
+    }
+
+    // Fetch Hawk credentials
+
+    try {
+        var credentials = await credentialsFunc(bewit.id);
+    }
+    catch (err) {
+        throw new Boom.Boom(err, { decorate: { bewit } });
+    }
+
+    if (!credentials) {
+        throw Object.assign(Utils.unauthorized('Unknown credentials'), { bewit });
+    }
+
+    const result = { credentials, attributes: bewit };
+
+    if (!credentials.key ||
+        !credentials.algorithm) {
+
+        throw new Boom.Boom('Invalid credentials', { decorate: result });
+    }
+
+    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
+        throw new Boom.Boom('Unknown algorithm', { decorate: result });
+    }
+
+    // Calculate MAC
+
+    const mac = Crypto.generateRequestMac('bewit', credentials, {
+        ts: bewit.exp,
+        nonce: '',
+        method: 'GET',
+        resource: url,
+        host: request.host,
+        port: request.port,
+        ext: bewit.ext
+    });
+
+    if (!Cryptiles.fixedTimeComparison(mac, bewit.mac)) {
+        throw Object.assign(Utils.unauthorized('Bad mac'), result);
+    }
+
+    // Check expiration
+
+    if (parseInt(bewit.exp, 10) * 1000 <= now) {
+        throw Object.assign(Utils.unauthorized('Access expired'), { bewit });
+    }
+
+    // Successful authentication
+
+    return result;
+};
+
+
+/*
+ *  options are the same as authenticate() with the exception that the only supported options are:
+ * 'nonceFunc', 'timestampSkewSec', 'localtimeOffsetMsec'
+ */
+
+exports.authenticateMessage = async function (host, port, message, authorization, credentialsFunc, options) {
+
+    options = options || {};
+
+    // Default options
+
+    options.timestampSkewSec = options.timestampSkewSec || 60;                                                  // 60 seconds
+
+    // Application time
+
+    const now = Utils.now(options.localtimeOffsetMsec);                       // Measure now before any other processing
+
+    // Validate authorization
+
+    if (!authorization.id ||
+        !authorization.ts ||
+        !authorization.nonce ||
+        !authorization.hash ||
+        !authorization.mac) {
+
+        throw Boom.badRequest('Invalid authorization');
+    }
+
+    // Fetch Hawk credentials
+
+    const credentials = await credentialsFunc(authorization.id);
+    if (!credentials) {
+        throw Utils.unauthorized('Unknown credentials');
+    }
+
+    const result = { credentials };
+
+    if (!credentials.key ||
+        !credentials.algorithm) {
+
+        throw new Boom.Boom('Invalid credentials', { decorate: result });
+    }
+
+    if (Crypto.algorithms.indexOf(credentials.algorithm) === -1) {
+        throw new Boom.Boom('Unknown algorithm', { decorate: result });
+    }
+
+    // Construct artifacts container
+
+    const artifacts = {
+        ts: authorization.ts,
+        nonce: authorization.nonce,
+        host,
+        port,
+        hash: authorization.hash
+    };
+
+    // Calculate MAC
+
+    const mac = Crypto.generateRequestMac('message', credentials, artifacts);
+    if (!Cryptiles.fixedTimeComparison(mac, authorization.mac)) {
+        throw Object.assign(Utils.unauthorized('Bad mac'), result);
+    }
+
+    // Check payload hash
+
+    const hash = Crypto.calculatePayloadHash(message, credentials.algorithm);
+    if (!Cryptiles.fixedTimeComparison(hash, authorization.hash)) {
+        throw Object.assign(Utils.unauthorized('Bad message hash'), result);
+    }
+
+    // Check nonce
+
+    if (options.nonceFunc) {
+        try {
+            await options.nonceFunc(credentials.key, authorization.nonce, authorization.ts);
+        }
+        catch (err) {
+            throw Object.assign(Utils.unauthorized('Invalid nonce'), result);
+        }
+    }
+
+    // Check timestamp staleness
+
+    if (Math.abs((authorization.ts * 1000) - now) > (options.timestampSkewSec * 1000)) {
+        throw Object.assign(Utils.unauthorized('Stale timestamp'), result);
+    }
+
+    // Successful authentication
+
+    return result;
+};
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/lib/utils.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/lib/utils.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/lib/utils.js	(working copy)
@@ -1,184 +1,194 @@
-// Load modules
-
-var Sntp = require('sntp');
-var Boom = require('boom');
-
-
-// Declare internals
-
-var internals = {};
-
-
-exports.version = function () {
-
-    return require('../package.json').version;
-};
-
-
-exports.limits = {
-    maxMatchLength: 4096            // Limit the length of uris and headers to avoid a DoS attack on string matching
-};
-
-
-// Extract host and port from request
-
-//                                            $1                            $2
-internals.hostHeaderRegex = /^(?:(?:\r\n)?\s)*((?:[^:]+)|(?:\[[^\]]+\]))(?::(\d+))?(?:(?:\r\n)?\s)*$/;              // (IPv4, hostname)|(IPv6)
-
-
-exports.parseHost = function (req, hostHeaderName) {
-
-    hostHeaderName = (hostHeaderName ? hostHeaderName.toLowerCase() : 'host');
-    var hostHeader = req.headers[hostHeaderName];
-    if (!hostHeader) {
-        return null;
-    }
-
-    if (hostHeader.length > exports.limits.maxMatchLength) {
-        return null;
-    }
-
-    var hostParts = hostHeader.match(internals.hostHeaderRegex);
-    if (!hostParts) {
-        return null;
-    }
-
-    return {
-        name: hostParts[1],
-        port: (hostParts[2] ? hostParts[2] : (req.connection && req.connection.encrypted ? 443 : 80))
-    };
-};
-
-
-// Parse Content-Type header content
-
-exports.parseContentType = function (header) {
-
-    if (!header) {
-        return '';
-    }
-
-    return header.split(';')[0].trim().toLowerCase();
-};
-
-
-// Convert node's  to request configuration object
-
-exports.parseRequest = function (req, options) {
-
-    if (!req.headers) {
-        return req;
-    }
-
-    // Obtain host and port information
-
-    var host;
-    if (!options.host ||
-        !options.port) {
-
-        host = exports.parseHost(req, options.hostHeaderName);
-        if (!host) {
-            return new Error('Invalid Host header');
-        }
-    }
-
-    var request = {
-        method: req.method,
-        url: req.url,
-        host: options.host || host.name,
-        port: options.port || host.port,
-        authorization: req.headers.authorization,
-        contentType: req.headers['content-type'] || ''
-    };
-
-    return request;
-};
-
-
-exports.now = function (localtimeOffsetMsec) {
-
-    return Sntp.now() + (localtimeOffsetMsec || 0);
-};
-
-
-exports.nowSecs = function (localtimeOffsetMsec) {
-
-    return Math.floor(exports.now(localtimeOffsetMsec) / 1000);
-};
-
-
-internals.authHeaderRegex = /^(\w+)(?:\s+(.*))?$/;                                      // Header: scheme[ something]
-internals.attributeRegex = /^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~]+$/;   // !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9
-
-
-// Parse Hawk HTTP Authorization header
-
-exports.parseAuthorizationHeader = function (header, keys) {
-
-    keys = keys || ['id', 'ts', 'nonce', 'hash', 'ext', 'mac', 'app', 'dlg'];
-
-    if (!header) {
-        return Boom.unauthorized(null, 'Hawk');
-    }
-
-    if (header.length > exports.limits.maxMatchLength) {
-        return Boom.badRequest('Header length too long');
-    }
-
-    var headerParts = header.match(internals.authHeaderRegex);
-    if (!headerParts) {
-        return Boom.badRequest('Invalid header syntax');
-    }
-
-    var scheme = headerParts[1];
-    if (scheme.toLowerCase() !== 'hawk') {
-        return Boom.unauthorized(null, 'Hawk');
-    }
-
-    var attributesString = headerParts[2];
-    if (!attributesString) {
-        return Boom.badRequest('Invalid header syntax');
-    }
-
-    var attributes = {};
-    var errorMessage = '';
-    var verify = attributesString.replace(/(\w+)="([^"\\]*)"\s*(?:,\s*|$)/g, function ($0, $1, $2) {
-
-        // Check valid attribute names
-
-        if (keys.indexOf($1) === -1) {
-            errorMessage = 'Unknown attribute: ' + $1;
-            return;
-        }
-
-        // Allowed attribute value characters
-
-        if ($2.match(internals.attributeRegex) === null) {
-            errorMessage = 'Bad attribute value: ' + $1;
-            return;
-        }
-
-        // Check for duplicates
-
-        if (attributes.hasOwnProperty($1)) {
-            errorMessage = 'Duplicate attribute: ' + $1;
-            return;
-        }
-
-        attributes[$1] = $2;
-        return '';
-    });
-
-    if (verify !== '') {
-        return Boom.badRequest(errorMessage || 'Bad header format');
-    }
-
-    return attributes;
-};
-
-
-exports.unauthorized = function (message, attributes) {
-
-    return Boom.unauthorized(message, 'Hawk', attributes);
-};
-
+'use strict';
+
+const Boom = require('@hapi/boom');
+const Url = require('url');
+
+
+const internals = {};
+
+
+exports.version = function () {
+
+    return require('../package.json').version;
+};
+
+
+exports.limits = {
+    maxMatchLength: 4096            // Limit the length of uris and headers to avoid a DoS attack on string matching
+};
+
+
+exports.parseHost = function (req, hostHeaderName) {
+
+    hostHeaderName = (hostHeaderName ? hostHeaderName.toLowerCase() : 'host');
+    const hostHeader = req.headers[hostHeaderName];
+    if (!hostHeader) {
+        return null;
+    }
+
+    if (hostHeader.length > exports.limits.maxMatchLength) {
+        return null;
+    }
+
+    if (hostHeader.indexOf('/') !== -1) {
+        return null;
+    }
+
+    let uri;
+    try {
+        uri = new Url.URL('http://' + hostHeader);
+    }
+    catch (err) {
+        return null;
+    }
+
+    return {
+        name: uri.hostname,
+        port: (uri.port ? uri.port : (req.connection && req.connection.encrypted ? 443 : 80))
+    };
+};
+
+
+// Parse Content-Type header content
+
+exports.parseContentType = function (header) {
+
+    if (!header) {
+        return '';
+    }
+
+    return header.split(';')[0].trim().toLowerCase();
+};
+
+
+// Convert node's  to request configuration object
+
+exports.parseRequest = function (req, options) {
+
+    if (!req.headers) {
+        return req;
+    }
+
+    // Obtain host and port information
+
+    let host;
+    if (!options.host ||
+        !options.port) {
+
+        host = exports.parseHost(req, options.hostHeaderName);
+        if (!host) {
+            throw Boom.badRequest('Invalid Host header');
+        }
+    }
+
+    const request = {
+        method: req.method,
+        url: req.url,
+        host: options.host || host.name,
+        port: options.port || host.port,
+        authorization: req.headers.authorization,
+        contentType: req.headers['content-type'] || ''
+    };
+
+    return request;
+};
+
+
+let _now = Date.now;
+
+
+// override the `now` function, e.g., to use sntp
+
+exports.setTimeFunction = function (fn) {
+
+    _now = fn;
+};
+
+
+exports.now = function (localtimeOffsetMsec) {
+
+    return _now() + (localtimeOffsetMsec || 0);
+};
+
+
+exports.nowSecs = function (localtimeOffsetMsec) {
+
+    return Math.floor(exports.now(localtimeOffsetMsec) / 1000);
+};
+
+
+internals.authHeaderRegex = /^(\w+)(?:\s+(.*))?$/;                                      // Header: scheme[ something]
+internals.attributeRegex = /^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~]+$/;   // !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9
+
+
+// Parse Hawk HTTP Authorization header
+
+exports.parseAuthorizationHeader = function (header, keys) {
+
+    keys = keys || ['id', 'ts', 'nonce', 'hash', 'ext', 'mac', 'app', 'dlg'];
+
+    if (!header) {
+        throw Boom.unauthorized(null, 'Hawk');
+    }
+
+    if (header.length > exports.limits.maxMatchLength) {
+        throw Boom.badRequest('Header length too long');
+    }
+
+    const headerParts = header.match(internals.authHeaderRegex);
+    if (!headerParts) {
+        throw Boom.badRequest('Invalid header syntax');
+    }
+
+    const scheme = headerParts[1];
+    if (scheme.toLowerCase() !== 'hawk') {
+        throw Boom.unauthorized(null, 'Hawk');
+    }
+
+    const attributesString = headerParts[2];
+    if (!attributesString) {
+        throw Boom.badRequest('Invalid header syntax');
+    }
+
+    const attributes = {};
+    let errorMessage = '';
+    const verify = attributesString.replace(/(\w+)="([^"\\]*)"\s*(?:,\s*|$)/g, ($0, $1, $2) => {
+
+        // Check valid attribute names
+
+        if (keys.indexOf($1) === -1) {
+            errorMessage = 'Unknown attribute: ' + $1;
+            return;
+        }
+
+        // Allowed attribute value characters
+
+        if ($2.match(internals.attributeRegex) === null) {
+            errorMessage = 'Bad attribute value: ' + $1;
+            return;
+        }
+
+        // Check for duplicates
+
+        if (attributes.hasOwnProperty($1)) {
+            errorMessage = 'Duplicate attribute: ' + $1;
+            return;
+        }
+
+        attributes[$1] = $2;
+        return '';
+    });
+
+    if (verify !== '') {
+        throw Boom.badRequest(errorMessage || 'Bad header format');
+    }
+
+    return attributes;
+};
+
+
+exports.unauthorized = function (message, attributes) {
+
+    return Boom.unauthorized(message || null, 'Hawk', attributes);
+};
+
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/LICENSE
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/LICENSE	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/LICENSE	(working copy)
@@ -1,31 +1,13 @@
-Copyright (c) 2011-2014, Walmart and other contributors.
+Copyright (c) 2011-2022, Project contributors
+Copyright (c) 2011-2020, Sideway Inc
+Copyright (c) 2011-2014, Walmart
 Copyright (c) 2011, Yahoo Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-    * The names of any contributors may not be used to endorse or promote
-      products derived from this software without specific prior written
-      permission.
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+All rights reserved.
 
-                                  *   *   *
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+* The names of any contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
 
-The complete list of contributors can be found at: https://github.com/hapijs/hapi/graphs/contributors
-Portions of this project were initially based on the Yahoo! Inc. Postmile project,
-published at https://github.com/yahoo/postmile.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS OFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/README.md
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/README.md	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/README.md	(working copy)
@@ -1,584 +1,19 @@
-![hoek Logo](https://raw.github.com/hapijs/hoek/master/images/hoek.png)
+<a href="https://hapi.dev"><img src="https://raw.githubusercontent.com/hapijs/assets/master/images/family.png" width="180px" align="right" /></a>
 
-Utility methods for the hapi ecosystem. This module is not intended to solve every problem for everyone, but rather as a central place to store hapi-specific methods. If you're looking for a general purpose utility module, check out [lodash](https://github.com/lodash/lodash) or [underscore](https://github.com/jashkenas/underscore).
+# @hapi/hoek
 
-[![Build Status](https://secure.travis-ci.org/hapijs/hoek.svg)](http://travis-ci.org/hapijs/hoek)
+#### Utility methods for the hapi ecosystem.
 
-Lead Maintainer: [Nathan LaFreniere](https://github.com/nlf)
+**hoek** is part of the **hapi** ecosystem and was designed to work seamlessly with the [hapi web framework](https://hapi.dev) and its other components (but works great on its own or with other frameworks). If you are using a different web framework and find this module useful, check out [hapi](https://hapi.dev) – they work even better together.
 
-# Table of Contents
+This module is not intended to solve every problem for everyone, but rather as a central place to store hapi-specific methods. If you're looking for a general purpose utility module, check out [lodash](https://github.com/lodash/lodash).
 
-* [Introduction](#introduction "Introduction")
-* [Object](#object "Object")
-  * [clone](#cloneobj "clone")
-  * [cloneWithShallow](#clonewithshallowobj-keys "cloneWithShallow")
-  * [merge](#mergetarget-source-isnulloverride-ismergearrays "merge")
-  * [applyToDefaults](#applytodefaultsdefaults-options-isnulloverride "applyToDefaults")
-  * [applyToDefaultsWithShallow](#applytodefaultswithshallowdefaults-options-keys "applyToDefaultsWithShallow")
-  * [deepEqual](#deepequala-b "deepEqual")
-  * [unique](#uniquearray-key "unique")
-  * [mapToObject](#maptoobjectarray-key "mapToObject")
-  * [intersect](#intersectarray1-array2 "intersect")
-  * [contain](#containref-values-options "contain")
-  * [flatten](#flattenarray-target "flatten")
-  * [reach](#reachobj-chain-options "reach")
-  * [reachTemplate](#reachtemplateobj-template-options "reachTemplate")
-  * [transform](#transformobj-transform-options "transform")
-  * [shallow](#shallowobj "shallow")
-  * [stringify](#stringifyobj "stringify")
-* [Timer](#timer "Timer")
-* [Bench](#bench "Bench")
-* [Binary Encoding/Decoding](#binary-encodingdecoding "Binary Encoding/Decoding")
-  * [base64urlEncode](#base64urlencodevalue "binary64urlEncode")
-  * [base64urlDecode](#base64urldecodevalue "binary64urlDecode")
-* [Escaping Characters](#escaping-characters "Escaping Characters")
-  * [escapeHtml](#escapehtmlstring "escapeHtml")
-  * [escapeHeaderAttribute](#escapeheaderattributeattribute "escapeHeaderAttribute")
-  * [escapeRegex](#escaperegexstring "escapeRegex")
-* [Errors](#errors "Errors")
-  * [assert](#assertcondition-message "assert")
-  * [abort](#abortmessage "abort")
-  * [displayStack](#displaystackslice "displayStack")
-  * [callStack](#callstackslice "callStack")
-* [Function](#function "Function")
-  * [nextTick](#nexttickfn "nextTick")
-  * [once](#oncefn "once")
-  * [ignore](#ignore "ignore")
-* [Miscellaneous](#miscellaneous "Miscellaneous")
-  * [uniqueFilename](#uniquefilenamepath-extension "uniqueFilename")
-  * [isAbsolutePath](#isabsolutepathpath-platform "isAbsolutePath")
-  * [isInteger](#isintegervalue "isInteger")
+### Visit the [hapi.dev](https://hapi.dev) Developer Portal for tutorials, documentation, and support
 
+## Useful resources
 
-
-# Introduction
-
-The *Hoek* library contains some common functions used within the hapi ecosystem. It comes with useful methods for Arrays (clone, merge, applyToDefaults), Objects (removeKeys, copy), Asserting and more.
-
-For example, to use Hoek to set configuration with default options:
-```javascript
-var Hoek = require('hoek');
-
-var default = {url : "www.github.com", port : "8000", debug : true};
-
-var config = Hoek.applyToDefaults(default, {port : "3000", admin : true});
-
-// In this case, config would be { url: 'www.github.com', port: '3000', debug: true, admin: true }
-```
-
-Under each of the sections (such as Array), there are subsections which correspond to Hoek methods. Each subsection will explain how to use the corresponding method. In each js excerpt below, the `var Hoek = require('hoek');` is omitted for brevity.
-
-## Object
-
-Hoek provides several helpful methods for objects and arrays.
-
-### clone(obj)
-
-This method is used to clone an object or an array. A *deep copy* is made (duplicates everything, including values that are objects, as well as non-enumerable properties).
-
-```javascript
-
-var nestedObj = {
-        w: /^something$/ig,
-        x: {
-            a: [1, 2, 3],
-            b: 123456,
-            c: new Date()
-        },
-        y: 'y',
-        z: new Date()
-    };
-
-var copy = Hoek.clone(nestedObj);
-
-copy.x.b = 100;
-
-console.log(copy.y);        // results in 'y'
-console.log(nestedObj.x.b); // results in 123456
-console.log(copy.x.b);      // results in 100
-```
-
-### cloneWithShallow(obj, keys)
-keys is an array of key names to shallow copy
-
-This method is also used to clone an object or array, however any keys listed in the `keys` array are shallow copied while those not listed are deep copied.
-
-```javascript
-
-var nestedObj = {
-        w: /^something$/ig,
-        x: {
-            a: [1, 2, 3],
-            b: 123456,
-            c: new Date()
-        },
-        y: 'y',
-        z: new Date()
-    };
-
-var copy = Hoek.cloneWithShallow(nestedObj, ['x']);
-
-copy.x.b = 100;
-
-console.log(copy.y);        // results in 'y'
-console.log(nestedObj.x.b); // results in 100
-console.log(copy.x.b);      // results in 100
-```
-
-### merge(target, source, isNullOverride, isMergeArrays)
-isNullOverride, isMergeArrays default to true
-
-Merge all the properties of source into target, source wins in conflict, and by default null and undefined from source are applied.
-Merge is destructive where the target is modified. For non destructive merge, use `applyToDefaults`.
-
-
-```javascript
-
-var target = {a: 1, b : 2};
-var source = {a: 0, c: 5};
-var source2 = {a: null, c: 5};
-
-Hoek.merge(target, source);         // results in {a: 0, b: 2, c: 5}
-Hoek.merge(target, source2);        // results in {a: null, b: 2, c: 5}
-Hoek.merge(target, source2, false); // results in {a: 1, b: 2, c: 5}
-
-var targetArray = [1, 2, 3];
-var sourceArray = [4, 5];
-
-Hoek.merge(targetArray, sourceArray);              // results in [1, 2, 3, 4, 5]
-Hoek.merge(targetArray, sourceArray, true, false); // results in [4, 5]
-```
-
-### applyToDefaults(defaults, options, isNullOverride)
-isNullOverride defaults to false
-
-Apply options to a copy of the defaults
-
-```javascript
-
-var defaults = { host: "localhost", port: 8000 };
-var options = { port: 8080 };
-
-var config = Hoek.applyToDefaults(defaults, options); // results in { host: "localhost", port: 8080 }
-```
-
-Apply options with a null value to a copy of the defaults
-
-```javascript
-
-var defaults = { host: "localhost", port: 8000 };
-var options = { host: null, port: 8080 };
-
-var config = Hoek.applyToDefaults(defaults, options, true); // results in { host: null, port: 8080 }
-```
-
-### applyToDefaultsWithShallow(defaults, options, keys)
-keys is an array of key names to shallow copy
-
-Apply options to a copy of the defaults. Keys specified in the last parameter are shallow copied from options instead of merged.
-
-```javascript
-
-var defaults = {
-        server: {
-            host: "localhost",
-            port: 8000
-        },
-        name: 'example'
-    };
-
-var options = { server: { port: 8080 } };
-
-var config = Hoek.applyToDefaultsWithShallow(defaults, options, ['server']); // results in { server: { port: 8080 }, name: 'example' }
-```
-
-### deepEqual(b, a, [options])
-
-Performs a deep comparison of the two values including support for circular dependencies, prototype, and properties. To skip prototype comparisons, use `options.prototype = false`
-
-```javascript
-Hoek.deepEqual({ a: [1, 2], b: 'string', c: { d: true } }, { a: [1, 2], b: 'string', c: { d: true } }); //results in true
-Hoek.deepEqual(Object.create(null), {}, { prototype: false }); //results in true
-Hoek.deepEqual(Object.create(null), {}); //results in false
-```
-
-### unique(array, key)
-
-Remove duplicate items from Array
-
-```javascript
-
-var array = [1, 2, 2, 3, 3, 4, 5, 6];
-
-var newArray = Hoek.unique(array);    // results in [1,2,3,4,5,6]
-
-array = [{id: 1}, {id: 1}, {id: 2}];
-
-newArray = Hoek.unique(array, "id");  // results in [{id: 1}, {id: 2}]
-```
-
-### mapToObject(array, key)
-
-Convert an Array into an Object
-
-```javascript
-
-var array = [1,2,3];
-var newObject = Hoek.mapToObject(array);   // results in [{"1": true}, {"2": true}, {"3": true}]
-
-array = [{id: 1}, {id: 2}];
-newObject = Hoek.mapToObject(array, "id"); // results in [{"id": 1}, {"id": 2}]
-```
-
-### intersect(array1, array2)
-
-Find the common unique items in two arrays
-
-```javascript
-
-var array1 = [1, 2, 3];
-var array2 = [1, 4, 5];
-
-var newArray = Hoek.intersect(array1, array2); // results in [1]
-```
-
-### contain(ref, values, [options])
-
-Tests if the reference value contains the provided values where:
-- `ref` - the reference string, array, or object.
-- `values` - a single or array of values to find within the `ref` value. If `ref` is an object, `values` can be a key name,
-  an array of key names, or an object with key-value pairs to compare.
-- `options` - an optional object with the following optional settings:
-    - `deep` - if `true`, performed a deep comparison of the values.
-    - `once` - if `true`, allows only one occurrence of each value.
-    - `only` - if `true`, does not allow values not explicitly listed.
-    - `part` - if `true`, allows partial match of the values (at least one must always match).
-
-Note: comparing a string to overlapping values will result in failed comparison (e.g. `contain('abc', ['ab', 'bc'])`).
-Also, if an object key's value does not match the provided value, `false` is returned even when `part` is specified.
-
-```javascript
-Hoek.contain('aaa', 'a', { only: true });							// true
-Hoek.contain([{ a: 1 }], [{ a: 1 }], { deep: true });				// true
-Hoek.contain([1, 2, 2], [1, 2], { once: true });					// false
-Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, d: 4 }, { part: true }); // true
-```
-
-### flatten(array, [target])
-
-Flatten an array
-
-```javascript
-
-var array = [1, [2, 3]];
-
-var flattenedArray = Hoek.flatten(array); // results in [1, 2, 3]
-
-array = [1, [2, 3]];
-target = [4, [5]];
-
-flattenedArray = Hoek.flatten(array, target); // results in [4, [5], 1, 2, 3]
-```
-
-### reach(obj, chain, [options])
-
-Converts an object key chain string to reference
-
-- `options` - optional settings
-    - `separator` - string to split chain path on, defaults to '.'
-    - `default` - value to return if the path or value is not present, default is `undefined`
-    - `strict` - if `true`, will throw an error on missing member, default is `false`
-    - `functions` - if `true` allow traversing functions for properties. `false` will throw an error if a function is part of the chain.
-
-A chain including negative numbers will work like negative indices on an
-array.
-
-If chain is `null`, `undefined` or `false`, the object itself will be returned.
-
-```javascript
-
-var chain = 'a.b.c';
-var obj = {a : {b : { c : 1}}};
-
-Hoek.reach(obj, chain); // returns 1
-
-var chain = 'a.b.-1';
-var obj = {a : {b : [2,3,6]}};
-
-Hoek.reach(obj, chain); // returns 6
-```
-
-### reachTemplate(obj, template, [options])
-
-Replaces string parameters (`{name}`) with their corresponding object key values by applying the
-(`reach()`)[#reachobj-chain-options] method where:
-
-- `obj` - the context object used for key lookup.
-- `template` - a string containing `{}` parameters.
-- `options` - optional (`reach()`)[#reachobj-chain-options] options.
-
-```javascript
-
-var chain = 'a.b.c';
-var obj = {a : {b : { c : 1}}};
-
-Hoek.reachTemplate(obj, '1+{a.b.c}=2'); // returns '1+1=2'
-```
-
-### transform(obj, transform, [options])
-
-Transforms an existing object into a new one based on the supplied `obj` and `transform` map. `options` are the same as the `reach` options. The first argument can also be an array of objects. In that case the method will return an array of transformed objects.
-
-```javascript
-var source = {
-    address: {
-        one: '123 main street',
-        two: 'PO Box 1234'
-    },
-    title: 'Warehouse',
-    state: 'CA'
-};
-
-var result = Hoek.transform(source, {
-    'person.address.lineOne': 'address.one',
-    'person.address.lineTwo': 'address.two',
-    'title': 'title',
-    'person.address.region': 'state'
-});
-// Results in
-// {
-//     person: {
-//         address: {
-//             lineOne: '123 main street',
-//             lineTwo: 'PO Box 1234',
-//             region: 'CA'
-//         }
-//     },
-//     title: 'Warehouse'
-// }
-```
-
-### shallow(obj)
-
-Performs a shallow copy by copying the references of all the top level children where:
-- `obj` - the object to be copied.
-
-```javascript
-var shallow = Hoek.shallow({ a: { b: 1 } });
-```
-
-### stringify(obj)
-
-Converts an object to string using the built-in `JSON.stringify()` method with the difference that any errors are caught
-and reported back in the form of the returned string. Used as a shortcut for displaying information to the console (e.g. in
-error message) without the need to worry about invalid conversion.
-
-```javascript
-var a = {};
-a.b = a;
-Hoek.stringify(a);		// Returns '[Cannot display object: Converting circular structure to JSON]'
-```
-
-# Timer
-
-A Timer object. Initializing a new timer object sets the ts to the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.
-
-```javascript
-
-var timerObj = new Hoek.Timer();
-console.log("Time is now: " + timerObj.ts);
-console.log("Elapsed time from initialization: " + timerObj.elapsed() + 'milliseconds');
-```
-
-
-# Bench
-
-Same as Timer with the exception that `ts` stores the internal node clock which is not related to `Date.now()` and cannot be used to display
-human-readable timestamps. More accurate for benchmarking or internal timers.
-
-# Binary Encoding/Decoding
-
-### base64urlEncode(value)
-
-Encodes value in Base64 or URL encoding
-
-### base64urlDecode(value)
-
-Decodes data in Base64 or URL encoding.
-# Escaping Characters
-
-Hoek provides convenient methods for escaping html characters. The escaped characters are as followed:
-
-```javascript
-
-internals.htmlEscaped = {
-    '&': '&amp;',
-    '<': '&lt;',
-    '>': '&gt;',
-    '"': '&quot;',
-    "'": '&#x27;',
-    '`': '&#x60;'
-};
-```
-
-### escapeHtml(string)
-
-```javascript
-
-var string = '<html> hey </html>';
-var escapedString = Hoek.escapeHtml(string); // returns &lt;html&gt; hey &lt;/html&gt;
-```
-
-### escapeHeaderAttribute(attribute)
-
-Escape attribute value for use in HTTP header
-
-```javascript
-
-var a = Hoek.escapeHeaderAttribute('I said "go w\\o me"');  //returns I said \"go w\\o me\"
-```
-
-
-### escapeRegex(string)
-
-Escape string for Regex construction
-
-```javascript
-
-var a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,');  // returns 4\^f\$s\.4\*5\+\-_\?%\=#\!\:@\|~\\\/`"\(>\)\[<\]d\{\}s\,
-```
-
-# Errors
-
-### assert(condition, message)
-
-```javascript
-
-var a = 1, b = 2;
-
-Hoek.assert(a === b, 'a should equal b');  // Throws 'a should equal b'
-```
-
-Note that you may also pass an already created Error object as the second parameter, and `assert` will throw that object.
-
-```javascript
-
-var a = 1, b = 2;
-
-Hoek.assert(a === b, new Error('a should equal b')); // Throws the given error object
-```
-
-### abort(message)
-
-First checks if `process.env.NODE_ENV === 'test'`, and if so, throws error message. Otherwise,
-displays most recent stack and then exits process.
-
-
-
-### displayStack(slice)
-
-Displays the trace stack
-
-```javascript
-
-var stack = Hoek.displayStack();
-console.log(stack); // returns something like:
-
-[ 'null (/Users/user/Desktop/hoek/test.js:4:18)',
-  'Module._compile (module.js:449:26)',
-  'Module._extensions..js (module.js:467:10)',
-  'Module.load (module.js:356:32)',
-  'Module._load (module.js:312:12)',
-  'Module.runMain (module.js:492:10)',
-  'startup.processNextTick.process._tickCallback (node.js:244:9)' ]
-```
-
-### callStack(slice)
-
-Returns a trace stack array.
-
-```javascript
-
-var stack = Hoek.callStack();
-console.log(stack);  // returns something like:
-
-[ [ '/Users/user/Desktop/hoek/test.js', 4, 18, null, false ],
-  [ 'module.js', 449, 26, 'Module._compile', false ],
-  [ 'module.js', 467, 10, 'Module._extensions..js', false ],
-  [ 'module.js', 356, 32, 'Module.load', false ],
-  [ 'module.js', 312, 12, 'Module._load', false ],
-  [ 'module.js', 492, 10, 'Module.runMain', false ],
-  [ 'node.js',
-    244,
-    9,
-    'startup.processNextTick.process._tickCallback',
-    false ] ]
-```
-
-## Function
-
-### nextTick(fn)
-
-Returns a new function that wraps `fn` in `process.nextTick`.
-
-```javascript
-
-var myFn = function () {
-    console.log('Do this later');
-};
-
-var nextFn = Hoek.nextTick(myFn);
-
-nextFn();
-console.log('Do this first');
-
-// Results in:
-//
-// Do this first
-// Do this later
-```
-
-### once(fn)
-
-Returns a new function that can be run multiple times, but makes sure `fn` is only run once.
-
-```javascript
-
-var myFn = function () {
-    console.log('Ran myFn');
-};
-
-var onceFn = Hoek.once(myFn);
-onceFn(); // results in "Ran myFn"
-onceFn(); // results in undefined
-```
-
-### ignore
-
-A simple no-op function. It does nothing at all.
-
-## Miscellaneous
-
-### uniqueFilename(path, extension)
-`path` to prepend with the randomly generated file name. `extension` is the optional file extension, defaults to `''`.
-
-Returns a randomly generated file name at the specified `path`. The result is a fully resolved path to a file.
-
-```javascript
-var result = Hoek.uniqueFilename('./test/modules', 'txt'); // results in "full/path/test/modules/{random}.txt"
-```
-
-### isAbsolutePath(path, [platform])
-
-Determines whether `path` is an absolute path. Returns `true` or `false`.
-
-- `path` - A file path to test for whether it is absolute or not.
-- `platform` - An optional parameter used for specifying the platform. Defaults to `process.platform`.
-
-### isInteger(value)
-
-Check `value` to see if it is an integer.  Returns true/false.
-
-```javascript
-var result = Hoek.isInteger('23')
-```
+- [Documentation and API](https://hapi.dev/family/hoek/)
+- [Version status](https://hapi.dev/resources/status/#hoek) (builds, dependencies, node versions, licenses, eol)
+- [Changelog](https://hapi.dev/family/hoek/changelog/)
+- [Project policies](https://hapi.dev/policies/)
+- [Free and commercial support options](https://hapi.dev/support/)
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/lib/index.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/lib/index.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/lib/index.js	(working copy)
@@ -1,993 +1,45 @@
-// Load modules
+'use strict';
 
-var Crypto = require('crypto');
-var Path = require('path');
-var Util = require('util');
-var Escape = require('./escape');
+exports.applyToDefaults = require('./applyToDefaults');
 
+exports.assert = require('./assert');
 
-// Declare internals
+exports.AssertError = require('./assertError');
 
-var internals = {};
+exports.Bench = require('./bench');
 
+exports.block = require('./block');
 
-// Clone object or array
+exports.clone = require('./clone');
 
-exports.clone = function (obj, seen) {
+exports.contain = require('./contain');
 
-    if (typeof obj !== 'object' ||
-        obj === null) {
+exports.deepEqual = require('./deepEqual');
 
-        return obj;
-    }
+exports.escapeHeaderAttribute = require('./escapeHeaderAttribute');
 
-    seen = seen || { orig: [], copy: [] };
+exports.escapeHtml = require('./escapeHtml');
 
-    var lookup = seen.orig.indexOf(obj);
-    if (lookup !== -1) {
-        return seen.copy[lookup];
-    }
+exports.escapeJson = require('./escapeJson');
 
-    var newObj;
-    var cloneDeep = false;
+exports.escapeRegex = require('./escapeRegex');
 
-    if (!Array.isArray(obj)) {
-        if (Buffer.isBuffer(obj)) {
-            newObj = new Buffer(obj);
-        }
-        else if (obj instanceof Date) {
-            newObj = new Date(obj.getTime());
-        }
-        else if (obj instanceof RegExp) {
-            newObj = new RegExp(obj);
-        }
-        else {
-            var proto = Object.getPrototypeOf(obj);
-            if (proto &&
-                proto.isImmutable) {
+exports.flatten = require('./flatten');
 
-                newObj = obj;
-            }
-            else {
-                newObj = Object.create(proto);
-                cloneDeep = true;
-            }
-        }
-    }
-    else {
-        newObj = [];
-        cloneDeep = true;
-    }
+exports.ignore = require('./ignore');
 
-    seen.orig.push(obj);
-    seen.copy.push(newObj);
+exports.intersect = require('./intersect');
 
-    if (cloneDeep) {
-        var keys = Object.getOwnPropertyNames(obj);
-        for (var i = 0, il = keys.length; i < il; ++i) {
-            var key = keys[i];
-            var descriptor = Object.getOwnPropertyDescriptor(obj, key);
-            if (descriptor &&
-                (descriptor.get ||
-                 descriptor.set)) {
+exports.isPromise = require('./isPromise');
 
-                Object.defineProperty(newObj, key, descriptor);
-            }
-            else {
-                newObj[key] = exports.clone(obj[key], seen);
-            }
-        }
-    }
+exports.merge = require('./merge');
 
-    return newObj;
-};
+exports.once = require('./once');
 
+exports.reach = require('./reach');
 
-// Merge all the properties of source into target, source wins in conflict, and by default null and undefined from source are applied
-/*eslint-disable */
-exports.merge = function (target, source, isNullOverride /* = true */, isMergeArrays /* = true */) {
-/*eslint-enable */
-    exports.assert(target && typeof target === 'object', 'Invalid target value: must be an object');
-    exports.assert(source === null || source === undefined || typeof source === 'object', 'Invalid source value: must be null, undefined, or an object');
+exports.reachTemplate = require('./reachTemplate');
 
-    if (!source) {
-        return target;
-    }
+exports.stringify = require('./stringify');
 
-    if (Array.isArray(source)) {
-        exports.assert(Array.isArray(target), 'Cannot merge array onto an object');
-        if (isMergeArrays === false) {                                                  // isMergeArrays defaults to true
-            target.length = 0;                                                          // Must not change target assignment
-        }
-
-        for (var i = 0, il = source.length; i < il; ++i) {
-            target.push(exports.clone(source[i]));
-        }
-
-        return target;
-    }
-
-    var keys = Object.keys(source);
-    for (var k = 0, kl = keys.length; k < kl; ++k) {
-        var key = keys[k];
-        var value = source[key];
-        if (value &&
-            typeof value === 'object') {
-
-            if (!target[key] ||
-                typeof target[key] !== 'object' ||
-                (Array.isArray(target[key]) ^ Array.isArray(value)) ||
-                value instanceof Date ||
-                Buffer.isBuffer(value) ||
-                value instanceof RegExp) {
-
-                target[key] = exports.clone(value);
-            }
-            else {
-                exports.merge(target[key], value, isNullOverride, isMergeArrays);
-            }
-        }
-        else {
-            if (value !== null &&
-                value !== undefined) {                              // Explicit to preserve empty strings
-
-                target[key] = value;
-            }
-            else if (isNullOverride !== false) {                    // Defaults to true
-                target[key] = value;
-            }
-        }
-    }
-
-    return target;
-};
-
-
-// Apply options to a copy of the defaults
-
-exports.applyToDefaults = function (defaults, options, isNullOverride) {
-
-    exports.assert(defaults && typeof defaults === 'object', 'Invalid defaults value: must be an object');
-    exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object');
-
-    if (!options) {                                                 // If no options, return null
-        return null;
-    }
-
-    var copy = exports.clone(defaults);
-
-    if (options === true) {                                         // If options is set to true, use defaults
-        return copy;
-    }
-
-    return exports.merge(copy, options, isNullOverride === true, false);
-};
-
-
-// Clone an object except for the listed keys which are shallow copied
-
-exports.cloneWithShallow = function (source, keys) {
-
-    if (!source ||
-        typeof source !== 'object') {
-
-        return source;
-    }
-
-    var storage = internals.store(source, keys);    // Move shallow copy items to storage
-    var copy = exports.clone(source);               // Deep copy the rest
-    internals.restore(copy, source, storage);       // Shallow copy the stored items and restore
-    return copy;
-};
-
-
-internals.store = function (source, keys) {
-
-    var storage = {};
-    for (var i = 0, il = keys.length; i < il; ++i) {
-        var key = keys[i];
-        var value = exports.reach(source, key);
-        if (value !== undefined) {
-            storage[key] = value;
-            internals.reachSet(source, key, undefined);
-        }
-    }
-
-    return storage;
-};
-
-
-internals.restore = function (copy, source, storage) {
-
-    var keys = Object.keys(storage);
-    for (var i = 0, il = keys.length; i < il; ++i) {
-        var key = keys[i];
-        internals.reachSet(copy, key, storage[key]);
-        internals.reachSet(source, key, storage[key]);
-    }
-};
-
-
-internals.reachSet = function (obj, key, value) {
-
-    var path = key.split('.');
-    var ref = obj;
-    for (var i = 0, il = path.length; i < il; ++i) {
-        var segment = path[i];
-        if (i + 1 === il) {
-            ref[segment] = value;
-        }
-
-        ref = ref[segment];
-    }
-};
-
-
-// Apply options to defaults except for the listed keys which are shallow copied from option without merging
-
-exports.applyToDefaultsWithShallow = function (defaults, options, keys) {
-
-    exports.assert(defaults && typeof defaults === 'object', 'Invalid defaults value: must be an object');
-    exports.assert(!options || options === true || typeof options === 'object', 'Invalid options value: must be true, falsy or an object');
-    exports.assert(keys && Array.isArray(keys), 'Invalid keys');
-
-    if (!options) {                                                 // If no options, return null
-        return null;
-    }
-
-    var copy = exports.cloneWithShallow(defaults, keys);
-
-    if (options === true) {                                         // If options is set to true, use defaults
-        return copy;
-    }
-
-    var storage = internals.store(options, keys);   // Move shallow copy items to storage
-    exports.merge(copy, options, false, false);     // Deep copy the rest
-    internals.restore(copy, options, storage);      // Shallow copy the stored items and restore
-    return copy;
-};
-
-
-// Deep object or array comparison
-
-exports.deepEqual = function (obj, ref, options, seen) {
-
-    options = options || { prototype: true };
-
-    var type = typeof obj;
-
-    if (type !== typeof ref) {
-        return false;
-    }
-
-    if (type !== 'object' ||
-        obj === null ||
-        ref === null) {
-
-        if (obj === ref) {                                                      // Copied from Deep-eql, copyright(c) 2013 Jake Luer, jake@alogicalparadox.com, MIT Licensed, https://github.com/chaijs/deep-eql
-            return obj !== 0 || 1 / obj === 1 / ref;        // -0 / +0
-        }
-
-        return obj !== obj && ref !== ref;                  // NaN
-    }
-
-    seen = seen || [];
-    if (seen.indexOf(obj) !== -1) {
-        return true;                            // If previous comparison failed, it would have stopped execution
-    }
-
-    seen.push(obj);
-
-    if (Array.isArray(obj)) {
-        if (!Array.isArray(ref)) {
-            return false;
-        }
-
-        if (!options.part && obj.length !== ref.length) {
-            return false;
-        }
-
-        for (var i = 0, il = obj.length; i < il; ++i) {
-            if (options.part) {
-                var found = false;
-                for (var r = 0, rl = ref.length; r < rl; ++r) {
-                    if (exports.deepEqual(obj[i], ref[r], options, seen)) {
-                        found = true;
-                        break;
-                    }
-                }
-
-                return found;
-            }
-
-            if (!exports.deepEqual(obj[i], ref[i], options, seen)) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    if (Buffer.isBuffer(obj)) {
-        if (!Buffer.isBuffer(ref)) {
-            return false;
-        }
-
-        if (obj.length !== ref.length) {
-            return false;
-        }
-
-        for (var j = 0, jl = obj.length; j < jl; ++j) {
-            if (obj[j] !== ref[j]) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    if (obj instanceof Date) {
-        return (ref instanceof Date && obj.getTime() === ref.getTime());
-    }
-
-    if (obj instanceof RegExp) {
-        return (ref instanceof RegExp && obj.toString() === ref.toString());
-    }
-
-    if (options.prototype) {
-        if (Object.getPrototypeOf(obj) !== Object.getPrototypeOf(ref)) {
-            return false;
-        }
-    }
-
-    var keys = Object.getOwnPropertyNames(obj);
-
-    if (!options.part && keys.length !== Object.getOwnPropertyNames(ref).length) {
-        return false;
-    }
-
-    for (var k = 0, kl = keys.length; k < kl; ++k) {
-        var key = keys[k];
-        var descriptor = Object.getOwnPropertyDescriptor(obj, key);
-        if (descriptor.get) {
-            if (!exports.deepEqual(descriptor, Object.getOwnPropertyDescriptor(ref, key), options, seen)) {
-                return false;
-            }
-        }
-        else if (!exports.deepEqual(obj[key], ref[key], options, seen)) {
-            return false;
-        }
-    }
-
-    return true;
-};
-
-
-// Remove duplicate items from array
-
-exports.unique = function (array, key) {
-
-    var index = {};
-    var result = [];
-
-    for (var i = 0, il = array.length; i < il; ++i) {
-        var id = (key ? array[i][key] : array[i]);
-        if (index[id] !== true) {
-
-            result.push(array[i]);
-            index[id] = true;
-        }
-    }
-
-    return result;
-};
-
-
-// Convert array into object
-
-exports.mapToObject = function (array, key) {
-
-    if (!array) {
-        return null;
-    }
-
-    var obj = {};
-    for (var i = 0, il = array.length; i < il; ++i) {
-        if (key) {
-            if (array[i][key]) {
-                obj[array[i][key]] = true;
-            }
-        }
-        else {
-            obj[array[i]] = true;
-        }
-    }
-
-    return obj;
-};
-
-
-// Find the common unique items in two arrays
-
-exports.intersect = function (array1, array2, justFirst) {
-
-    if (!array1 || !array2) {
-        return [];
-    }
-
-    var common = [];
-    var hash = (Array.isArray(array1) ? exports.mapToObject(array1) : array1);
-    var found = {};
-    for (var i = 0, il = array2.length; i < il; ++i) {
-        if (hash[array2[i]] && !found[array2[i]]) {
-            if (justFirst) {
-                return array2[i];
-            }
-
-            common.push(array2[i]);
-            found[array2[i]] = true;
-        }
-    }
-
-    return (justFirst ? null : common);
-};
-
-
-// Test if the reference contains the values
-
-exports.contain = function (ref, values, options) {
-
-    /*
-        string -> string(s)
-        array -> item(s)
-        object -> key(s)
-        object -> object (key:value)
-    */
-
-    var valuePairs = null;
-    if (typeof ref === 'object' &&
-        typeof values === 'object' &&
-        !Array.isArray(ref) &&
-        !Array.isArray(values)) {
-
-        valuePairs = values;
-        values = Object.keys(values);
-    }
-    else {
-        values = [].concat(values);
-    }
-
-    options = options || {};            // deep, once, only, part
-
-    exports.assert(arguments.length >= 2, 'Insufficient arguments');
-    exports.assert(typeof ref === 'string' || typeof ref === 'object', 'Reference must be string or an object');
-    exports.assert(values.length, 'Values array cannot be empty');
-
-    var compare, compareFlags;
-    if (options.deep) {
-        compare = exports.deepEqual;
-
-        var hasOnly = options.hasOwnProperty('only'), hasPart = options.hasOwnProperty('part');
-
-        compareFlags = {
-            prototype: hasOnly ? options.only : hasPart ? !options.part : false,
-            part: hasOnly ? !options.only : hasPart ? options.part : true
-        };
-    }
-    else {
-        compare = function (a, b) {
-
-            return a === b;
-        };
-    }
-
-    var misses = false;
-    var matches = new Array(values.length);
-    for (var i = 0, il = matches.length; i < il; ++i) {
-        matches[i] = 0;
-    }
-
-    if (typeof ref === 'string') {
-        var pattern = '(';
-        for (i = 0, il = values.length; i < il; ++i) {
-            var value = values[i];
-            exports.assert(typeof value === 'string', 'Cannot compare string reference to non-string value');
-            pattern += (i ? '|' : '') + exports.escapeRegex(value);
-        }
-
-        var regex = new RegExp(pattern + ')', 'g');
-        var leftovers = ref.replace(regex, function ($0, $1) {
-
-            var index = values.indexOf($1);
-            ++matches[index];
-            return '';          // Remove from string
-        });
-
-        misses = !!leftovers;
-    }
-    else if (Array.isArray(ref)) {
-        for (i = 0, il = ref.length; i < il; ++i) {
-            for (var j = 0, jl = values.length, matched = false; j < jl && matched === false; ++j) {
-                matched = compare(values[j], ref[i], compareFlags) && j;
-            }
-
-            if (matched !== false) {
-                ++matches[matched];
-            }
-            else {
-                misses = true;
-            }
-        }
-    }
-    else {
-        var keys = Object.keys(ref);
-        for (i = 0, il = keys.length; i < il; ++i) {
-            var key = keys[i];
-            var pos = values.indexOf(key);
-            if (pos !== -1) {
-                if (valuePairs &&
-                    !compare(valuePairs[key], ref[key], compareFlags)) {
-
-                    return false;
-                }
-
-                ++matches[pos];
-            }
-            else {
-                misses = true;
-            }
-        }
-    }
-
-    var result = false;
-    for (i = 0, il = matches.length; i < il; ++i) {
-        result = result || !!matches[i];
-        if ((options.once && matches[i] > 1) ||
-            (!options.part && !matches[i])) {
-
-            return false;
-        }
-    }
-
-    if (options.only &&
-        misses) {
-
-        return false;
-    }
-
-    return result;
-};
-
-
-// Flatten array
-
-exports.flatten = function (array, target) {
-
-    var result = target || [];
-
-    for (var i = 0, il = array.length; i < il; ++i) {
-        if (Array.isArray(array[i])) {
-            exports.flatten(array[i], result);
-        }
-        else {
-            result.push(array[i]);
-        }
-    }
-
-    return result;
-};
-
-
-// Convert an object key chain string ('a.b.c') to reference (object[a][b][c])
-
-exports.reach = function (obj, chain, options) {
-
-    if (chain === false ||
-        chain === null ||
-        typeof chain === 'undefined') {
-
-        return obj;
-    }
-
-    options = options || {};
-    if (typeof options === 'string') {
-        options = { separator: options };
-    }
-
-    var path = chain.split(options.separator || '.');
-    var ref = obj;
-    for (var i = 0, il = path.length; i < il; ++i) {
-        var key = path[i];
-        if (key[0] === '-' && Array.isArray(ref)) {
-            key = key.slice(1, key.length);
-            key = ref.length - key;
-        }
-
-        if (!ref ||
-            !ref.hasOwnProperty(key) ||
-            (typeof ref !== 'object' && options.functions === false)) {         // Only object and function can have properties
-
-            exports.assert(!options.strict || i + 1 === il, 'Missing segment', key, 'in reach path ', chain);
-            exports.assert(typeof ref === 'object' || options.functions === true || typeof ref !== 'function', 'Invalid segment', key, 'in reach path ', chain);
-            ref = options.default;
-            break;
-        }
-
-        ref = ref[key];
-    }
-
-    return ref;
-};
-
-
-exports.reachTemplate = function (obj, template, options) {
-
-    return template.replace(/{([^}]+)}/g, function ($0, chain) {
-
-        var value = exports.reach(obj, chain, options);
-        return (value === undefined || value === null ? '' : value);
-    });
-};
-
-
-exports.formatStack = function (stack) {
-
-    var trace = [];
-    for (var i = 0, il = stack.length; i < il; ++i) {
-        var item = stack[i];
-        trace.push([item.getFileName(), item.getLineNumber(), item.getColumnNumber(), item.getFunctionName(), item.isConstructor()]);
-    }
-
-    return trace;
-};
-
-
-exports.formatTrace = function (trace) {
-
-    var display = [];
-
-    for (var i = 0, il = trace.length; i < il; ++i) {
-        var row = trace[i];
-        display.push((row[4] ? 'new ' : '') + row[3] + ' (' + row[0] + ':' + row[1] + ':' + row[2] + ')');
-    }
-
-    return display;
-};
-
-
-exports.callStack = function (slice) {
-
-    // http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
-
-    var v8 = Error.prepareStackTrace;
-    Error.prepareStackTrace = function (err, stack) {
-
-        return stack;
-    };
-
-    var capture = {};
-    Error.captureStackTrace(capture, arguments.callee);     /*eslint no-caller:0 */
-    var stack = capture.stack;
-
-    Error.prepareStackTrace = v8;
-
-    var trace = exports.formatStack(stack);
-
-    if (slice) {
-        return trace.slice(slice);
-    }
-
-    return trace;
-};
-
-
-exports.displayStack = function (slice) {
-
-    var trace = exports.callStack(slice === undefined ? 1 : slice + 1);
-
-    return exports.formatTrace(trace);
-};
-
-
-exports.abortThrow = false;
-
-
-exports.abort = function (message, hideStack) {
-
-    if (process.env.NODE_ENV === 'test' || exports.abortThrow === true) {
-        throw new Error(message || 'Unknown error');
-    }
-
-    var stack = '';
-    if (!hideStack) {
-        stack = exports.displayStack(1).join('\n\t');
-    }
-    console.log('ABORT: ' + message + '\n\t' + stack);
-    process.exit(1);
-};
-
-
-exports.assert = function (condition /*, msg1, msg2, msg3 */) {
-
-    if (condition) {
-        return;
-    }
-
-    if (arguments.length === 2 && arguments[1] instanceof Error) {
-        throw arguments[1];
-    }
-
-    var msgs = [];
-    for (var i = 1, il = arguments.length; i < il; ++i) {
-        if (arguments[i] !== '') {
-            msgs.push(arguments[i]);            // Avoids Array.slice arguments leak, allowing for V8 optimizations
-        }
-    }
-
-    msgs = msgs.map(function (msg) {
-
-        return typeof msg === 'string' ? msg : msg instanceof Error ? msg.message : exports.stringify(msg);
-    });
-    throw new Error(msgs.join(' ') || 'Unknown error');
-};
-
-
-exports.Timer = function () {
-
-    this.ts = 0;
-    this.reset();
-};
-
-
-exports.Timer.prototype.reset = function () {
-
-    this.ts = Date.now();
-};
-
-
-exports.Timer.prototype.elapsed = function () {
-
-    return Date.now() - this.ts;
-};
-
-
-exports.Bench = function () {
-
-    this.ts = 0;
-    this.reset();
-};
-
-
-exports.Bench.prototype.reset = function () {
-
-    this.ts = exports.Bench.now();
-};
-
-
-exports.Bench.prototype.elapsed = function () {
-
-    return exports.Bench.now() - this.ts;
-};
-
-
-exports.Bench.now = function () {
-
-    var ts = process.hrtime();
-    return (ts[0] * 1e3) + (ts[1] / 1e6);
-};
-
-
-// Escape string for Regex construction
-
-exports.escapeRegex = function (string) {
-
-    // Escape ^$.*+-?=!:|\/()[]{},
-    return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&');
-};
-
-
-// Base64url (RFC 4648) encode
-
-exports.base64urlEncode = function (value, encoding) {
-
-    var buf = (Buffer.isBuffer(value) ? value : new Buffer(value, encoding || 'binary'));
-    return buf.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
-};
-
-
-// Base64url (RFC 4648) decode
-
-exports.base64urlDecode = function (value, encoding) {
-
-    if (value &&
-        !/^[\w\-]*$/.test(value)) {
-
-        return new Error('Invalid character');
-    }
-
-    try {
-        var buf = new Buffer(value, 'base64');
-        return (encoding === 'buffer' ? buf : buf.toString(encoding || 'binary'));
-    }
-    catch (err) {
-        return err;
-    }
-};
-
-
-// Escape attribute value for use in HTTP header
-
-exports.escapeHeaderAttribute = function (attribute) {
-
-    // Allowed value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9, \, "
-
-    exports.assert(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~\"\\]*$/.test(attribute), 'Bad attribute value (' + attribute + ')');
-
-    return attribute.replace(/\\/g, '\\\\').replace(/\"/g, '\\"');                             // Escape quotes and slash
-};
-
-
-exports.escapeHtml = function (string) {
-
-    return Escape.escapeHtml(string);
-};
-
-
-exports.escapeJavaScript = function (string) {
-
-    return Escape.escapeJavaScript(string);
-};
-
-
-exports.nextTick = function (callback) {
-
-    return function () {
-
-        var args = arguments;
-        process.nextTick(function () {
-
-            callback.apply(null, args);
-        });
-    };
-};
-
-
-exports.once = function (method) {
-
-    if (method._hoekOnce) {
-        return method;
-    }
-
-    var once = false;
-    var wrapped = function () {
-
-        if (!once) {
-            once = true;
-            method.apply(null, arguments);
-        }
-    };
-
-    wrapped._hoekOnce = true;
-
-    return wrapped;
-};
-
-
-exports.isAbsolutePath = function (path, platform) {
-
-    if (!path) {
-        return false;
-    }
-
-    if (Path.isAbsolute) {                      // node >= 0.11
-        return Path.isAbsolute(path);
-    }
-
-    platform = platform || process.platform;
-
-    // Unix
-
-    if (platform !== 'win32') {
-        return path[0] === '/';
-    }
-
-    // Windows
-
-    return !!/^(?:[a-zA-Z]:[\\\/])|(?:[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/])/.test(path);        // C:\ or \\something\something
-};
-
-
-exports.isInteger = function (value) {
-
-    return (typeof value === 'number' &&
-            parseFloat(value) === parseInt(value, 10) &&
-            !isNaN(value));
-};
-
-
-exports.ignore = function () { };
-
-
-exports.inherits = Util.inherits;
-
-
-exports.format = Util.format;
-
-
-exports.transform = function (source, transform, options) {
-
-    exports.assert(source === null || source === undefined || typeof source === 'object' || Array.isArray(source), 'Invalid source object: must be null, undefined, an object, or an array');
-
-    if (Array.isArray(source)) {
-        var results = [];
-        for (var i = 0, il = source.length; i < il; ++i) {
-            results.push(exports.transform(source[i], transform, options));
-        }
-        return results;
-    }
-
-    var result = {};
-    var keys = Object.keys(transform);
-
-    for (var k = 0, kl = keys.length; k < kl; ++k) {
-        var key = keys[k];
-        var path = key.split('.');
-        var sourcePath = transform[key];
-
-        exports.assert(typeof sourcePath === 'string', 'All mappings must be "." delineated strings');
-
-        var segment;
-        var res = result;
-
-        while (path.length > 1) {
-            segment = path.shift();
-            if (!res[segment]) {
-                res[segment] = {};
-            }
-            res = res[segment];
-        }
-        segment = path.shift();
-        res[segment] = exports.reach(source, sourcePath, options);
-    }
-
-    return result;
-};
-
-
-exports.uniqueFilename = function (path, extension) {
-
-    if (extension) {
-        extension = extension[0] !== '.' ? '.' + extension : extension;
-    }
-    else {
-        extension = '';
-    }
-
-    path = Path.resolve(path);
-    var name = [Date.now(), process.pid, Crypto.randomBytes(8).toString('hex')].join('-') + extension;
-    return Path.join(path, name);
-};
-
-
-exports.stringify = function () {
-
-    try {
-        return JSON.stringify.apply(null, arguments);
-    }
-    catch (err) {
-        return '[Cannot display object: ' + err.message + ']';
-    }
-};
-
-
-exports.shallow = function (source) {
-
-    var target = {};
-    var keys = Object.keys(source);
-    for (var i = 0, il = keys.length; i < il; ++i) {
-        var key = keys[i];
-        target[key] = source[key];
-    }
-
-    return target;
-};
+exports.wait = require('./wait');
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/package.json
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/package.json	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/package.json	(working copy)
@@ -1,37 +1,59 @@
 {
-  "name": "hoek",
+  "name": "@hapi/hoek",
   "description": "General purpose node utilities",
-  "version": "2.16.3",
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/hapijs/hoek"
-  },
+  "version": "11.0.2",
+  "repository": "git://github.com/hapijs/hoek",
   "main": "lib/index.js",
+  "types": "lib/index.d.ts",
+  "exports": {
+    ".": {
+      "import": "./lib/index.mjs",
+      "require": "./lib/index.js"
+    },
+    "./applyToDefaults": "./lib/applyToDefaults.js",
+    "./assert": "./lib/assert.js",
+    "./assertError": "./lib/assertError.js",
+    "./bench": "./lib/bench.js",
+    "./block": "./lib/block.js",
+    "./clone": "./lib/clone.js",
+    "./contain": "./lib/contain.js",
+    "./deepEqual": "./lib/deepEqual.js",
+    "./escapeHeaderAttribute": "./lib/escapeHeaderAttribute.js",
+    "./escapeHtml": "./lib/escapeHtml.js",
+    "./escapeJson": "./lib/escapeJson.js",
+    "./escapeRegex": "./lib/escapeRegex.js",
+    "./flatten": "./lib/flatten.js",
+    "./ignore": "./lib/ignore.js",
+    "./intersect": "./lib/intersect.js",
+    "./isPromise": "./lib/isPromise.js",
+    "./merge": "./lib/merge.js",
+    "./once": "./lib/once.js",
+    "./reach": "./lib/reach.js",
+    "./reachTemplate": "./lib/reachTemplate.js",
+    "./stringify": "./lib/stringify.js",
+    "./wait": "./lib/wait.js"
+  },
   "keywords": [
     "utilities"
   ],
-  "engines": {
-    "node": ">=0.10.40"
+  "files": [
+    "lib"
+  ],
+  "eslintConfig": {
+    "extends": [
+      "plugin:@hapi/module"
+    ]
   },
-  "dependencies": {},
   "devDependencies": {
-    "code": "1.x.x",
-    "lab": "5.x.x"
+    "@hapi/code": "^9.0.0",
+    "@hapi/eslint-plugin": "*",
+    "@hapi/lab": "^25.0.1",
+    "@types/node": "^17.0.30",
+    "typescript": "~4.6.4"
   },
   "scripts": {
-    "test": "lab -a code -t 100 -L",
-    "test-cov-html": "lab -a code -t 100 -L -r html -o coverage.html"
-  },
-  "license": "BSD-3-Clause",
-  "readme": "![hoek Logo](https://raw.github.com/hapijs/hoek/master/images/hoek.png)\n\nUtility methods for the hapi ecosystem. This module is not intended to solve every problem for everyone, but rather as a central place to store hapi-specific methods. If you're looking for a general purpose utility module, check out [lodash](https://github.com/lodash/lodash) or [underscore](https://github.com/jashkenas/underscore).\n\n[![Build Status](https://secure.travis-ci.org/hapijs/hoek.svg)](http://travis-ci.org/hapijs/hoek)\n\nLead Maintainer: [Nathan LaFreniere](https://github.com/nlf)\n\n# Table of Contents\n\n* [Introduction](#introduction \"Introduction\")\n* [Object](#object \"Object\")\n  * [clone](#cloneobj \"clone\")\n  * [cloneWithShallow](#clonewithshallowobj-keys \"cloneWithShallow\")\n  * [merge](#mergetarget-source-isnulloverride-ismergearrays \"merge\")\n  * [applyToDefaults](#applytodefaultsdefaults-options-isnulloverride \"applyToDefaults\")\n  * [applyToDefaultsWithShallow](#applytodefaultswithshallowdefaults-options-keys \"applyToDefaultsWithShallow\")\n  * [deepEqual](#deepequala-b \"deepEqual\")\n  * [unique](#uniquearray-key \"unique\")\n  * [mapToObject](#maptoobjectarray-key \"mapToObject\")\n  * [intersect](#intersectarray1-array2 \"intersect\")\n  * [contain](#containref-values-options \"contain\")\n  * [flatten](#flattenarray-target \"flatten\")\n  * [reach](#reachobj-chain-options \"reach\")\n  * [reachTemplate](#reachtemplateobj-template-options \"reachTemplate\")\n  * [transform](#transformobj-transform-options \"transform\")\n  * [shallow](#shallowobj \"shallow\")\n  * [stringify](#stringifyobj \"stringify\")\n* [Timer](#timer \"Timer\")\n* [Bench](#bench \"Bench\")\n* [Binary Encoding/Decoding](#binary-encodingdecoding \"Binary Encoding/Decoding\")\n  * [base64urlEncode](#base64urlencodevalue \"binary64urlEncode\")\n  * [base64urlDecode](#base64urldecodevalue \"binary64urlDecode\")\n* [Escaping Characters](#escaping-characters \"Escaping Characters\")\n  * [escapeHtml](#escapehtmlstring \"escapeHtml\")\n  * [escapeHeaderAttribute](#escapeheaderattributeattribute \"escapeHeaderAttribute\")\n  * [escapeRegex](#escaperegexstring \"escapeRegex\")\n* [Errors](#errors \"Errors\")\n  * [assert](#assertcondition-message \"assert\")\n  * [abort](#abortmessage \"abort\")\n  * [displayStack](#displaystackslice \"displayStack\")\n  * [callStack](#callstackslice \"callStack\")\n* [Function](#function \"Function\")\n  * [nextTick](#nexttickfn \"nextTick\")\n  * [once](#oncefn \"once\")\n  * [ignore](#ignore \"ignore\")\n* [Miscellaneous](#miscellaneous \"Miscellaneous\")\n  * [uniqueFilename](#uniquefilenamepath-extension \"uniqueFilename\")\n  * [isAbsolutePath](#isabsolutepathpath-platform \"isAbsolutePath\")\n  * [isInteger](#isintegervalue \"isInteger\")\n\n\n\n# Introduction\n\nThe *Hoek* library contains some common functions used within the hapi ecosystem. It comes with useful methods for Arrays (clone, merge, applyToDefaults), Objects (removeKeys, copy), Asserting and more.\n\nFor example, to use Hoek to set configuration with default options:\n```javascript\nvar Hoek = require('hoek');\n\nvar default = {url : \"www.github.com\", port : \"8000\", debug : true};\n\nvar config = Hoek.applyToDefaults(default, {port : \"3000\", admin : true});\n\n// In this case, config would be { url: 'www.github.com', port: '3000', debug: true, admin: true }\n```\n\nUnder each of the sections (such as Array), there are subsections which correspond to Hoek methods. Each subsection will explain how to use the corresponding method. In each js excerpt below, the `var Hoek = require('hoek');` is omitted for brevity.\n\n## Object\n\nHoek provides several helpful methods for objects and arrays.\n\n### clone(obj)\n\nThis method is used to clone an object or an array. A *deep copy* is made (duplicates everything, including values that are objects, as well as non-enumerable properties).\n\n```javascript\n\nvar nestedObj = {\n        w: /^something$/ig,\n        x: {\n            a: [1, 2, 3],\n            b: 123456,\n            c: new Date()\n        },\n        y: 'y',\n        z: new Date()\n    };\n\nvar copy = Hoek.clone(nestedObj);\n\ncopy.x.b = 100;\n\nconsole.log(copy.y);        // results in 'y'\nconsole.log(nestedObj.x.b); // results in 123456\nconsole.log(copy.x.b);      // results in 100\n```\n\n### cloneWithShallow(obj, keys)\nkeys is an array of key names to shallow copy\n\nThis method is also used to clone an object or array, however any keys listed in the `keys` array are shallow copied while those not listed are deep copied.\n\n```javascript\n\nvar nestedObj = {\n        w: /^something$/ig,\n        x: {\n            a: [1, 2, 3],\n            b: 123456,\n            c: new Date()\n        },\n        y: 'y',\n        z: new Date()\n    };\n\nvar copy = Hoek.cloneWithShallow(nestedObj, ['x']);\n\ncopy.x.b = 100;\n\nconsole.log(copy.y);        // results in 'y'\nconsole.log(nestedObj.x.b); // results in 100\nconsole.log(copy.x.b);      // results in 100\n```\n\n### merge(target, source, isNullOverride, isMergeArrays)\nisNullOverride, isMergeArrays default to true\n\nMerge all the properties of source into target, source wins in conflict, and by default null and undefined from source are applied.\nMerge is destructive where the target is modified. For non destructive merge, use `applyToDefaults`.\n\n\n```javascript\n\nvar target = {a: 1, b : 2};\nvar source = {a: 0, c: 5};\nvar source2 = {a: null, c: 5};\n\nHoek.merge(target, source);         // results in {a: 0, b: 2, c: 5}\nHoek.merge(target, source2);        // results in {a: null, b: 2, c: 5}\nHoek.merge(target, source2, false); // results in {a: 1, b: 2, c: 5}\n\nvar targetArray = [1, 2, 3];\nvar sourceArray = [4, 5];\n\nHoek.merge(targetArray, sourceArray);              // results in [1, 2, 3, 4, 5]\nHoek.merge(targetArray, sourceArray, true, false); // results in [4, 5]\n```\n\n### applyToDefaults(defaults, options, isNullOverride)\nisNullOverride defaults to false\n\nApply options to a copy of the defaults\n\n```javascript\n\nvar defaults = { host: \"localhost\", port: 8000 };\nvar options = { port: 8080 };\n\nvar config = Hoek.applyToDefaults(defaults, options); // results in { host: \"localhost\", port: 8080 }\n```\n\nApply options with a null value to a copy of the defaults\n\n```javascript\n\nvar defaults = { host: \"localhost\", port: 8000 };\nvar options = { host: null, port: 8080 };\n\nvar config = Hoek.applyToDefaults(defaults, options, true); // results in { host: null, port: 8080 }\n```\n\n### applyToDefaultsWithShallow(defaults, options, keys)\nkeys is an array of key names to shallow copy\n\nApply options to a copy of the defaults. Keys specified in the last parameter are shallow copied from options instead of merged.\n\n```javascript\n\nvar defaults = {\n        server: {\n            host: \"localhost\",\n            port: 8000\n        },\n        name: 'example'\n    };\n\nvar options = { server: { port: 8080 } };\n\nvar config = Hoek.applyToDefaultsWithShallow(defaults, options, ['server']); // results in { server: { port: 8080 }, name: 'example' }\n```\n\n### deepEqual(b, a, [options])\n\nPerforms a deep comparison of the two values including support for circular dependencies, prototype, and properties. To skip prototype comparisons, use `options.prototype = false`\n\n```javascript\nHoek.deepEqual({ a: [1, 2], b: 'string', c: { d: true } }, { a: [1, 2], b: 'string', c: { d: true } }); //results in true\nHoek.deepEqual(Object.create(null), {}, { prototype: false }); //results in true\nHoek.deepEqual(Object.create(null), {}); //results in false\n```\n\n### unique(array, key)\n\nRemove duplicate items from Array\n\n```javascript\n\nvar array = [1, 2, 2, 3, 3, 4, 5, 6];\n\nvar newArray = Hoek.unique(array);    // results in [1,2,3,4,5,6]\n\narray = [{id: 1}, {id: 1}, {id: 2}];\n\nnewArray = Hoek.unique(array, \"id\");  // results in [{id: 1}, {id: 2}]\n```\n\n### mapToObject(array, key)\n\nConvert an Array into an Object\n\n```javascript\n\nvar array = [1,2,3];\nvar newObject = Hoek.mapToObject(array);   // results in [{\"1\": true}, {\"2\": true}, {\"3\": true}]\n\narray = [{id: 1}, {id: 2}];\nnewObject = Hoek.mapToObject(array, \"id\"); // results in [{\"id\": 1}, {\"id\": 2}]\n```\n\n### intersect(array1, array2)\n\nFind the common unique items in two arrays\n\n```javascript\n\nvar array1 = [1, 2, 3];\nvar array2 = [1, 4, 5];\n\nvar newArray = Hoek.intersect(array1, array2); // results in [1]\n```\n\n### contain(ref, values, [options])\n\nTests if the reference value contains the provided values where:\n- `ref` - the reference string, array, or object.\n- `values` - a single or array of values to find within the `ref` value. If `ref` is an object, `values` can be a key name,\n  an array of key names, or an object with key-value pairs to compare.\n- `options` - an optional object with the following optional settings:\n    - `deep` - if `true`, performed a deep comparison of the values.\n    - `once` - if `true`, allows only one occurrence of each value.\n    - `only` - if `true`, does not allow values not explicitly listed.\n    - `part` - if `true`, allows partial match of the values (at least one must always match).\n\nNote: comparing a string to overlapping values will result in failed comparison (e.g. `contain('abc', ['ab', 'bc'])`).\nAlso, if an object key's value does not match the provided value, `false` is returned even when `part` is specified.\n\n```javascript\nHoek.contain('aaa', 'a', { only: true });\t\t\t\t\t\t\t// true\nHoek.contain([{ a: 1 }], [{ a: 1 }], { deep: true });\t\t\t\t// true\nHoek.contain([1, 2, 2], [1, 2], { once: true });\t\t\t\t\t// false\nHoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, d: 4 }, { part: true }); // true\n```\n\n### flatten(array, [target])\n\nFlatten an array\n\n```javascript\n\nvar array = [1, [2, 3]];\n\nvar flattenedArray = Hoek.flatten(array); // results in [1, 2, 3]\n\narray = [1, [2, 3]];\ntarget = [4, [5]];\n\nflattenedArray = Hoek.flatten(array, target); // results in [4, [5], 1, 2, 3]\n```\n\n### reach(obj, chain, [options])\n\nConverts an object key chain string to reference\n\n- `options` - optional settings\n    - `separator` - string to split chain path on, defaults to '.'\n    - `default` - value to return if the path or value is not present, default is `undefined`\n    - `strict` - if `true`, will throw an error on missing member, default is `false`\n    - `functions` - if `true` allow traversing functions for properties. `false` will throw an error if a function is part of the chain.\n\nA chain including negative numbers will work like negative indices on an\narray.\n\nIf chain is `null`, `undefined` or `false`, the object itself will be returned.\n\n```javascript\n\nvar chain = 'a.b.c';\nvar obj = {a : {b : { c : 1}}};\n\nHoek.reach(obj, chain); // returns 1\n\nvar chain = 'a.b.-1';\nvar obj = {a : {b : [2,3,6]}};\n\nHoek.reach(obj, chain); // returns 6\n```\n\n### reachTemplate(obj, template, [options])\n\nReplaces string parameters (`{name}`) with their corresponding object key values by applying the\n(`reach()`)[#reachobj-chain-options] method where:\n\n- `obj` - the context object used for key lookup.\n- `template` - a string containing `{}` parameters.\n- `options` - optional (`reach()`)[#reachobj-chain-options] options.\n\n```javascript\n\nvar chain = 'a.b.c';\nvar obj = {a : {b : { c : 1}}};\n\nHoek.reachTemplate(obj, '1+{a.b.c}=2'); // returns '1+1=2'\n```\n\n### transform(obj, transform, [options])\n\nTransforms an existing object into a new one based on the supplied `obj` and `transform` map. `options` are the same as the `reach` options. The first argument can also be an array of objects. In that case the method will return an array of transformed objects.\n\n```javascript\nvar source = {\n    address: {\n        one: '123 main street',\n        two: 'PO Box 1234'\n    },\n    title: 'Warehouse',\n    state: 'CA'\n};\n\nvar result = Hoek.transform(source, {\n    'person.address.lineOne': 'address.one',\n    'person.address.lineTwo': 'address.two',\n    'title': 'title',\n    'person.address.region': 'state'\n});\n// Results in\n// {\n//     person: {\n//         address: {\n//             lineOne: '123 main street',\n//             lineTwo: 'PO Box 1234',\n//             region: 'CA'\n//         }\n//     },\n//     title: 'Warehouse'\n// }\n```\n\n### shallow(obj)\n\nPerforms a shallow copy by copying the references of all the top level children where:\n- `obj` - the object to be copied.\n\n```javascript\nvar shallow = Hoek.shallow({ a: { b: 1 } });\n```\n\n### stringify(obj)\n\nConverts an object to string using the built-in `JSON.stringify()` method with the difference that any errors are caught\nand reported back in the form of the returned string. Used as a shortcut for displaying information to the console (e.g. in\nerror message) without the need to worry about invalid conversion.\n\n```javascript\nvar a = {};\na.b = a;\nHoek.stringify(a);\t\t// Returns '[Cannot display object: Converting circular structure to JSON]'\n```\n\n# Timer\n\nA Timer object. Initializing a new timer object sets the ts to the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.\n\n```javascript\n\nvar timerObj = new Hoek.Timer();\nconsole.log(\"Time is now: \" + timerObj.ts);\nconsole.log(\"Elapsed time from initialization: \" + timerObj.elapsed() + 'milliseconds');\n```\n\n\n# Bench\n\nSame as Timer with the exception that `ts` stores the internal node clock which is not related to `Date.now()` and cannot be used to display\nhuman-readable timestamps. More accurate for benchmarking or internal timers.\n\n# Binary Encoding/Decoding\n\n### base64urlEncode(value)\n\nEncodes value in Base64 or URL encoding\n\n### base64urlDecode(value)\n\nDecodes data in Base64 or URL encoding.\n# Escaping Characters\n\nHoek provides convenient methods for escaping html characters. The escaped characters are as followed:\n\n```javascript\n\ninternals.htmlEscaped = {\n    '&': '&amp;',\n    '<': '&lt;',\n    '>': '&gt;',\n    '\"': '&quot;',\n    \"'\": '&#x27;',\n    '`': '&#x60;'\n};\n```\n\n### escapeHtml(string)\n\n```javascript\n\nvar string = '<html> hey </html>';\nvar escapedString = Hoek.escapeHtml(string); // returns &lt;html&gt; hey &lt;/html&gt;\n```\n\n### escapeHeaderAttribute(attribute)\n\nEscape attribute value for use in HTTP header\n\n```javascript\n\nvar a = Hoek.escapeHeaderAttribute('I said \"go w\\\\o me\"');  //returns I said \\\"go w\\\\o me\\\"\n```\n\n\n### escapeRegex(string)\n\nEscape string for Regex construction\n\n```javascript\n\nvar a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\\\/`\"(>)[<]d{}s,');  // returns 4\\^f\\$s\\.4\\*5\\+\\-_\\?%\\=#\\!\\:@\\|~\\\\\\/`\"\\(>\\)\\[<\\]d\\{\\}s\\,\n```\n\n# Errors\n\n### assert(condition, message)\n\n```javascript\n\nvar a = 1, b = 2;\n\nHoek.assert(a === b, 'a should equal b');  // Throws 'a should equal b'\n```\n\nNote that you may also pass an already created Error object as the second parameter, and `assert` will throw that object.\n\n```javascript\n\nvar a = 1, b = 2;\n\nHoek.assert(a === b, new Error('a should equal b')); // Throws the given error object\n```\n\n### abort(message)\n\nFirst checks if `process.env.NODE_ENV === 'test'`, and if so, throws error message. Otherwise,\ndisplays most recent stack and then exits process.\n\n\n\n### displayStack(slice)\n\nDisplays the trace stack\n\n```javascript\n\nvar stack = Hoek.displayStack();\nconsole.log(stack); // returns something like:\n\n[ 'null (/Users/user/Desktop/hoek/test.js:4:18)',\n  'Module._compile (module.js:449:26)',\n  'Module._extensions..js (module.js:467:10)',\n  'Module.load (module.js:356:32)',\n  'Module._load (module.js:312:12)',\n  'Module.runMain (module.js:492:10)',\n  'startup.processNextTick.process._tickCallback (node.js:244:9)' ]\n```\n\n### callStack(slice)\n\nReturns a trace stack array.\n\n```javascript\n\nvar stack = Hoek.callStack();\nconsole.log(stack);  // returns something like:\n\n[ [ '/Users/user/Desktop/hoek/test.js', 4, 18, null, false ],\n  [ 'module.js', 449, 26, 'Module._compile', false ],\n  [ 'module.js', 467, 10, 'Module._extensions..js', false ],\n  [ 'module.js', 356, 32, 'Module.load', false ],\n  [ 'module.js', 312, 12, 'Module._load', false ],\n  [ 'module.js', 492, 10, 'Module.runMain', false ],\n  [ 'node.js',\n    244,\n    9,\n    'startup.processNextTick.process._tickCallback',\n    false ] ]\n```\n\n## Function\n\n### nextTick(fn)\n\nReturns a new function that wraps `fn` in `process.nextTick`.\n\n```javascript\n\nvar myFn = function () {\n    console.log('Do this later');\n};\n\nvar nextFn = Hoek.nextTick(myFn);\n\nnextFn();\nconsole.log('Do this first');\n\n// Results in:\n//\n// Do this first\n// Do this later\n```\n\n### once(fn)\n\nReturns a new function that can be run multiple times, but makes sure `fn` is only run once.\n\n```javascript\n\nvar myFn = function () {\n    console.log('Ran myFn');\n};\n\nvar onceFn = Hoek.once(myFn);\nonceFn(); // results in \"Ran myFn\"\nonceFn(); // results in undefined\n```\n\n### ignore\n\nA simple no-op function. It does nothing at all.\n\n## Miscellaneous\n\n### uniqueFilename(path, extension)\n`path` to prepend with the randomly generated file name. `extension` is the optional file extension, defaults to `''`.\n\nReturns a randomly generated file name at the specified `path`. The result is a fully resolved path to a file.\n\n```javascript\nvar result = Hoek.uniqueFilename('./test/modules', 'txt'); // results in \"full/path/test/modules/{random}.txt\"\n```\n\n### isAbsolutePath(path, [platform])\n\nDetermines whether `path` is an absolute path. Returns `true` or `false`.\n\n- `path` - A file path to test for whether it is absolute or not.\n- `platform` - An optional parameter used for specifying the platform. Defaults to `process.platform`.\n\n### isInteger(value)\n\nCheck `value` to see if it is an integer.  Returns true/false.\n\n```javascript\nvar result = Hoek.isInteger('23')\n```\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/hapijs/hoek/issues"
-  },
-  "_id": "hoek@2.16.3",
-  "dist": {
-    "shasum": "971abcb413ed680782575bd079a72b9444df0ff4"
+    "test": "lab -a @hapi/code -t 100 -L -Y",
+    "test-cov-html": "lab -a @hapi/code -t 100 -L -r html -o coverage.html"
   },
-  "_from": "hoek@2.x.x",
-  "_resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz"
+  "license": "BSD-3-Clause"
 }
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/escaper.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/escaper.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/escaper.js	(working copy)
@@ -1,88 +1,123 @@
-// Load modules
+'use strict';
 
-var Code = require('code');
-var Hoek = require('../lib');
-var Lab = require('lab');
+const Code = require('@hapi/code');
+const Hoek = require('..');
+const Lab = require('@hapi/lab');
 
 
-// Declare internals
+const internals = {};
 
-var internals = {};
 
+const { describe, it } = exports.lab = Lab.script();
+const expect = Code.expect;
 
-// Test shortcuts
 
-var lab = exports.lab = Lab.script();
-var describe = lab.experiment;
-var it = lab.test;
-var expect = Code.expect;
+describe('escapeHtml()', () => {
 
+    it('encodes / characters', () => {
 
-describe('escapeJavaScript()', function () {
+        const encoded = Hoek.escapeHtml('<script>alert(1)</script>');
+        expect(encoded).to.equal('&lt;script&gt;alert&#x28;1&#x29;&lt;&#x2f;script&gt;');
+    });
 
-    it('encodes / characters', function (done) {
+    it('encodes < and > as named characters', () => {
 
-        var encoded = Hoek.escapeJavaScript('<script>alert(1)</script>');
-        expect(encoded).to.equal('\\x3cscript\\x3ealert\\x281\\x29\\x3c\\x2fscript\\x3e');
-        done();
+        const encoded = Hoek.escapeHtml('<script><>');
+        expect(encoded).to.equal('&lt;script&gt;&lt;&gt;');
     });
 
-    it('encodes \' characters', function (done) {
+    it('encodes large unicode characters', () => {
 
-        var encoded = Hoek.escapeJavaScript('something(\'param\')');
-        expect(encoded).to.equal('something\\x28\\x27param\\x27\\x29');
-        done();
+        const encoded = Hoek.escapeHtml(String.fromCharCode(500) + String.fromCharCode(1000));
+        expect(encoded).to.equal('&#500;&#1000;');
     });
 
-    it('encodes large unicode characters with the correct padding', function (done) {
+    it('doesn\'t throw an exception when passed null', () => {
 
-        var encoded = Hoek.escapeJavaScript(String.fromCharCode(500) + String.fromCharCode(1000));
-        expect(encoded).to.equal('\\u0500\\u1000');
-        done();
+        const encoded = Hoek.escapeHtml(null);
+        expect(encoded).to.equal('');
     });
 
-    it('doesn\'t throw an exception when passed null', function (done) {
+    it('encodes {} characters', () => {
 
-        var encoded = Hoek.escapeJavaScript(null);
-        expect(encoded).to.equal('');
-        done();
+        const encoded = Hoek.escapeHtml('{}');
+        expect(encoded).to.equal('&#x7b;&#x7d;');
     });
 });
 
-describe('escapeHtml()', function () {
+describe('escapeJson()', () => {
 
-    it('encodes / characters', function (done) {
+    it('encodes < and > as unicode escaped equivalents', () => {
 
-        var encoded = Hoek.escapeHtml('<script>alert(1)</script>');
-        expect(encoded).to.equal('&lt;script&gt;alert&#x28;1&#x29;&lt;&#x2f;script&gt;');
-        done();
+        const encoded = Hoek.escapeJson('<script><>');
+        expect(encoded).to.equal('\\u003cscript\\u003e\\u003c\\u003e');
     });
 
-    it('encodes < and > as named characters', function (done) {
+    it('doesn\'t encode \0 as hex escaped equivalent', () => {
 
-        var encoded = Hoek.escapeHtml('<script><>');
-        expect(encoded).to.equal('&lt;script&gt;&lt;&gt;');
-        done();
+        const encoded = Hoek.escapeJson('\0');
+        expect(encoded).to.equal('\0');
     });
 
-    it('encodes large unicode characters', function (done) {
+    it('encodes & (ampersand) as unicode escaped equivalent', () => {
 
-        var encoded = Hoek.escapeHtml(String.fromCharCode(500) + String.fromCharCode(1000));
-        expect(encoded).to.equal('&#500;&#1000;');
-        done();
+        const encoded = Hoek.escapeJson('&&');
+        expect(encoded).to.equal('\\u0026\\u0026');
+    });
+
+    it('encodes line seperator as unicode escaped equivalent', () => {
+
+        const lineSeparator = String.fromCharCode(0x2028);
+        const encoded = Hoek.escapeJson(lineSeparator);
+        expect(encoded).to.equal('\\u2028');
+    });
+
+    it('encodes paragraph seperator as unicode escaped equivalent', () => {
+
+        const paragraphSeparator = String.fromCharCode(0x2029);
+        const encoded = Hoek.escapeJson(paragraphSeparator);
+        expect(encoded).to.equal('\\u2029');
     });
 
-    it('doesn\'t throw an exception when passed null', function (done) {
+    it('doesn\'t encode U+13F0 Cherokee Letter Ye as unicode escaped equivalent', () => {
 
-        var encoded = Hoek.escapeHtml(null);
+        const encoded = Hoek.escapeJson('Ᏸ');
+        expect(encoded).to.equal('Ᏸ');
+    });
+
+    it('doesn\'t encode U+1F4A9 PILE OF POO as unicode escaped equivalent', () => {
+
+        const encoded = Hoek.escapeJson('💩');
+        expect(encoded).to.equal('💩');
+    });
+
+    it('doesn\'t encode U+1D306 TETRAGRAM FOR CENTRE as unicode escaped equivalent', () => {
+
+        const encoded = Hoek.escapeJson('𝌆');
+        expect(encoded).to.equal('𝌆');
+    });
+
+    it('doesn\'t encode \\ (backslash)', () => {
+
+        const encoded = Hoek.escapeJson('\\');
+        expect(encoded).to.equal('\\');
+    });
+
+    it('doesn\'t throw an exception when passed null', () => {
+
+        const encoded = Hoek.escapeJson(null);
         expect(encoded).to.equal('');
-        done();
     });
 
-    it('encodes {} characters', function (done) {
+    it('doesn\'t encode {} characters', () => {
 
-        var encoded = Hoek.escapeHtml('{}');
-        expect(encoded).to.equal('&#x7b;&#x7d;');
-        done();
+        const encoded = Hoek.escapeJson('{}');
+        expect(encoded).to.equal('{}');
+    });
+
+    it('doesn\'t encode / (slash) character', () => {
+
+        const encoded = Hoek.escapeJson('<script>alert(1)</script>');
+        expect(encoded).to.equal('\\u003cscript\\u003ealert(1)\\u003c/script\\u003e');
     });
 });
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/index.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/index.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/index.js	(working copy)
@@ -1,26 +1,20 @@
-// Load modules
+'use strict';
 
-var Fs = require('fs');
-var Path = require('path');
-var Code = require('code');
-var Hoek = require('../lib');
-var Lab = require('lab');
+const Util = require('util');
 
+const Code = require('@hapi/code');
+const Hoek = require('..');
+const Lab = require('@hapi/lab');
 
-// Declare internals
 
-var internals = {};
+const internals = {};
 
 
-// Test shortcuts
+const { describe, it } = exports.lab = Lab.script();
+const expect = Code.expect;
 
-var lab = exports.lab = Lab.script();
-var describe = lab.experiment;
-var it = lab.test;
-var expect = Code.expect;
 
-
-var nestedObj = {
+const nestedObj = {
     v: [7, 8, 9],
     w: /^something$/igm,
     x: {
@@ -34,388 +28,84 @@
     z: new Date(1378775452757)
 };
 
-var dupsArray = [nestedObj, { z: 'z' }, nestedObj];
-var reducedDupsArray = [nestedObj, { z: 'z' }];
-
-describe('clone()', function () {
-
-    it('clones a nested object', function (done) {
-
-        var a = nestedObj;
-        var b = Hoek.clone(a);
-
-        expect(a).to.deep.equal(b);
-        expect(a.z.getTime()).to.equal(b.z.getTime());
-        done();
-    });
-
-    it('clones a null object', function (done) {
-
-        var b = Hoek.clone(null);
-
-        expect(b).to.equal(null);
-        done();
-    });
-
-    it('should not convert undefined properties to null', function (done) {
-
-        var obj = { something: undefined };
-        var b = Hoek.clone(obj);
-
-        expect(typeof b.something).to.equal('undefined');
-        done();
-    });
-
-    it('should not throw on circular reference', function (done) {
-
-        var a = {};
-        a.x = a;
-
-        var test = function () {
-
-            var b = Hoek.clone(a);
-        };
-
-        expect(test).to.not.throw();
-        done();
-    });
-
-    it('clones circular reference', function (done) {
-
-        var x = {
-            'z': new Date()
-        };
-        x.y = x;
-
-        var b = Hoek.clone(x);
-        expect(Object.keys(b.y)).to.deep.equal(Object.keys(x));
-        expect(b.z).to.not.equal(x.z);
-        expect(b.y).to.not.equal(x.y);
-        expect(b.y.z).to.not.equal(x.y.z);
-        expect(b.y).to.equal(b);
-        expect(b.y.y.y.y).to.equal(b);
-        done();
-    });
-
-    it('clones an object with a null prototype', function (done) {
-
-        var obj = Object.create(null);
-        var b = Hoek.clone(obj);
-
-        expect(b).to.deep.equal(obj);
-        done();
-    });
-
-    it('clones deeply nested object', function (done) {
-
-        var a = {
-            x: {
-                y: {
-                    a: [1, 2, 3],
-                    b: 123456,
-                    c: new Date(),
-                    d: /hi/igm,
-                    e: /hello/
-                }
-            }
-        };
-
-        var b = Hoek.clone(a);
-
-        expect(a).to.deep.equal(b);
-        expect(a.x.y.c.getTime()).to.equal(b.x.y.c.getTime());
-        done();
-    });
-
-    it('clones arrays', function (done) {
-
-        var a = [1, 2, 3];
-
-        var b = Hoek.clone(a);
-
-        expect(a).to.deep.equal(b);
-        done();
-    });
-
-    it('performs actual copy for shallow keys (no pass by reference)', function (done) {
-
-        var x = Hoek.clone(nestedObj);
-        var y = Hoek.clone(nestedObj);
-
-        // Date
-        expect(x.z).to.not.equal(nestedObj.z);
-        expect(x.z).to.not.equal(y.z);
-
-        // Regex
-        expect(x.w).to.not.equal(nestedObj.w);
-        expect(x.w).to.not.equal(y.w);
-
-        // Array
-        expect(x.v).to.not.equal(nestedObj.v);
-        expect(x.v).to.not.equal(y.v);
-
-        // Immutable(s)
-        x.y = 5;
-        expect(x.y).to.not.equal(nestedObj.y);
-        expect(x.y).to.not.equal(y.y);
-
-        done();
-    });
-
-    it('performs actual copy for deep keys (no pass by reference)', function (done) {
-
-        var x = Hoek.clone(nestedObj);
-        var y = Hoek.clone(nestedObj);
-
-        expect(x.x.c).to.not.equal(nestedObj.x.c);
-        expect(x.x.c).to.not.equal(y.x.c);
-
-        expect(x.x.c.getTime()).to.equal(nestedObj.x.c.getTime());
-        expect(x.x.c.getTime()).to.equal(y.x.c.getTime());
-        done();
-    });
-
-    it('copies functions with properties', function (done) {
-
-        var a = {
-            x: function () {
-
-                return 1;
-            },
-            y: {}
-        };
-        a.x.z = 'string in function';
-        a.x.v = function () {
-
-            return 2;
-        };
-        a.y.u = a.x;
-
-        var b = Hoek.clone(a);
-        expect(b.x()).to.equal(1);
-        expect(b.x.v()).to.equal(2);
-        expect(b.y.u).to.equal(b.x);
-        expect(b.x.z).to.equal('string in function');
-        done();
-    });
-
-    it('should copy a buffer', function (done) {
-
-        var tls = {
-            key: new Buffer([1, 2, 3, 4, 5]),
-            cert: new Buffer([1, 2, 3, 4, 5, 6, 10])
-        };
-
-        var copiedTls = Hoek.clone(tls);
-        expect(Buffer.isBuffer(copiedTls.key)).to.equal(true);
-        expect(JSON.stringify(copiedTls.key)).to.equal(JSON.stringify(tls.key));
-        expect(Buffer.isBuffer(copiedTls.cert)).to.equal(true);
-        expect(JSON.stringify(copiedTls.cert)).to.equal(JSON.stringify(tls.cert));
-        done();
-    });
-
-    it('clones an object with a prototype', function (done) {
-
-        var Obj = function () {
-
-            this.a = 5;
-        };
-
-        Obj.prototype.b = function () {
-
-            return 'c';
-        };
-
-        var a = new Obj();
-        var b = Hoek.clone(a);
-
-        expect(b.a).to.equal(5);
-        expect(b.b()).to.equal('c');
-        expect(a).to.deep.equal(b);
-        done();
-    });
-
-    it('reuses cloned Date object', function (done) {
-
-        var obj = {
-            a: new Date()
-        };
-
-        obj.b = obj.a;
-
-        var copy = Hoek.clone(obj);
-        expect(copy.a).to.equal(copy.b);
-        done();
-    });
-
-    it('shallow copies an object with a prototype and isImmutable flag', function (done) {
-
-        var Obj = function () {
-
-            this.value = 5;
-        };
-
-        Obj.prototype.b = function () {
-
-            return 'c';
-        };
-
-        Obj.prototype.isImmutable = true;
-
-        var obj = {
-            a: new Obj()
-        };
 
-        var copy = Hoek.clone(obj);
+describe('merge()', () => {
 
-        expect(obj.a.value).to.equal(5);
-        expect(copy.a.value).to.equal(5);
-        expect(copy.a.b()).to.equal('c');
-        expect(obj.a).to.equal(copy.a);
-        done();
-    });
+    it('deep copies source items', () => {
 
-    it('clones an object with property getter without executing it', function (done) {
+        const sym1 = Symbol('1');
+        const sym2 = Symbol('2');
+        const sym3 = Symbol('3');
 
-        var obj = {};
-        var value = 1;
-        var execCount = 0;
-
-        Object.defineProperty(obj, 'test', {
-            enumerable: true,
-            configurable: true,
-            get: function () {
-
-                ++execCount;
-                return value;
-            }
-        });
-
-        var copy = Hoek.clone(obj);
-        expect(execCount).to.equal(0);
-        expect(copy.test).to.equal(1);
-        expect(execCount).to.equal(1);
-        done();
-    });
-
-    it('clones an object with property getter and setter', function (done) {
-
-        var obj = {
-            _test: 0
+        const target = {
+            b: 3,
+            d: [],
+            [sym1]: true,
+            [sym3]: true
         };
 
-        Object.defineProperty(obj, 'test', {
-            enumerable: true,
-            configurable: true,
-            get: function () {
-
-                return this._test;
+        const source = {
+            c: {
+                d: 1
             },
-            set: function (value) {
-
-                this._test = value - 1;
-            }
-        });
-
-        var copy = Hoek.clone(obj);
-        expect(copy.test).to.equal(0);
-        copy.test = 5;
-        expect(copy.test).to.equal(4);
-        done();
-    });
-
-    it('clones an object with only property setter', function (done) {
-
-        var obj = {
-            _test: 0
+            d: [{ e: 1 }],
+            [sym2]: true,
+            [sym3]: false
         };
 
-        Object.defineProperty(obj, 'test', {
-            enumerable: true,
-            configurable: true,
-            set: function (value) {
-
-                this._test = value - 1;
-            }
-        });
-
-        var copy = Hoek.clone(obj);
-        expect(copy._test).to.equal(0);
-        copy.test = 5;
-        expect(copy._test).to.equal(4);
-        done();
-    });
-
-    it('clones an object with non-enumerable properties', function (done) {
-
-        var obj = {
-            _test: 0
-        };
-
-        Object.defineProperty(obj, 'test', {
-            enumerable: false,
-            configurable: true,
-            set: function (value) {
-
-                this._test = value - 1;
-            }
-        });
-
-        var copy = Hoek.clone(obj);
-        expect(copy._test).to.equal(0);
-        copy.test = 5;
-        expect(copy._test).to.equal(4);
-        done();
-    });
-
-    it('clones an object where getOwnPropertyDescriptor returns undefined', function (done) {
-
-        var oldGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
-        var obj = { a: 'b' };
-        Object.getOwnPropertyDescriptor = function () {
-
-            return undefined;
-        };
+        Hoek.merge(target, source);
+        expect(target.c).to.not.shallow.equal(source.c);
+        expect(target.c).to.equal(source.c);
+        expect(target.d).to.not.shallow.equal(source.d);
+        expect(target.d[0]).to.not.shallow.equal(source.d[0]);
+        expect(target.d).to.equal(source.d);
 
-        var copy = Hoek.clone(obj);
-        Object.getOwnPropertyDescriptor = oldGetOwnPropertyDescriptor;
-        expect(copy).to.deep.equal(obj);
-        done();
+        expect(target[sym1]).to.be.true();
+        expect(target[sym2]).to.be.true();
+        expect(target[sym3]).to.be.false();
     });
-});
 
-describe('merge()', function () {
+    it('deep copies source items without symbols', () => {
 
-    it('deep copies source items', function (done) {
+        const sym1 = Symbol('1');
+        const sym2 = Symbol('2');
+        const sym3 = Symbol('3');
 
-        var target = {
+        const target = {
             b: 3,
-            d: []
+            d: [],
+            [sym1]: true,
+            [sym3]: true
         };
 
-        var source = {
+        const source = {
             c: {
                 d: 1
             },
-            d: [{ e: 1 }]
+            d: [{ e: 1 }],
+            [sym2]: true,
+            [sym3]: false
         };
 
-        Hoek.merge(target, source);
-        expect(target.c).to.not.equal(source.c);
-        expect(target.c).to.deep.equal(source.c);
-        expect(target.d).to.not.equal(source.d);
-        expect(target.d[0]).to.not.equal(source.d[0]);
-        expect(target.d).to.deep.equal(source.d);
-        done();
+        Hoek.merge(target, source, { symbols: false });
+        expect(target.c).to.not.shallow.equal(source.c);
+        expect(target.c).to.equal(source.c);
+        expect(target.d).to.not.shallow.equal(source.d);
+        expect(target.d[0]).to.not.shallow.equal(source.d[0]);
+        expect(target.d).to.equal(source.d);
+
+        expect(target[sym1]).to.be.true();
+        expect(target[sym2]).to.not.exist();
+        expect(target[sym3]).to.be.true();
     });
 
-    it('merges array over an object', function (done) {
+    it('merges array over an object', () => {
 
-        var a = {
+        const a = {
             x: ['n', 'm']
         };
 
-        var b = {
+        const b = {
             x: {
                 n: '1',
                 m: '2'
@@ -425,16 +115,15 @@
         Hoek.merge(b, a);
         expect(a.x[0]).to.equal('n');
         expect(a.x.n).to.not.exist();
-        done();
     });
 
-    it('merges object over an array', function (done) {
+    it('merges object over an array', () => {
 
-        var a = {
+        const a = {
             x: ['n', 'm']
         };
 
-        var b = {
+        const b = {
             x: {
                 n: '1',
                 m: '2'
@@ -444,206 +133,298 @@
         Hoek.merge(a, b);
         expect(a.x.n).to.equal('1');
         expect(a.x[0]).to.not.exist();
-        done();
     });
 
-    it('does not throw if source is null', function (done) {
+    it('merges from null prototype objects', () => {
+
+        const a = {};
+
+        const b = Object.create(null);
+        b.x = true;
+
+        Hoek.merge(a, b);
+        expect(a.x).to.be.true();
+    });
+
+    it('skips non-enumerable properties', () => {
+
+        const a = { x: 0 };
+
+        const b = {};
+        Object.defineProperty(b, 'x', {
+            enumerable: false,
+            value: 1
+        });
+
+        Hoek.merge(a, b);
+        expect(a.x).to.equal(0);
+    });
 
-        var a = {};
-        var b = null;
-        var c = null;
+    it('does not throw if source is null', () => {
 
-        expect(function () {
+        const a = {};
+        const b = null;
+        let c = null;
+
+        expect(() => {
 
             c = Hoek.merge(a, b);
         }).to.not.throw();
 
         expect(c).to.equal(a);
-        done();
     });
 
-    it('does not throw if source is undefined', function (done) {
+    it('does not throw if source is undefined', () => {
 
-        var a = {};
-        var b;
-        var c = null;
+        const a = {};
+        const b = undefined;
+        let c = null;
 
-        expect(function () {
+        expect(() => {
 
             c = Hoek.merge(a, b);
         }).to.not.throw();
 
         expect(c).to.equal(a);
-        done();
     });
 
-    it('throws if source is not an object', function (done) {
+    it('throws if source is not an object', () => {
 
-        expect(function () {
+        expect(() => {
 
-            var a = {};
-            var b = 0;
+            const a = {};
+            const b = 0;
 
             Hoek.merge(a, b);
         }).to.throw('Invalid source value: must be null, undefined, or an object');
-        done();
     });
 
-    it('throws if target is not an object', function (done) {
+    it('throws if target is not an object', () => {
 
-        expect(function () {
+        expect(() => {
 
-            var a = 0;
-            var b = {};
+            const a = 0;
+            const b = {};
 
             Hoek.merge(a, b);
         }).to.throw('Invalid target value: must be an object');
-        done();
     });
 
-    it('throws if target is not an array and source is', function (done) {
+    it('throws if target is not an array and source is', () => {
 
-        expect(function () {
+        expect(() => {
 
-            var a = {};
-            var b = [1, 2];
+            const a = {};
+            const b = [1, 2];
 
             Hoek.merge(a, b);
         }).to.throw('Cannot merge array onto an object');
-        done();
     });
 
-    it('returns the same object when merging arrays', function (done) {
+    it('returns the same object when merging arrays', () => {
 
-        var a = [];
-        var b = [1, 2];
+        const a = [];
+        const b = [1, 2];
 
         expect(Hoek.merge(a, b)).to.equal(a);
-        done();
     });
 
-    it('combines an empty object with a non-empty object', function (done) {
+    it('combines an empty object with a non-empty object', () => {
 
-        var a = {};
-        var b = nestedObj;
+        const a = {};
+        const b = nestedObj;
 
-        var c = Hoek.merge(a, b);
-        expect(a).to.deep.equal(b);
-        expect(c).to.deep.equal(b);
-        done();
+        const c = Hoek.merge(a, b);
+        expect(a).to.equal(b);
+        expect(c).to.equal(b);
     });
 
-    it('overrides values in target', function (done) {
+    it('overrides values in target', () => {
 
-        var a = { x: 1, y: 2, z: 3, v: 5, t: 'test', m: 'abc' };
-        var b = { x: null, z: 4, v: 0, t: { u: 6 }, m: '123' };
+        const a = { x: 1, y: 2, z: 3, v: 5, t: 'test', s: 1, m: 'abc' };
+        const b = { x: null, z: 4, v: 0, t: { u: 6 }, s: undefined, m: '123' };
 
-        var c = Hoek.merge(a, b);
+        const c = Hoek.merge(a, b);
         expect(c.x).to.equal(null);
         expect(c.y).to.equal(2);
         expect(c.z).to.equal(4);
         expect(c.v).to.equal(0);
         expect(c.m).to.equal('123');
-        expect(c.t).to.deep.equal({ u: 6 });
-        done();
+        expect(c.t).to.equal({ u: 6 });
+        expect(c.s).to.equal(undefined);
     });
 
-    it('overrides values in target (flip)', function (done) {
+    it('overrides values in target (flip)', () => {
 
-        var a = { x: 1, y: 2, z: 3, v: 5, t: 'test', m: 'abc' };
-        var b = { x: null, z: 4, v: 0, t: { u: 6 }, m: '123' };
+        const a = { x: 1, y: 2, z: 3, v: 5, t: 'test', s: 1, m: 'abc' };
+        const b = { x: null, z: 4, v: 0, t: { u: 6 }, s: undefined, m: '123' };
 
-        var d = Hoek.merge(b, a);
+        const d = Hoek.merge(b, a);
         expect(d.x).to.equal(1);
         expect(d.y).to.equal(2);
         expect(d.z).to.equal(3);
         expect(d.v).to.equal(5);
         expect(d.m).to.equal('abc');
-        expect(d.t).to.deep.equal('test');
-        done();
+        expect(d.t).to.equal('test');
+        expect(d.s).to.equal(1);
     });
 
-    it('retains Date properties', function (done) {
+    it('retains Date properties', () => {
 
-        var a = { x: new Date(1378776452757) };
+        const a = { x: new Date(1378776452757) };
 
-        var b = Hoek.merge({}, a);
+        const b = Hoek.merge({}, a);
         expect(a.x.getTime()).to.equal(b.x.getTime());
-        done();
     });
 
-    it('retains Date properties when merging keys', function (done) {
+    it('retains Date properties when merging keys', () => {
 
-        var a = { x: new Date(1378776452757) };
+        const a = { x: new Date(1378776452757) };
 
-        var b = Hoek.merge({ x: {} }, a);
+        const b = Hoek.merge({ x: {} }, a);
         expect(a.x.getTime()).to.equal(b.x.getTime());
-        done();
     });
 
-    it('overrides Buffer', function (done) {
+    it('overrides Buffer', () => {
 
-        var a = { x: new Buffer('abc') };
+        const a = { x: Buffer.from('abc') };
 
-        var b = Hoek.merge({ x: {} }, a);
+        Hoek.merge({ x: {} }, a);
         expect(a.x.toString()).to.equal('abc');
-        done();
     });
-});
 
-describe('applyToDefaults()', function () {
+    it('overrides RegExp', () => {
 
-    var defaults = {
-        a: 1,
-        b: 2,
-        c: {
-            d: 3,
-            e: [5, 6]
-        },
-        f: 6,
-        g: 'test'
-    };
+        const a = { x: /test/ };
+
+        Hoek.merge({ x: {} }, a);
+        expect(a.x).to.equal(/test/);
+    });
+
+    it('overrides Symbol properties', () => {
+
+        const sym = Symbol();
+        const a = { [sym]: 1 };
+
+        Hoek.merge({ [sym]: {} }, a);
+        expect(a[sym]).to.equal(1);
+    });
+
+    it('skips __proto__', () => {
+
+        const a = '{ "ok": "value", "__proto__": { "test": "value" } }';
 
-    it('throws when target is null', function (done) {
+        const b = Hoek.merge({}, JSON.parse(a));
+        expect(b).to.equal({ ok: 'value' });
+        expect(b.test).to.equal(undefined);
+    });
+});
+
+describe('applyToDefaults()', () => {
 
-        expect(function () {
+    it('throws when target is null', () => {
+
+        expect(() => {
 
             Hoek.applyToDefaults(null, {});
         }).to.throw('Invalid defaults value: must be an object');
-        done();
     });
 
-    it('returns null if options is false', function (done) {
+    it('throws when options are invalid', () => {
+
+        expect(() => {
+
+            Hoek.applyToDefaults({}, {}, false);
+        }).to.throw('Invalid options: must be an object');
+
+        expect(() => {
+
+            Hoek.applyToDefaults({}, {}, 123);
+        }).to.throw('Invalid options: must be an object');
+    });
+
+    it('returns null if source is false', () => {
 
-        var result = Hoek.applyToDefaults(defaults, false);
+        const defaults = {
+            a: 1,
+            b: 2,
+            c: {
+                d: 3,
+                e: [5, 6]
+            },
+            f: 6,
+            g: 'test'
+        };
+
+        const result = Hoek.applyToDefaults(defaults, false);
         expect(result).to.equal(null);
-        done();
     });
 
-    it('returns null if options is null', function (done) {
+    it('returns null if source is null', () => {
 
-        var result = Hoek.applyToDefaults(defaults, null);
+        const defaults = {
+            a: 1,
+            b: 2,
+            c: {
+                d: 3,
+                e: [5, 6]
+            },
+            f: 6,
+            g: 'test'
+        };
+
+        const result = Hoek.applyToDefaults(defaults, null);
         expect(result).to.equal(null);
-        done();
     });
 
-    it('returns null if options is undefined', function (done) {
+    it('returns null if source is undefined', () => {
 
-        var result = Hoek.applyToDefaults(defaults, undefined);
+        const defaults = {
+            a: 1,
+            b: 2,
+            c: {
+                d: 3,
+                e: [5, 6]
+            },
+            f: 6,
+            g: 'test'
+        };
+
+        const result = Hoek.applyToDefaults(defaults, undefined);
         expect(result).to.equal(null);
-        done();
     });
 
-    it('returns a copy of defaults if options is true', function (done) {
+    it('returns a copy of defaults if source is true', () => {
 
-        var result = Hoek.applyToDefaults(defaults, true);
-        expect(result).to.deep.equal(defaults);
-        done();
+        const defaults = {
+            a: 1,
+            b: 2,
+            c: {
+                d: 3,
+                e: [5, 6]
+            },
+            f: 6,
+            g: 'test'
+        };
+
+        const result = Hoek.applyToDefaults(defaults, true);
+        expect(result).to.equal(defaults);
     });
 
-    it('applies object to defaults', function (done) {
+    it('applies object to defaults', () => {
+
+        const defaults = {
+            a: 1,
+            b: 2,
+            c: {
+                d: 3,
+                e: [5, 6]
+            },
+            f: 6,
+            g: 'test'
+        };
 
-        var obj = {
+        const obj = {
             a: null,
             c: {
                 e: [4]
@@ -654,18 +435,28 @@
             }
         };
 
-        var result = Hoek.applyToDefaults(defaults, obj);
-        expect(result.c.e).to.deep.equal([4]);
+        const result = Hoek.applyToDefaults(defaults, obj);
+        expect(result.c.e).to.equal([4]);
         expect(result.a).to.equal(1);
         expect(result.b).to.equal(2);
         expect(result.f).to.equal(0);
-        expect(result.g).to.deep.equal({ h: 5 });
-        done();
+        expect(result.g).to.equal({ h: 5 });
     });
 
-    it('applies object to defaults with null', function (done) {
+    it('applies object to defaults with null', () => {
+
+        const defaults = {
+            a: 1,
+            b: 2,
+            c: {
+                d: 3,
+                e: [5, 6]
+            },
+            f: 6,
+            g: 'test'
+        };
 
-        var obj = {
+        const obj = {
             a: null,
             c: {
                 e: [4]
@@ -676,80 +467,17 @@
             }
         };
 
-        var result = Hoek.applyToDefaults(defaults, obj, true);
-        expect(result.c.e).to.deep.equal([4]);
+        const result = Hoek.applyToDefaults(defaults, obj, { nullOverride: true });
+        expect(result.c.e).to.equal([4]);
         expect(result.a).to.equal(null);
         expect(result.b).to.equal(2);
         expect(result.f).to.equal(0);
-        expect(result.g).to.deep.equal({ h: 5 });
-        done();
-    });
-});
-
-describe('cloneWithShallow()', function () {
-
-    it('deep clones except for listed keys', function (done) {
-
-        var source = {
-            a: {
-                b: 5
-            },
-            c: {
-                d: 6
-            }
-        };
-
-        var copy = Hoek.cloneWithShallow(source, ['c']);
-        expect(copy).to.deep.equal(source);
-        expect(copy).to.not.equal(source);
-        expect(copy.a).to.not.equal(source.a);
-        expect(copy.b).to.equal(source.b);
-        done();
-    });
-
-    it('returns immutable value', function (done) {
-
-        expect(Hoek.cloneWithShallow(5)).to.equal(5);
-        done();
+        expect(result.g).to.equal({ h: 5 });
     });
 
-    it('returns null value', function (done) {
+    it('shallow copies the listed keys from source without merging', () => {
 
-        expect(Hoek.cloneWithShallow(null)).to.equal(null);
-        done();
-    });
-
-    it('returns undefined value', function (done) {
-
-        expect(Hoek.cloneWithShallow(undefined)).to.equal(undefined);
-        done();
-    });
-
-    it('deep clones except for listed keys (including missing keys)', function (done) {
-
-        var source = {
-            a: {
-                b: 5
-            },
-            c: {
-                d: 6
-            }
-        };
-
-        var copy = Hoek.cloneWithShallow(source, ['c', 'v']);
-        expect(copy).to.deep.equal(source);
-        expect(copy).to.not.equal(source);
-        expect(copy.a).to.not.equal(source.a);
-        expect(copy.b).to.equal(source.b);
-        done();
-    });
-});
-
-describe('applyToDefaultsWithShallow()', function () {
-
-    it('shallow copies the listed keys from options without merging', function (done) {
-
-        var defaults = {
+        const defaults = {
             a: {
                 b: 5,
                 e: 3
@@ -760,7 +488,7 @@
             }
         };
 
-        var options = {
+        const source = {
             a: {
                 b: 4
             },
@@ -770,18 +498,17 @@
             }
         };
 
-        var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['a']);
-        expect(merged).to.deep.equal({ a: { b: 4 }, c: { d: 6, g: 1, f: 7 } });
-        expect(merged.a).to.equal(options.a);
+        const merged = Hoek.applyToDefaults(defaults, source, { shallow: ['a'] });
+        expect(merged).to.equal({ a: { b: 4 }, c: { d: 6, g: 1, f: 7 } });
+        expect(merged.a).to.shallow.equal(source.a);
         expect(merged.a).to.not.equal(defaults.a);
-        expect(merged.c).to.not.equal(options.c);
+        expect(merged.c).to.not.equal(source.c);
         expect(merged.c).to.not.equal(defaults.c);
-        done();
     });
 
-    it('shallow copies the nested keys (override)', function (done) {
+    it('shallow copies the nested keys (override)', () => {
 
-        var defaults = {
+        const defaults = {
             a: {
                 b: 5
             },
@@ -791,7 +518,7 @@
             }
         };
 
-        var options = {
+        const source = {
             a: {
                 b: 4
             },
@@ -803,21 +530,20 @@
             }
         };
 
-        var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['c.g']);
-        expect(merged).to.deep.equal({ a: { b: 4 }, c: { d: 6, g: { h: 8 } } });
-        expect(merged.c.g).to.equal(options.c.g);
-        done();
+        const merged = Hoek.applyToDefaults(defaults, source, { shallow: ['c.g'] });
+        expect(merged).to.equal({ a: { b: 4 }, c: { d: 6, g: { h: 8 } } });
+        expect(merged.c.g).to.shallow.equal(source.c.g);
     });
 
-    it('shallow copies the nested keys (missing)', function (done) {
+    it('shallow copies the nested keys (missing)', () => {
 
-        var defaults = {
+        const defaults = {
             a: {
                 b: 5
             }
         };
 
-        var options = {
+        const source = {
             a: {
                 b: 4
             },
@@ -828,15 +554,14 @@
             }
         };
 
-        var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['c.g']);
-        expect(merged).to.deep.equal({ a: { b: 4 }, c: { g: { h: 8 } } });
-        expect(merged.c.g).to.equal(options.c.g);
-        done();
+        const merged = Hoek.applyToDefaults(defaults, source, { shallow: ['c.g'] });
+        expect(merged).to.equal({ a: { b: 4 }, c: { g: { h: 8 } } });
+        expect(merged.c.g).to.shallow.equal(source.c.g);
     });
 
-    it('shallow copies the nested keys (override)', function (done) {
+    it('shallow copies the nested keys (override)', () => {
 
-        var defaults = {
+        const defaults = {
             a: {
                 b: 5
             },
@@ -847,7 +572,7 @@
             }
         };
 
-        var options = {
+        const source = {
             a: {
                 b: 4
             },
@@ -858,21 +583,20 @@
             }
         };
 
-        var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['c.g']);
-        expect(merged).to.deep.equal({ a: { b: 4 }, c: { g: { h: 8 } } });
-        expect(merged.c.g).to.equal(options.c.g);
-        done();
+        const merged = Hoek.applyToDefaults(defaults, source, { shallow: ['c.g'] });
+        expect(merged).to.equal({ a: { b: 4 }, c: { g: { h: 8 } } });
+        expect(merged.c.g).to.shallow.equal(source.c.g);
     });
 
-    it('shallow copies the nested keys (deeper)', function (done) {
+    it('shallow copies the nested keys (deeper)', () => {
 
-        var defaults = {
+        const defaults = {
             a: {
                 b: 5
             }
         };
 
-        var options = {
+        const source = {
             a: {
                 b: 4
             },
@@ -885,21 +609,20 @@
             }
         };
 
-        var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['c.g.r']);
-        expect(merged).to.deep.equal({ a: { b: 4 }, c: { g: { r: { h: 8 } } } });
-        expect(merged.c.g.r).to.equal(options.c.g.r);
-        done();
+        const merged = Hoek.applyToDefaults(defaults, source, { shallow: ['c.g.r'] });
+        expect(merged).to.equal({ a: { b: 4 }, c: { g: { r: { h: 8 } } } });
+        expect(merged.c.g.r).to.shallow.equal(source.c.g.r);
     });
 
-    it('shallow copies the nested keys (not present)', function (done) {
+    it('shallow copies the nested keys (not present)', () => {
 
-        var defaults = {
+        const defaults = {
             a: {
                 b: 5
             }
         };
 
-        var options = {
+        const source = {
             a: {
                 b: 4
             },
@@ -912,99 +635,238 @@
             }
         };
 
-        var merged = Hoek.applyToDefaultsWithShallow(defaults, options, ['x.y']);
-        expect(merged).to.deep.equal({ a: { b: 4 }, c: { g: { r: { h: 8 } } } });
-        done();
+        const merged = Hoek.applyToDefaults(defaults, source, { shallow: ['x.y'] });
+        expect(merged).to.equal({ a: { b: 4 }, c: { g: { r: { h: 8 } } } });
     });
 
-    it('shallow copies the listed keys in the defaults', function (done) {
+    it('shallow copies the nested keys (non-object)', () => {
 
-        var defaults = {
+        const defaults = {
+            // All falsy values:
+            _undefined: {
+                a: 1
+            },
+            _null: {
+                a: 2
+            },
+            _false: {
+                a: 3
+            },
+            _emptyString: {
+                a: 4
+            },
+            _zero: {
+                a: 5
+            },
+            _NaN: {
+                a: 6
+            },
+            // Other non-object values:
+            _string: {
+                a: 7
+            },
+            _number: {
+                a: 8
+            },
+            _true: {
+                a: 9
+            },
+            _function: {
+                a: 10
+            }
+        };
+
+        const source = {
+            _undefined: undefined,
+            _null: null,
+            _false: false,
+            _emptyString: '',
+            _zero: 0,
+            _NaN: NaN,
+            _string: 'foo',
+            _number: 42,
+            _true: true,
+            _function: () => {}
+        };
+
+        const merged = Hoek.applyToDefaults(defaults, source, { shallow: [
+            '_undefined.a',
+            '_null.a',
+            '_false.a',
+            '_emptyString.a',
+            '_zero.a',
+            '_NaN.a',
+            '_string.a',
+            '_number.a',
+            '_true.a',
+            '_function.a'
+        ] });
+        expect(merged).to.equal({
+            _undefined: { a: 1 },
+            _null: { a: 2 },
+            _false: false,
+            _emptyString: '',
+            _zero: 0,
+            _NaN: NaN,
+            _string: 'foo',
+            _number: 42,
+            _true: true,
+            _function: source._function
+        });
+    });
+
+    it('shallow copies the listed keys in the defaults', () => {
+
+        const defaults = {
             a: {
                 b: 1
             }
         };
 
-        var merged = Hoek.applyToDefaultsWithShallow(defaults, {}, ['a']);
-        expect(merged.a).to.equal(defaults.a);
-        done();
+        const merged = Hoek.applyToDefaults(defaults, {}, { shallow: ['a'] });
+        expect(merged.a).to.shallow.equal(defaults.a);
     });
 
-    it('shallow copies the listed keys in the defaults (true)', function (done) {
+    it('shallow copies the listed keys in the defaults (true)', () => {
 
-        var defaults = {
+        const defaults = {
             a: {
                 b: 1
             }
         };
 
-        var merged = Hoek.applyToDefaultsWithShallow(defaults, true, ['a']);
-        expect(merged.a).to.equal(defaults.a);
-        done();
+        const merged = Hoek.applyToDefaults(defaults, true, { shallow: ['a'] });
+        expect(merged.a).to.shallow.equal(defaults.a);
     });
 
-    it('returns null on false', function (done) {
+    it('returns null on false', () => {
 
-        var defaults = {
+        const defaults = {
             a: {
                 b: 1
             }
         };
 
-        var merged = Hoek.applyToDefaultsWithShallow(defaults, false, ['a']);
+        const merged = Hoek.applyToDefaults(defaults, false, { shallow: ['a'] });
         expect(merged).to.equal(null);
-        done();
     });
 
-    it('throws on missing defaults', function (done) {
+    it('handles missing shallow key in defaults', () => {
 
-        expect(function () {
+        const defaults = {
+            a: {
+                b: 1
+            }
+        };
 
-            Hoek.applyToDefaultsWithShallow(null, {}, ['a']);
-        }).to.throw('Invalid defaults value: must be an object');
-        done();
+        const options = {
+            a: {
+                b: 4
+            },
+            c: {
+                d: 2
+            }
+        };
+
+        const merged = Hoek.applyToDefaults(defaults, options, { shallow: ['c'] });
+        expect(merged).to.equal({ a: { b: 4 }, c: { d: 2 } });
+        expect(merged.c).to.shallow.equal(options.c);
+
+        expect(Hoek.applyToDefaults(defaults, true, { shallow: ['c'] })).to.equal({ a: { b: 1 } });
     });
 
-    it('throws on invalid defaults', function (done) {
+    it('throws on missing defaults', () => {
+
+        expect(() => Hoek.applyToDefaults(null, {}, { shallow: ['a'] })).to.throw('Invalid defaults value: must be an object');
+    });
 
-        expect(function () {
+    it('throws on invalid defaults', () => {
 
-            Hoek.applyToDefaultsWithShallow('abc', {}, ['a']);
-        }).to.throw('Invalid defaults value: must be an object');
-        done();
+        expect(() => Hoek.applyToDefaults('abc', {}, { shallow: ['a'] })).to.throw('Invalid defaults value: must be an object');
     });
 
-    it('throws on invalid options', function (done) {
+    it('throws on invalid source', () => {
+
+        expect(() => Hoek.applyToDefaults({}, 'abc', { shallow: ['a'] })).to.throw('Invalid source value: must be true, falsy or an object');
+    });
 
-        expect(function () {
+    it('throws on missing keys', () => {
 
-            Hoek.applyToDefaultsWithShallow({}, 'abc', ['a']);
-        }).to.throw('Invalid options value: must be true, falsy or an object');
-        done();
+        expect(() => Hoek.applyToDefaults({}, true, { shallow: 123 })).to.throw('Invalid keys');
     });
 
-    it('throws on missing keys', function (done) {
+    it('handles array keys', () => {
 
-        expect(function () {
+        const sym = Symbol();
 
-            Hoek.applyToDefaultsWithShallow({}, true);
-        }).to.throw('Invalid keys');
-        done();
+        const defaults = {
+            a: {
+                b: 5,
+                e: 3
+            },
+            c: {
+                d: 7,
+                [sym]: {
+                    f: 9
+                }
+            }
+        };
+
+        const options = {
+            a: {
+                b: 4
+            },
+            c: {
+                d: 6,
+                [sym]: {
+                    g: 1
+                }
+            }
+        };
+
+        const merged = Hoek.applyToDefaults(defaults, options, { shallow: [['c', sym]] });
+        expect(merged).to.equal({ a: { b: 4, e: 3 }, c: { d: 6, [sym]: { g: 1 } } });
+        expect(merged.c[sym]).to.shallow.equal(options.c[sym]);
     });
 
-    it('throws on invalid keys', function (done) {
+    it('does not modify shallow entries in source', () => {
 
-        expect(function () {
+        const defaults = {
+            a: {
+                b: 5
+            }
+        };
+
+        const source = {};
+
+        Object.defineProperty(source, 'a', { value: { b: 4 } });
+
+        const merged = Hoek.applyToDefaults(defaults, source, { shallow: ['a'] });
+        expect(merged).to.equal({ a: { b: 4 } });
+        expect(merged.a).to.shallow.equal(source.a);
+        expect(merged.a).to.not.equal(defaults.a);
+    });
+
+    it('should respect nullOverride when shallow is used', () => {
+
+        const defaults = { host: 'localhost', port: 8000 };
+        const source = { host: null, port: 8080 };
 
-            Hoek.applyToDefaultsWithShallow({}, true, 'a');
-        }).to.throw('Invalid keys');
-        done();
+        const result = Hoek.applyToDefaults(defaults, source, { nullOverride: true, shallow: [] });
+        expect(result.host).to.equal(null);
+        expect(result.port).to.equal(8080);
     });
 });
 
-describe('deepEqual()', function () {
+describe('deepEqual()', () => {
+
+    it('compares identical references', () => {
+
+        const x = {};
+        expect(Hoek.deepEqual(x, x)).to.be.true();
+    });
 
-    it('compares simple values', function (done) {
+    it('compares simple values', () => {
 
         expect(Hoek.deepEqual('x', 'x')).to.be.true();
         expect(Hoek.deepEqual('x', 'y')).to.be.false();
@@ -1018,118 +880,550 @@
         expect(Hoek.deepEqual(-1, 1)).to.be.false();
         expect(Hoek.deepEqual(NaN, 0)).to.be.false();
         expect(Hoek.deepEqual(NaN, NaN)).to.be.true();
-        done();
     });
 
-    it('compares different types', function (done) {
+    it('compares different types', () => {
 
-        expect(Hoek.deepEqual([], 5)).to.be.false();
-        expect(Hoek.deepEqual(5, [])).to.be.false();
-        expect(Hoek.deepEqual({}, null)).to.be.false();
-        expect(Hoek.deepEqual(null, {})).to.be.false();
-        expect(Hoek.deepEqual('abc', {})).to.be.false();
-        expect(Hoek.deepEqual({}, 'abc')).to.be.false();
-        done();
+        expect(Hoek.deepEqual([], 5, { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual(5, [], { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual({}, null, { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual(null, {}, { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual('abc', {}, { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual({}, 'abc', { prototype: false })).to.be.false();
     });
 
-    it('compares empty structures', function (done) {
+    it('compares empty structures', () => {
 
         expect(Hoek.deepEqual([], [])).to.be.true();
         expect(Hoek.deepEqual({}, {})).to.be.true();
         expect(Hoek.deepEqual([], {})).to.be.false();
-        done();
+        expect(Hoek.deepEqual([], {}, { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual({}, [], { prototype: false })).to.be.false();
     });
 
-    it('compares empty arguments object', function (done) {
+    it('compares empty arguments object', () => {
 
-        var compare = function () {
+        const compare = function () {
 
-            expect(Hoek.deepEqual([], arguments)).to.be.false();
+            expect(Hoek.deepEqual([], arguments)).to.be.false();            // eslint-disable-line prefer-rest-params
         };
 
         compare();
-        done();
     });
 
-    it('compares empty arguments objects', function (done) {
+    it('compares empty arguments objects', () => {
 
-        var compare = function () {
+        const compare = function () {
 
-            var arg1 = arguments;
+            const arg1 = arguments;                                         // eslint-disable-line prefer-rest-params
 
-            var inner = function () {
+            const inner = function () {
 
-                expect(Hoek.deepEqual(arg1, arguments)).to.be.false(); // callee is not the same
+                // callee is not supported in strict mode, was previously false becuse callee was different
+                expect(Hoek.deepEqual(arg1, arguments)).to.be.true();       // eslint-disable-line prefer-rest-params
             };
 
             inner();
         };
 
         compare();
-        done();
     });
 
-    it('compares dates', function (done) {
+    it('compares symbol object properties', () => {
 
-        expect(Hoek.deepEqual(new Date(2015, 1, 1), new Date(2015, 1, 1))).to.be.true();
+        const sym = Symbol();
+
+        const ne = {};
+        Object.defineProperty(ne, sym, { value: true });
+
+        expect(Hoek.deepEqual({ [sym]: { c: true } }, { [sym]: { c: true } })).to.be.true();
+        expect(Hoek.deepEqual({ [sym]: { c: true } }, { [sym]: { c: false } })).to.be.false();
+        expect(Hoek.deepEqual({ [sym]: { c: true } }, { [sym]: true })).to.be.false();
+        expect(Hoek.deepEqual({ [sym]: undefined }, { [sym]: undefined })).to.be.true();
+        expect(Hoek.deepEqual({ [sym]: undefined }, {})).to.be.false();
+        expect(Hoek.deepEqual({}, { [sym]: undefined })).to.be.false();
+
+        expect(Hoek.deepEqual({}, ne)).to.be.true();
+        expect(Hoek.deepEqual(ne, {})).to.be.true();
+        expect(Hoek.deepEqual({ [sym]: true }, ne)).to.be.false();
+        expect(Hoek.deepEqual(ne, { [sym]: true })).to.be.false();
+        expect(Hoek.deepEqual(ne, { [Symbol()]: undefined })).to.be.false();
+
+        expect(Hoek.deepEqual({ [sym]: true }, { [sym]: true })).to.be.true();
+        expect(Hoek.deepEqual({ [sym]: true }, {})).to.be.false();
+        expect(Hoek.deepEqual({ [sym]: true }, {}, { symbols: false })).to.be.true();
+    });
+
+    it('compares dates', () => {
+
+        expect(Hoek.deepEqual(new Date(2015, 1, 1), new Date('2015/02/01'))).to.be.true();
         expect(Hoek.deepEqual(new Date(100), new Date(101))).to.be.false();
         expect(Hoek.deepEqual(new Date(), {})).to.be.false();
-        done();
+        expect(Hoek.deepEqual(new Date(2015, 1, 1), new Date('2015/02/01'), { prototype: false })).to.be.true();
+        expect(Hoek.deepEqual(new Date(), {}, { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual({}, new Date(), { prototype: false })).to.be.false();
     });
 
-    it('compares regular expressions', function (done) {
+    it('compares regular expressions', () => {
 
         expect(Hoek.deepEqual(/\s/, new RegExp('\\\s'))).to.be.true();
         expect(Hoek.deepEqual(/\s/g, /\s/g)).to.be.true();
-        expect(Hoek.deepEqual(/a/, {})).to.be.false();
+        expect(Hoek.deepEqual(/a/, {}, { prototype: false })).to.be.false();
         expect(Hoek.deepEqual(/\s/g, /\s/i)).to.be.false();
         expect(Hoek.deepEqual(/a/g, /b/g)).to.be.false();
-        done();
     });
 
-    it('compares arrays', function (done) {
+    it('compares errors', () => {
+
+        expect(Hoek.deepEqual(new Error('a'), new Error('a'))).to.be.true();
+        expect(Hoek.deepEqual(new Error('a'), new Error('b'))).to.be.false();
+
+        expect(Hoek.deepEqual(new Error('a'), new TypeError('a'))).to.be.false();
+        expect(Hoek.deepEqual(new Error('a'), new TypeError('a'), { prototype: false })).to.be.false();
+
+        expect(Hoek.deepEqual(new Error(), {})).to.be.false();
+        expect(Hoek.deepEqual(new Error(), {}, { prototype: false })).to.be.false();
+
+        expect(Hoek.deepEqual({}, new Error())).to.be.false();
+        expect(Hoek.deepEqual({}, new Error(), { prototype: false })).to.be.false();
+
+        const error = new Error('a');
+        expect(Hoek.deepEqual(Hoek.clone(error), error)).to.be.true();
+        expect(Hoek.deepEqual(Hoek.clone(error), error, { prototype: false })).to.be.true();
+    });
+
+    it('compares arrays', () => {
 
         expect(Hoek.deepEqual([[1]], [[1]])).to.be.true();
         expect(Hoek.deepEqual([1, 2, 3], [1, 2, 3])).to.be.true();
         expect(Hoek.deepEqual([1, 2, 3], [1, 3, 2])).to.be.false();
         expect(Hoek.deepEqual([1, 2, 3], [1, 2])).to.be.false();
         expect(Hoek.deepEqual([1], [1])).to.be.true();
-        done();
+        const item1 = { key: 'value1' };
+        const item2 = { key: 'value2' };
+        expect(Hoek.deepEqual([item1, item1], [item1, item2])).to.be.false();
+    });
+
+    it('compares sets', () => {
+
+        expect(Hoek.deepEqual(new Set(), new Set())).to.be.true();
+        expect(Hoek.deepEqual(new Set([1]), new Set([1]))).to.be.true();
+        expect(Hoek.deepEqual(new Set([]), new Set([]))).to.be.true();
+        expect(Hoek.deepEqual(new Set([1, 2, 3]), new Set([1, 2, 3]))).to.be.true();
+        expect(Hoek.deepEqual(new Set([1, 2, 3]), new Set([3, 2, 1]))).to.be.true();
+        expect(Hoek.deepEqual(new Set([1, 2, 3]), new Set([1, 2, 4]))).to.be.false();
+        expect(Hoek.deepEqual(new Set([1, 2, 3]), new Set([1, 2]))).to.be.false();
+        expect(Hoek.deepEqual(new Set([1, 2, 1]), new Set([1, 2]))).to.be.true();
+        expect(Hoek.deepEqual(new Set([+0]), new Set([-0]))).to.be.true();
+        expect(Hoek.deepEqual(new Set([NaN]), new Set([NaN]))).to.be.true();
+        expect(Hoek.deepEqual(new Set([1, {}]), new Set([1, {}]))).to.be.true();
+        expect(Hoek.deepEqual(new Set([1, {}]), new Set([{}, 1]))).to.be.true();
+        expect(Hoek.deepEqual(new Set([1, {}, {}]), new Set([{}, 1, {}]))).to.be.true();
+        expect(Hoek.deepEqual(new Set([1, { a: 1 }]), new Set([{ a: 0 }, 1]))).to.be.false();
+        expect(Hoek.deepEqual(new WeakSet(), new WeakSet())).to.be.true();
+        const obj = {};
+        expect(Hoek.deepEqual(new WeakSet([obj]), new WeakSet())).to.be.true();
+        expect(Hoek.deepEqual(new WeakSet(), new Set()), { prototype: false }).to.be.false();
+
+        const sets = [new Set(), new Set()].map((set) => {
+
+            set.modified = true;
+            return set;
+        });
+        expect(Hoek.deepEqual(sets[0], sets[1])).to.be.true();
+        expect(Hoek.deepEqual(sets[0], new Set())).to.be.false();
+    });
+
+    it('compares extended sets', () => {
+
+        class PrivateSet extends Set {
+
+            has() {
+
+                throw new Error('not allowed');
+            }
+        }
+
+        const entries = ['a', undefined];
+        expect(Hoek.deepEqual(new PrivateSet(), new PrivateSet())).to.be.true();
+        expect(Hoek.deepEqual(new PrivateSet(entries), new PrivateSet(entries))).to.be.true();
+        expect(Hoek.deepEqual(new PrivateSet(entries), new Set(entries), { prototype: false })).to.be.true();
+        expect(Hoek.deepEqual(new PrivateSet(entries), new Set(entries), { prototype: true })).to.be.false();
+        expect(Hoek.deepEqual(new PrivateSet(), new PrivateSet(entries))).to.be.false();
+        expect(Hoek.deepEqual(new PrivateSet(entries), new PrivateSet())).to.be.false();
+
+        class LockableSet extends Set {
+
+            constructor(values, locked = true) {
+
+                super(values);
+                this.locked = locked;
+            }
+
+            has() {
+
+                if (this.locked) {
+                    throw new Error('not allowed');
+                }
+            }
+        }
+
+        expect(Hoek.deepEqual(new LockableSet(), new LockableSet())).to.be.true();
+        expect(Hoek.deepEqual(new LockableSet(entries), new LockableSet(entries))).to.be.true();
+        expect(Hoek.deepEqual(new LockableSet(entries, false), new LockableSet(entries, false))).to.be.true();
+        expect(Hoek.deepEqual(new LockableSet(entries, true), new LockableSet(entries, false))).to.be.false();
+        expect(Hoek.deepEqual(new LockableSet(entries, false), new LockableSet(entries, true))).to.be.false();
+        expect(Hoek.deepEqual(new LockableSet(entries), new Set(entries), { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual(new LockableSet(entries), new PrivateSet(entries), { prototype: false })).to.be.false();
+    });
+
+    it('compares maps', () => {
+
+        const item1 = { key: 'value1' };
+        const item2 = { key: 'value2' };
+        expect(Hoek.deepEqual(new Map(), new Map())).to.be.true();
+        expect(Hoek.deepEqual(new Map([[1, {}]]), new Map([[1, {}]]))).to.be.true();
+        expect(Hoek.deepEqual(new Map([[1, item1]]), new Map([[1, item1]]))).to.be.true();
+        expect(Hoek.deepEqual(new Map([[1, item1]]), new Map([[1, item2]]))).to.be.false();
+        expect(Hoek.deepEqual(new Map([[1, undefined]]), new Map([[1, undefined]]))).to.be.true();
+        expect(Hoek.deepEqual(new Map([[1, undefined]]), new Map([[2, undefined]]))).to.be.false();
+        expect(Hoek.deepEqual(new Map([[1, {}]]), new Map([[1, {}], [2, {}]]))).to.be.false();
+        expect(Hoek.deepEqual(new Map([[item1, 1]]), new Map([[item1, 1]]))).to.be.true();
+        expect(Hoek.deepEqual(new Map([[{}, 1]]), new Map([[{}, 1]]))).to.be.false();
+        expect(Hoek.deepEqual(new WeakMap(), new WeakMap())).to.be.true();
+        expect(Hoek.deepEqual(new WeakMap([[item1, 1]]), new WeakMap())).to.be.true();
+        expect(Hoek.deepEqual(new WeakMap(), new Map()), { prototype: false }).to.be.false();
+
+        const maps = [new Map(), new Map()].map((map) => {
+
+            map.modified = true;
+            return map;
+        });
+        expect(Hoek.deepEqual(maps[0], maps[1])).to.be.true();
+        expect(Hoek.deepEqual(maps[0], new Map())).to.be.false();
+    });
+
+    it('compares extended maps', () => {
+
+        class PrivateMap extends Map {
+
+            get() {
+
+                throw new Error('not allowed');
+            }
+        }
+
+        const entries = [['a', 1], ['b', undefined]];
+        expect(Hoek.deepEqual(new PrivateMap(), new PrivateMap())).to.be.true();
+        expect(Hoek.deepEqual(new PrivateMap(entries), new PrivateMap(entries))).to.be.true();
+        expect(Hoek.deepEqual(new PrivateMap(entries), new Map(entries), { prototype: false })).to.be.true();
+        expect(Hoek.deepEqual(new PrivateMap(entries), new Map(entries), { prototype: true })).to.be.false();
+        expect(Hoek.deepEqual(new PrivateMap(), new PrivateMap(entries))).to.be.false();
+        expect(Hoek.deepEqual(new PrivateMap(entries), new PrivateMap())).to.be.false();
+
+        class LockableMap extends Map {
+
+            constructor(kvs, locked = true) {
+
+                super(kvs);
+                this.locked = locked;
+            }
+
+            get() {
+
+                if (this.locked) {
+                    throw new Error('not allowed');
+                }
+            }
+        }
+
+        expect(Hoek.deepEqual(new LockableMap(), new LockableMap())).to.be.true();
+        expect(Hoek.deepEqual(new LockableMap(entries), new LockableMap(entries))).to.be.true();
+        expect(Hoek.deepEqual(new LockableMap(entries, false), new LockableMap(entries, false))).to.be.true();
+        expect(Hoek.deepEqual(new LockableMap(entries, true), new LockableMap(entries, false))).to.be.false();
+        expect(Hoek.deepEqual(new LockableMap(entries, false), new LockableMap(entries, true))).to.be.false();
+        expect(Hoek.deepEqual(new LockableMap(entries), new Map(entries), { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual(new LockableMap(entries), new PrivateMap(entries), { prototype: false })).to.be.false();
+    });
+
+    it('compares promises', () => {
+
+        const a = new Promise(() => { });
+
+        expect(Hoek.deepEqual(a, a)).to.be.true();
+        expect(Hoek.deepEqual(a, new Promise(() => { }))).to.be.false();
+    });
+
+    it('compares buffers', () => {
+
+        expect(Hoek.deepEqual(Buffer.from([1, 2, 3]), Buffer.from([1, 2, 3]))).to.be.true();
+        expect(Hoek.deepEqual(Buffer.from([1, 2, 3]), Buffer.from([1, 3, 2]))).to.be.false();
+        expect(Hoek.deepEqual(Buffer.from([1, 2, 3]), Buffer.from([1, 2]))).to.be.false();
+        expect(Hoek.deepEqual(Buffer.from([1, 2, 3]), {})).to.be.false();
+        expect(Hoek.deepEqual(Buffer.from([1, 2, 3]), [1, 2, 3])).to.be.false();
+    });
+
+    it('compares string objects', () => {
+
+        /* eslint-disable no-new-wrappers */
+        expect(Hoek.deepEqual(new String('a'), new String('a'))).to.be.true();
+        expect(Hoek.deepEqual(new String('a'), new String('b'))).to.be.false();
+        expect(Hoek.deepEqual(new String(''), {}, { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual({}, new String(''), { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual(new String('a'), 'a', { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual('a', new String('a'), { prototype: false })).to.be.false();
+        /* eslint-enable no-new-wrappers */
+    });
+
+    it('compares number objects', () => {
+
+        /* eslint-disable no-new-wrappers */
+        expect(Hoek.deepEqual(new Number(1), new Number(1))).to.be.true();
+        expect(Hoek.deepEqual(new Number(1), new Number(2))).to.be.false();
+        expect(Hoek.deepEqual(new Number(+0), new Number(-0))).to.be.false();
+        expect(Hoek.deepEqual(new Number(NaN), new Number(NaN))).to.be.true();
+        expect(Hoek.deepEqual(new Number(0), {}, { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual({}, new Number(0), { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual(new Number(1), 1, { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual(1, new Number(1), { prototype: false })).to.be.false();
+        /* eslint-enable no-new-wrappers */
     });
 
-    it('compares buffers', function (done) {
+    it('compares boolean objects', () => {
 
-        expect(Hoek.deepEqual(new Buffer([1, 2, 3]), new Buffer([1, 2, 3]))).to.be.true();
-        expect(Hoek.deepEqual(new Buffer([1, 2, 3]), new Buffer([1, 3, 2]))).to.be.false();
-        expect(Hoek.deepEqual(new Buffer([1, 2, 3]), new Buffer([1, 2]))).to.be.false();
-        expect(Hoek.deepEqual(new Buffer([1, 2, 3]), {})).to.be.false();
-        expect(Hoek.deepEqual(new Buffer([1, 2, 3]), [1, 2, 3])).to.be.false();
-        done();
+        /* eslint-disable no-new-wrappers */
+        expect(Hoek.deepEqual(new Boolean(true), new Boolean(true))).to.be.true();
+        expect(Hoek.deepEqual(new Boolean(true), new Boolean(false))).to.be.false();
+        expect(Hoek.deepEqual(new Boolean(false), {}, { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual({}, new Boolean(false), { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual(new Boolean(true), true, { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual(true, new Boolean(true), { prototype: false })).to.be.false();
+        /* eslint-enable no-new-wrappers */
     });
 
-    it('compares objects', function (done) {
+    it('compares objects', () => {
 
         expect(Hoek.deepEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 3 })).to.be.true();
         expect(Hoek.deepEqual({ foo: 'bar' }, { foo: 'baz' })).to.be.false();
         expect(Hoek.deepEqual({ foo: { bar: 'foo' } }, { foo: { bar: 'baz' } })).to.be.false();
-        done();
+        expect(Hoek.deepEqual({ foo: undefined }, {})).to.be.false();
+        expect(Hoek.deepEqual({}, { foo: undefined })).to.be.false();
+        expect(Hoek.deepEqual({ foo: undefined }, { bar: undefined })).to.be.false();
+    });
+
+    it('compares functions', () => {
+
+        const f1 = () => 1;
+        const f2 = () => 2;
+        const f2a = () => 2;
+
+        expect(Hoek.deepEqual({ f1 }, { f1 })).to.be.true();
+        expect(Hoek.deepEqual({ f1 }, { f1: f2 })).to.be.false();
+        expect(Hoek.deepEqual({ f2 }, { f2: f2a })).to.be.false();
+        expect(Hoek.deepEqual({ f2 }, { f2: f2a }, { deepFunction: true })).to.be.true();
+        expect(Hoek.deepEqual({ f2 }, { f2: f1 }, { deepFunction: true })).to.be.false();
+
+        const f3 = () => 3;
+        f3.x = 1;
+
+        const f3a = () => 3;
+        f3a.x = 1;
+
+        const f3b = () => 3;
+        f3b.x = 2;
+
+        expect(Hoek.deepEqual({ f3 }, { f3: f3a }, { deepFunction: true })).to.be.true();
+        expect(Hoek.deepEqual({ f3 }, { f3: f3b }, { deepFunction: true })).to.be.false();
+    });
+
+    it('skips keys', () => {
+
+        expect(Hoek.deepEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 4 })).to.be.false();
+        expect(Hoek.deepEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 4 }, { skip: ['c'] })).to.be.true();
+
+        expect(Hoek.deepEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2 })).to.be.false();
+        expect(Hoek.deepEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2 }, { skip: ['c'] })).to.be.true();
+
+        const sym = Symbol('test');
+        expect(Hoek.deepEqual({ a: 1, b: 2, [sym]: 3 }, { a: 1, b: 2, [sym]: 4 })).to.be.false();
+        expect(Hoek.deepEqual({ a: 1, b: 2, [sym]: 3 }, { a: 1, b: 2, [sym]: 4 }, { skip: [sym] })).to.be.true();
+
+        expect(Hoek.deepEqual({ a: 1, b: 2, [sym]: 3 }, { a: 1, b: 2 })).to.be.false();
+        expect(Hoek.deepEqual({ a: 1, b: 2, [sym]: 3 }, { a: 1, b: 2 }, { skip: [sym] })).to.be.true();
+        expect(Hoek.deepEqual({ a: 1, b: 2, [sym]: 3, [Symbol('other')]: true }, { a: 1, b: 2 }, { skip: [sym] })).to.be.false();
+
+        expect(Hoek.deepEqual({ a: 1, b: 2 }, { a: 1 }, { skip: ['a'] })).to.be.false();
+        expect(Hoek.deepEqual({ a: 1 }, { a: 1, b: 2 }, { skip: ['a'] })).to.be.false();
+    });
+
+    it('handles circular dependency', () => {
+
+        const a = {};
+        a.x = a;
+
+        const b = Hoek.clone(a);
+        expect(Hoek.deepEqual(a, b)).to.be.true();
+    });
+
+    it('handles obj only circular dependency', () => {
+
+        const a = {};
+        a.x = a;
+
+        const b = { x: {} };
+        expect(Hoek.deepEqual(a, b)).to.be.false();
+        expect(Hoek.deepEqual(b, a)).to.be.false();
     });
 
-    it('handles circular dependency', function (done) {
+    it('handles irregular circular dependency', () => {
 
-        var a = {};
+        const a = {};
         a.x = a;
 
-        var b = Hoek.clone(a);
+        const b = { x: {} };
+        b.x.x = b;
+
+        const c = { x: { x: {} } };
+        c.x.x.x = c;
         expect(Hoek.deepEqual(a, b)).to.be.true();
-        done();
+        expect(Hoek.deepEqual(b, a)).to.be.true();
+        expect(Hoek.deepEqual(a, c)).to.be.true();
+        expect(Hoek.deepEqual(b, c)).to.be.true();
+        expect(Hoek.deepEqual(c, a)).to.be.true();
+        expect(Hoek.deepEqual(c, b)).to.be.true();
+        b.x.y = 1;
+        expect(Hoek.deepEqual(a, b)).to.be.false();
+        expect(Hoek.deepEqual(b, a)).to.be.false();
+    });
+
+    it('handles cross circular dependency', () => {
+
+        const a = {};
+        const b = { x: {}, y: a };
+        b.x.x = b;
+        b.x.y = b.x;
+        a.x = b;
+        a.y = a;
+        expect(Hoek.deepEqual(b, a)).to.be.true();
+        expect(Hoek.deepEqual(a, b)).to.be.true();
+        b.x.y = 1;
+        expect(Hoek.deepEqual(b, a)).to.be.false();
+        expect(Hoek.deepEqual(a, b)).to.be.false();
     });
 
-    it('compares an object with property getter without executing it', function (done) {
+    it('handles reuse of objects', () => {
+
+        const date1 = { year: 2018, month: 1, day: 1 };
+        const date2 = { year: 2000, month: 1, day: 1 };
+
+        expect(Hoek.deepEqual({ start: date1, end: date1 }, { start: date1, end: date2 })).to.be.false();
+    });
+
+    it('handles valueOf() that throws', () => {
+
+        const throwing = class {
+
+            constructor(value) {
+
+                this.value = value;
+            }
 
-        var obj = {};
-        var value = 1;
-        var execCount = 0;
+            valueOf() {
+
+                throw new Error('failed');
+            }
+        };
+
+        expect(Hoek.deepEqual(new throwing('a'), new throwing('a'))).to.be.true();
+        expect(Hoek.deepEqual(new throwing('a'), new throwing('b'))).to.be.false();
+        expect(Hoek.deepEqual(new throwing('a'), { value: 'a' }, { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual({ value: 'a' }, new throwing('a'), { prototype: false })).to.be.false();
+    });
+
+    it('handles valueOf() that returns similar value', () => {
+
+        const identity = class {
+
+            constructor(value) {
+
+                this.value = value;
+            }
+
+            valueOf() {
+
+                return { value: this.value };
+            }
+        };
+
+        expect(Hoek.deepEqual(new identity('a'), new identity('a'))).to.be.true();
+        expect(Hoek.deepEqual(new identity('a'), new identity('b'))).to.be.false();
+        expect(Hoek.deepEqual(new identity('a'), { value: 'a' }, { prototype: true })).to.be.false();
+        expect(Hoek.deepEqual(new identity('a'), { value: 'a' }, { prototype: false })).to.be.true();
+        expect(Hoek.deepEqual({ value: 'a' }, new identity('a'), { prototype: true })).to.be.false();
+        expect(Hoek.deepEqual({ value: 'a' }, new identity('a'), { prototype: false })).to.be.true();
+    });
+
+    it('skips enumerable properties on prototype chain', () => {
+
+        const base = function (value, surprice) {
+
+            this.value = value;
+            if (surprice) {
+                this.surprice = surprice;
+            }
+        };
+
+        Object.defineProperty(base.prototype, 'enum', {
+            enumerable: true,
+            configurable: true,
+            value: true
+        });
+
+        expect('enum' in new base('a')).to.be.true();
+        expect(Hoek.deepEqual(new base('a'), new base('a'))).to.be.true();
+        expect(Hoek.deepEqual(new base('a'), new base('b'))).to.be.false();
+        expect(Hoek.deepEqual(new base('a'), { value: 'a' }, { prototype: false })).to.be.true();
+        expect(Hoek.deepEqual({ value: 'a' }, new base('a'), { prototype: false })).to.be.true();
+        expect(Hoek.deepEqual(new base('a', 1), { value: 'a', enum: true }, { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual({ value: 'a', enum: true }, new base('a', 1), { prototype: false })).to.be.false();
+    });
+
+    it('skips non-enumerable properties', () => {
+
+        const base = function Base(value, surprice) {
+
+            this.value = value;
+            if (surprice) {
+                this.surprice = surprice;
+            }
+        };
+
+        const createObj = (...args) => {
+
+            const obj = new base(...args);
+
+            Object.defineProperty(obj, 'hidden', {
+                enumerable: false,
+                configurable: true,
+                value: true
+            });
+
+            return obj;
+        };
+
+        expect(Hoek.deepEqual(createObj('a'), createObj('a'))).to.be.true();
+        expect(Hoek.deepEqual(createObj('a'), createObj('b'))).to.be.false();
+        expect(Hoek.deepEqual(createObj('a'), { value: 'a' }, { prototype: false })).to.be.true();
+        expect(Hoek.deepEqual({ value: 'a' }, createObj('a'), { prototype: false })).to.be.true();
+        expect(Hoek.deepEqual(createObj('a', 1), { value: 'a', hidden: true }, { prototype: false })).to.be.false();
+        expect(Hoek.deepEqual({ value: 'a', hidden: true }, createObj('a', 1), { prototype: false })).to.be.false();
+    });
+
+    it('compares an object with property getter while executing it', () => {
+
+        const obj = {};
+        const value = 1;
+        let execCount = 0;
 
         Object.defineProperty(obj, 'test', {
             enumerable: true,
@@ -1141,17 +1435,16 @@
             }
         });
 
-        var copy = Hoek.clone(obj);
+        const copy = Hoek.clone(obj);
         expect(Hoek.deepEqual(obj, copy)).to.be.true();
-        expect(execCount).to.equal(0);
+        expect(execCount).to.equal(2);
         expect(copy.test).to.equal(1);
-        expect(execCount).to.equal(1);
-        done();
+        expect(execCount).to.equal(3);
     });
 
-    it('compares objects with property getters', function (done) {
+    it('compares objects with property getters', () => {
 
-        var obj = {};
+        const obj = {};
         Object.defineProperty(obj, 'test', {
             enumerable: true,
             configurable: true,
@@ -1161,7 +1454,7 @@
             }
         });
 
-        var ref = {};
+        const ref = {};
         Object.defineProperty(ref, 'test', {
             enumerable: true,
             configurable: true,
@@ -1172,12 +1465,11 @@
         });
 
         expect(Hoek.deepEqual(obj, ref)).to.be.false();
-        done();
     });
 
-    it('compares object prototypes', function (done) {
+    it('compares object prototypes', () => {
 
-        var Obj = function () {
+        const Obj = function () {
 
             this.a = 5;
         };
@@ -1187,7 +1479,7 @@
             return this.a;
         };
 
-        var Ref = function () {
+        const Ref = function () {
 
             this.a = 5;
         };
@@ -1200,151 +1492,125 @@
         expect(Hoek.deepEqual(new Obj(), new Ref())).to.be.false();
         expect(Hoek.deepEqual(new Obj(), new Obj())).to.be.true();
         expect(Hoek.deepEqual(new Ref(), new Ref())).to.be.true();
-        done();
     });
 
-    it('compares plain objects', function (done) {
+    it('compares plain objects', () => {
 
-        var a = Object.create(null);
-        var b = Object.create(null);
+        const a = Object.create(null);
+        const b = Object.create(null);
 
         a.b = 'c';
         b.b = 'c';
 
         expect(Hoek.deepEqual(a, b)).to.be.true();
         expect(Hoek.deepEqual(a, { b: 'c' })).to.be.false();
-        done();
     });
 
-    it('compares an object with an empty object', function (done) {
+    it('compares an object with an empty object', () => {
 
-        var a = { a: 1, b: 2 };
+        const a = { a: 1, b: 2 };
 
         expect(Hoek.deepEqual({}, a)).to.be.false();
         expect(Hoek.deepEqual(a, {})).to.be.false();
-        done();
     });
 
-    it('compares an object ignoring the prototype', function (done) {
+    it('compares an object ignoring the prototype', () => {
 
-        var a = Object.create(null);
-        var b = {};
+        const a = Object.create(null);
+        const b = {};
 
         expect(Hoek.deepEqual(a, b, { prototype: false })).to.be.true();
-        done();
     });
 
-    it('compares an object ignoring the prototype recursively', function (done) {
+    it('compares an object ignoring the prototype recursively', () => {
 
-        var a = [Object.create(null)];
-        var b = [{}];
+        const a = [Object.create(null)];
+        const b = [{}];
 
         expect(Hoek.deepEqual(a, b, { prototype: false })).to.be.true();
-        done();
-    });
-});
-
-describe('unique()', function () {
-
-    it('ensures uniqueness within array of objects based on subkey', function (done) {
-
-        var a = Hoek.unique(dupsArray, 'x');
-        expect(a).to.deep.equal(reducedDupsArray);
-        done();
-    });
-
-    it('removes duplicated without key', function (done) {
-
-        expect(Hoek.unique([1, 2, 3, 4, 2, 1, 5])).to.deep.equal([1, 2, 3, 4, 5]);
-        done();
     });
 });
 
-describe('mapToObject()', function () {
+describe('intersect()', () => {
 
-    it('returns null on null array', function (done) {
+    it('returns the common objects of two arrays', () => {
 
-        var a = Hoek.mapToObject(null);
-        expect(a).to.equal(null);
-        done();
+        const array1 = [1, 2, 3, 4, 4, 5, 5];
+        const array2 = [5, 4, 5, 6, 7];
+        const common = Hoek.intersect(array1, array2);
+        expect(common).to.equal([5, 4]);
     });
 
-    it('converts basic array to existential object', function (done) {
+    it('returns the common objects of array and set', () => {
 
-        var keys = [1, 2, 3, 4];
-        var a = Hoek.mapToObject(keys);
-        for (var i in keys) {
-            expect(a[keys[i]]).to.equal(true);
-        }
-        done();
+        const array1 = new Set([1, 2, 3, 4, 4, 5, 5]);
+        const array2 = [5, 4, 5, 6, 7];
+        const common = Hoek.intersect(array1, array2);
+        expect(common).to.equal([5, 4]);
     });
 
-    it('converts array of objects to existential object', function (done) {
+    it('returns the common objects of set and array', () => {
 
-        var keys = [{ x: 1 }, { x: 2 }, { x: 3 }, { y: 4 }];
-        var subkey = 'x';
-        var a = Hoek.mapToObject(keys, subkey);
-        expect(a).to.deep.equal({ 1: true, 2: true, 3: true });
-        done();
+        const array1 = [1, 2, 3, 4, 4, 5, 5];
+        const array2 = new Set([5, 4, 5, 6, 7]);
+        const common = Hoek.intersect(array1, array2);
+        expect(common).to.equal([5, 4]);
     });
-});
 
-describe('intersect()', function () {
+    it('returns the common objects of two sets', () => {
 
-    it('returns the common objects of two arrays', function (done) {
-
-        var array1 = [1, 2, 3, 4, 4, 5, 5];
-        var array2 = [5, 4, 5, 6, 7];
-        var common = Hoek.intersect(array1, array2);
-        expect(common.length).to.equal(2);
-        done();
+        const array1 = new Set([1, 2, 3, 4, 4, 5, 5]);
+        const array2 = new Set([5, 4, 5, 6, 7]);
+        const common = Hoek.intersect(array1, array2);
+        expect(common).to.equal([5, 4]);
     });
 
-    it('returns just the first common object of two arrays', function (done) {
+    it('returns just the first common object of two arrays', () => {
 
-        var array1 = [1, 2, 3, 4, 4, 5, 5];
-        var array2 = [5, 4, 5, 6, 7];
-        var common = Hoek.intersect(array1, array2, true);
+        const array1 = [1, 2, 3, 4, 4, 5, 5];
+        const array2 = [5, 4, 5, 6, 7];
+        const common = Hoek.intersect(array1, array2, { first: true });
         expect(common).to.equal(5);
-        done();
     });
 
-    it('returns null when no common and returning just the first common object of two arrays', function (done) {
+    it('returns null when no common and returning just the first common object of two arrays', () => {
 
-        var array1 = [1, 2, 3, 4, 4, 5, 5];
-        var array2 = [6, 7];
-        var common = Hoek.intersect(array1, array2, true);
+        const array1 = [1, 2, 3, 4, 4, 5, 5];
+        const array2 = [6, 7];
+        const common = Hoek.intersect(array1, array2, { first: true });
         expect(common).to.equal(null);
-        done();
     });
 
-    it('returns an empty array if either input is null', function (done) {
+    it('returns an empty array if either input is null', () => {
 
         expect(Hoek.intersect([1], null).length).to.equal(0);
         expect(Hoek.intersect(null, [1]).length).to.equal(0);
-        done();
+        expect(Hoek.intersect(null, [1], { first: true })).to.be.null();
     });
 
-    it('returns the common objects of object and array', function (done) {
+    it('returns the common objects of object and array', () => {
 
-        var array1 = [1, 2, 3, 4, 4, 5, 5];
-        var array2 = [5, 4, 5, 6, 7];
-        var common = Hoek.intersect(Hoek.mapToObject(array1), array2);
+        const array1 = { 1: true, 2: true, 3: true, 4: true, 5: true };
+        const array2 = [5, 4, 5, 6, 7];
+        const common = Hoek.intersect(array1, array2);
         expect(common.length).to.equal(2);
-        done();
     });
 });
 
-describe('contain()', function () {
+describe('contain()', () => {
 
-    it('tests strings', function (done) {
+    it('tests strings', () => {
 
         expect(Hoek.contain('abc', 'ab')).to.be.true();
         expect(Hoek.contain('abc', 'abc', { only: true })).to.be.true();
         expect(Hoek.contain('aaa', 'a', { only: true })).to.be.true();
+        expect(Hoek.contain('aaa', 'a', { only: true, once: true })).to.be.false();
         expect(Hoek.contain('abc', 'b', { once: true })).to.be.true();
         expect(Hoek.contain('abc', ['a', 'c'])).to.be.true();
         expect(Hoek.contain('abc', ['a', 'd'], { part: true })).to.be.true();
+        expect(Hoek.contain('aaa', ['a', 'a'], { only: true, once: true })).to.be.false();
+        expect(Hoek.contain('aaa', ['a', 'a'], { only: true })).to.be.true();
+        expect(Hoek.contain('aaa', ['a', 'a', 'a'], { only: true, once: true })).to.be.true();
 
         expect(Hoek.contain('abc', 'ac')).to.be.false();
         expect(Hoek.contain('abcd', 'abc', { only: true })).to.be.false();
@@ -1352,10 +1618,33 @@
         expect(Hoek.contain('abb', 'b', { once: true })).to.be.false();
         expect(Hoek.contain('abc', ['a', 'd'])).to.be.false();
         expect(Hoek.contain('abc', ['ab', 'bc'])).to.be.false();                      // Overlapping values not supported
-        done();
+
+        expect(Hoek.contain('', 'a')).to.be.false();
+        expect(Hoek.contain('', 'a', { only: true })).to.be.false();
+
+        expect(Hoek.contain('', '')).to.be.true();
+        expect(Hoek.contain('', ''), { only: true }).to.be.true();
+        expect(Hoek.contain('', ''), { once: true }).to.be.true();
+        expect(Hoek.contain('', ['', ''])).to.be.true();
+        expect(Hoek.contain('', ['', ''], { only: true })).to.be.true();
+        expect(Hoek.contain('', ['', ''], { once: true })).to.be.false();
+
+        expect(Hoek.contain('a', '')).to.be.true();
+        expect(Hoek.contain('a', '', { only: true })).to.be.false();
+        expect(Hoek.contain('a', '', { once: true })).to.be.false();
+        expect(Hoek.contain('a', ['', ''])).to.be.true();
+        expect(Hoek.contain('a', ['', ''], { only: true })).to.be.false();
+        expect(Hoek.contain('a', ['', ''], { once: true })).to.be.false();
+
+        expect(Hoek.contain('ab', ['a', 'b', 'c'])).to.be.false();
+        expect(Hoek.contain('ab', ['a', 'b', 'c'], { only: true })).to.be.false();
+        expect(Hoek.contain('ab', ['a', 'b', 'c'], { only: true, once: true })).to.be.false();
+
+        expect(Hoek.contain('ab', ['c'], { part: true })).to.be.false();
+        expect(Hoek.contain('ab', ['b'], { part: true })).to.be.true();
     });
 
-    it('tests arrays', function (done) {
+    it('tests arrays', () => {
 
         expect(Hoek.contain([1, 2, 3], 1)).to.be.true();
         expect(Hoek.contain([{ a: 1 }], { a: 1 }, { deep: true })).to.be.true();
@@ -1364,22 +1653,49 @@
         expect(Hoek.contain([1, 1, 2], [1, 2], { only: true })).to.be.true();
         expect(Hoek.contain([1, 2], [1, 2], { once: true })).to.be.true();
         expect(Hoek.contain([1, 2, 3], [1, 4], { part: true })).to.be.true();
+        expect(Hoek.contain([null, 2, 3], [null, 4], { part: true })).to.be.true();
+        expect(Hoek.contain([null], null, { deep: true })).to.be.true();
         expect(Hoek.contain([[1], [2]], [[1]], { deep: true })).to.be.true();
+        expect(Hoek.contain([[1], [2], 3], [[1]], { deep: true })).to.be.true();
+        expect(Hoek.contain([[1, 2]], [[1]], { deep: true, part: true })).to.be.true();
+        expect(Hoek.contain([[1, 2]], [[1], 2], { deep: true, part: true })).to.be.true();
+        expect(Hoek.contain([1, 2, 1], [1, 1, 2], { only: true })).to.be.true();
+        expect(Hoek.contain([1, 2, 1], [1, 1, 2], { only: true, once: true })).to.be.true();
+        expect(Hoek.contain([1, 2, 1], [1, 2, 2], { only: true })).to.be.false();
+        expect(Hoek.contain([1, 2, 1], [1, 2, 2], { only: true, part: true })).to.be.true();
+        expect(Hoek.contain([1, 1, 1], [1, 1, 1, 1])).to.be.false();
+        expect(Hoek.contain([1, 1, 1], [1, 1, 1, 1], { part: true })).to.be.true();
 
         expect(Hoek.contain([1, 2, 3], 4)).to.be.false();
         expect(Hoek.contain([{ a: 1 }], { a: 2 }, { deep: true })).to.be.false();
+        expect(Hoek.contain([{ a: 1 }, { a: 1 }], [{ a: 1 }, { a: 1 }], { deep: true, once: true, only: true })).to.be.true();
+        expect(Hoek.contain([{ a: 1 }, { a: 1 }], [{ a: 1 }, { a: 2 }], { deep: true, once: true, only: true })).to.be.false();
         expect(Hoek.contain([{ a: 1 }], { a: 1 })).to.be.false();
         expect(Hoek.contain([1, 2, 3], [4, 5])).to.be.false();
         expect(Hoek.contain([[3], [2]], [[1]])).to.be.false();
         expect(Hoek.contain([[1], [2]], [[1]])).to.be.false();
+        expect(Hoek.contain([[1, 2]], [[1]], { deep: true })).to.be.false();
         expect(Hoek.contain([{ a: 1 }], [{ a: 2 }], { deep: true })).to.be.false();
         expect(Hoek.contain([1, 3, 2], [1, 2], { only: true })).to.be.false();
         expect(Hoek.contain([1, 2, 2], [1, 2], { once: true })).to.be.false();
         expect(Hoek.contain([0, 2, 3], [1, 4], { part: true })).to.be.false();
-        done();
+        expect(Hoek.contain([1, 2, 1], [1, 2, 2], { only: true, once: true })).to.be.false();
+        expect(Hoek.contain([1, 2, 1], [1, 2], { only: true, once: true })).to.be.false();
+
+        expect(Hoek.contain([], 1)).to.be.false();
+        expect(Hoek.contain([], 1, { only: true })).to.be.false();
+
+        expect(Hoek.contain(['a', 'b'], ['a', 'b', 'c'])).to.be.false();
+        expect(Hoek.contain(['a', 'b'], ['a', 'b', 'c'], { only: true })).to.be.false();
+        expect(Hoek.contain(['a', 'b'], ['a', 'b', 'c'], { only: true, once: true })).to.be.false();
+
+        expect(Hoek.contain(['a', 'b'], ['c'], { part: true })).to.be.false();
+        expect(Hoek.contain(['a', 'b'], ['b'], { part: true })).to.be.true();
+
+        expect(Hoek.contain([{ a: 1 }], [1], { deep: true })).to.be.false();
     });
 
-    it('tests objects', function (done) {
+    it('tests objects', () => {
 
         expect(Hoek.contain({ a: 1, b: 2, c: 3 }, 'a')).to.be.true();
         expect(Hoek.contain({ a: 1, b: 2, c: 3 }, ['a', 'c'])).to.be.true();
@@ -1389,11 +1705,12 @@
         expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, d: 4 }, { part: true })).to.be.true();
         expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 3 }, { only: true })).to.be.true();
         expect(Hoek.contain({ a: [1], b: [2], c: [3] }, { a: [1], c: [3] }, { deep: true })).to.be.true();
-        expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true })).to.be.true();
+        expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true })).to.be.false();
         expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true, part: true })).to.be.true();
         expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true, part: false })).to.be.false();
         expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true, only: true })).to.be.false();
         expect(Hoek.contain({ a: [{ b: 1 }, { c: 2 }, { d: 3, e: 4 }] }, { a: [{ b: 1 }, { d: 3 }] }, { deep: true, only: false })).to.be.true();
+        expect(Hoek.contain({ a: [1, 2, 3] }, { a: [2, 4, 6] }, { deep: true, part: true })).to.be.true();
 
         expect(Hoek.contain({ a: 1, b: 2, c: 3 }, 'd')).to.be.false();
         expect(Hoek.contain({ a: 1, b: 2, c: 3 }, ['a', 'd'])).to.be.false();
@@ -1405,51 +1722,143 @@
         expect(Hoek.contain({ a: 1, b: 2, c: 3 }, { a: 1, b: 2 }, { only: true })).to.be.false();
         expect(Hoek.contain({ a: [1], b: [2], c: [3] }, { a: [1], c: [3] })).to.be.false();
         expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } })).to.be.false();
-        expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true })).to.be.true();
+        expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true })).to.be.false();
         expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true, only: true })).to.be.false();
         expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true, only: false })).to.be.true();
         expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true, part: true })).to.be.true();
         expect(Hoek.contain({ a: { b: { c: 1, d: 2 } } }, { a: { b: { c: 1 } } }, { deep: true, part: false })).to.be.false();
+        expect(Hoek.contain({ a: [1, 2, 3] }, { a: [4, 5, 6] }, { deep: true, part: true })).to.be.false();
+
+        expect(Hoek.contain({}, 'a')).to.be.false();
+        expect(Hoek.contain({}, 'a', { only: true })).to.be.false();
+
+        expect(Hoek.contain({ a: 'foo', b: 'bar' }, ['a', 'b', 'c'])).to.be.false();
+        expect(Hoek.contain({ a: 'foo', b: 'bar' }, ['a', 'b', 'c'], { only: true })).to.be.false();
+        expect(Hoek.contain({ a: 'foo', b: 'bar' }, { a: 'foo', b: 'bar', c: 'x' })).to.be.false();
+        expect(Hoek.contain({ a: 'foo', b: 'bar' }, { a: 'foo', b: 'bar', c: 'x' }, { only: true })).to.be.false();
+
+        expect(Hoek.contain({ a: 1, b: 2 }, ['c'], { part: true })).to.be.false();
+        expect(Hoek.contain({ a: 1, b: 2 }, ['b'], { part: true })).to.be.true();
 
         // Getter check
-        var Foo = function (bar) {
 
-            this.bar = bar;
-        };
+        {
+            const Foo = function (bar) {
 
-        Object.defineProperty(Foo.prototype, 'baz', {
-            enumerable: true,
-            get: function () {
+                this.bar = bar;
+            };
+
+            const getBar = function () {
 
                 return this.bar;
-            }
-        });
+            };
+
+            const createFoo = (value) => {
+
+                const foo = new Foo(value);
+                Object.defineProperty(foo, 'baz', {
+                    enumerable: true,
+                    get: getBar
+                });
+
+                return foo;
+            };
+
+            expect(Hoek.contain({ a: createFoo('b') }, { a: createFoo('b') }, { deep: true })).to.be.true();
+            expect(Hoek.contain({ a: createFoo('b') }, { a: createFoo('b') }, { deep: true, part: true })).to.be.true();
+            expect(Hoek.contain({ a: createFoo('b') }, { a: { bar: 'b', baz: 'b' } }, { deep: true })).to.be.true();
+            expect(Hoek.contain({ a: createFoo('b') }, { a: { bar: 'b', baz: 'b' } }, { deep: true, only: true })).to.be.false();
+            expect(Hoek.contain({ a: createFoo('b') }, { a: { baz: 'b' } }, { deep: true, part: false })).to.be.false();
+            expect(Hoek.contain({ a: createFoo('b') }, { a: { baz: 'b' } }, { deep: true, part: true })).to.be.true();
+            expect(Hoek.contain({ a: createFoo('b') }, { a: createFoo('b') }, { deep: true })).to.be.true();
+        }
+
+        // Properties on prototype not visible
+
+        {
+            const Foo = function () {
+
+                this.a = 1;
+            };
+
+            Object.defineProperty(Foo.prototype, 'b', {
+                enumerable: true,
+                value: 2
+            });
+
+            const Bar = function () {
+
+                Foo.call(this);
+                this.c = 3;
+            };
+
+            Util.inherits(Bar, Foo);
+
+            expect((new Bar()).a).to.equal(1);
+            expect((new Bar()).b).to.equal(2);
+            expect((new Bar()).c).to.equal(3);
+            expect(Hoek.contain(new Bar(), { 'a': 1, 'c': 3 }, { only: true })).to.be.true();
+            expect(Hoek.contain(new Bar(), 'b')).to.be.false();
+        }
+
+        // Non-Enumerable properties
+
+        {
+            const foo = { a: 1, b: 2 };
+
+            Object.defineProperty(foo, 'c', {
+                enumerable: false,
+                value: 3
+            });
+
+            expect(Hoek.contain(foo, 'c')).to.be.true();
+            expect(Hoek.contain(foo, { 'c': 3 })).to.be.true();
+            expect(Hoek.contain(foo, { 'a': 1, 'b': 2, 'c': 3 }, { only: true })).to.be.true();
+        }
+    });
+
+    it('supports symbols', () => {
+
+        const sym = Symbol();
 
-        expect(Hoek.contain({ a: new Foo('b') }, { a: new Foo('b') }, { deep: true })).to.be.true();
-        expect(Hoek.contain({ a: new Foo('b') }, { a: new Foo('b') }, { deep: true, part: true })).to.be.true();
-        expect(Hoek.contain({ a: new Foo('b') }, { a: { baz: 'b' } }, { deep: true })).to.be.true();
-        expect(Hoek.contain({ a: new Foo('b') }, { a: { baz: 'b' } }, { deep: true, only: true })).to.be.false();
-        expect(Hoek.contain({ a: new Foo('b') }, { a: { baz: 'b' } }, { deep: true, part: false })).to.be.false();
-        expect(Hoek.contain({ a: new Foo('b') }, { a: { baz: 'b' } }, { deep: true, part: true })).to.be.true();
+        expect(Hoek.contain([sym], sym)).to.be.true();
+        expect(Hoek.contain({ [sym]: 1 }, sym)).to.be.true();
+        expect(Hoek.contain({ [sym]: 1, a: 2 }, { [sym]: 1 })).to.be.true();
 
-        done();
+        expect(Hoek.contain([sym], Symbol())).to.be.false();
+        expect(Hoek.contain({ [sym]: 1 }, Symbol())).to.be.false();
+    });
+
+    it('compares error keys', () => {
+
+        const error = new Error('test');
+        expect(Hoek.contain(error, { x: 1 })).to.be.false();
+        expect(Hoek.contain(error, { x: 1 }, { part: true })).to.be.false();
+
+        error.x = 1;
+
+        expect(Hoek.contain(error, { x: 1 })).to.be.true();
+        expect(Hoek.contain(error, { x: 1 }, { part: true })).to.be.true();
+
+        expect(Hoek.contain(error, { x: 1, y: 2 })).to.be.false();
+        expect(Hoek.contain(error, { x: 1, y: 2 }, { part: true })).to.be.true();
     });
 });
 
-describe('flatten()', function () {
+describe('flatten()', () => {
 
-    it('returns a flat array', function (done) {
+    it('returns a flat array', () => {
 
-        var result = Hoek.flatten([1, 2, [3, 4, [5, 6], [7], 8], [9], [10, [11, 12]], 13]);
+        const result = Hoek.flatten([1, 2, [3, 4, [5, 6], [7], 8], [9], [10, [11, 12]], 13]);
         expect(result.length).to.equal(13);
-        expect(result).to.deep.equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
-        done();
+        expect(result).to.equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
     });
 });
 
-describe('reach()', function () {
+describe('reach()', () => {
 
-    var obj = {
+    const sym = Symbol();
+    const obj = {
         a: {
             b: {
                 c: {
@@ -1460,6 +1869,10 @@
             },
             g: {
                 h: 3
+            },
+            '-2': true,
+            [sym]: {
+                v: true
             }
         },
         i: function () { },
@@ -1469,124 +1882,159 @@
 
     obj.i.x = 5;
 
-    it('returns object itself', function (done) {
+    it('returns object itself', () => {
 
         expect(Hoek.reach(obj, null)).to.equal(obj);
         expect(Hoek.reach(obj, false)).to.equal(obj);
         expect(Hoek.reach(obj)).to.equal(obj);
-        done();
+        expect(Hoek.reach(obj, [])).to.equal(obj);
     });
 
-    it('returns first value of array', function (done) {
+    it('returns values of array', () => {
 
         expect(Hoek.reach(obj, 'k.0')).to.equal(4);
-        done();
+        expect(Hoek.reach(obj, 'k.1')).to.equal(8);
     });
 
-    it('returns last value of array using negative index', function (done) {
+    it('returns last value of array using negative index', () => {
 
+        expect(Hoek.reach(obj, 'k.-1')).to.equal(1);
         expect(Hoek.reach(obj, 'k.-2')).to.equal(9);
-        done();
     });
 
-    it('returns a valid member', function (done) {
+    it('returns object property with negative index for non-array', () => {
+
+        expect(Hoek.reach(obj, 'a.-2')).to.be.equal(true);
+    });
+
+    it('returns a valid member', () => {
 
         expect(Hoek.reach(obj, 'a.b.c.d')).to.equal(1);
-        done();
     });
 
-    it('returns a valid member with separator override', function (done) {
+    it('returns a valid member with separator override', () => {
 
         expect(Hoek.reach(obj, 'a/b/c/d', '/')).to.equal(1);
-        done();
     });
 
-    it('returns undefined on null object', function (done) {
+    it('returns undefined on null object', () => {
 
         expect(Hoek.reach(null, 'a.b.c.d')).to.equal(undefined);
-        done();
     });
 
-    it('returns undefined on missing object member', function (done) {
+    it('returns undefined on missing object member', () => {
 
         expect(Hoek.reach(obj, 'a.b.c.d.x')).to.equal(undefined);
-        done();
     });
 
-    it('returns undefined on missing function member', function (done) {
+    it('returns undefined on missing function member', () => {
 
         expect(Hoek.reach(obj, 'i.y', { functions: true })).to.equal(undefined);
-        done();
     });
 
-    it('throws on missing member in strict mode', function (done) {
+    it('throws on missing member in strict mode', () => {
 
-        expect(function () {
+        expect(() => {
 
             Hoek.reach(obj, 'a.b.c.o.x', { strict: true });
         }).to.throw('Missing segment o in reach path  a.b.c.o.x');
 
-        done();
     });
 
-    it('returns undefined on invalid member', function (done) {
+    it('returns undefined on invalid member', () => {
 
         expect(Hoek.reach(obj, 'a.b.c.d-.x')).to.equal(undefined);
-        done();
+        expect(Hoek.reach(obj, 'k.x')).to.equal(undefined);
+        expect(Hoek.reach(obj, 'k.1000')).to.equal(undefined);
+        expect(Hoek.reach(obj, 'k/0.5', '/')).to.equal(undefined);
     });
 
-    it('returns function member', function (done) {
+    it('returns function member', () => {
 
         expect(typeof Hoek.reach(obj, 'i')).to.equal('function');
-        done();
     });
 
-    it('returns function property', function (done) {
+    it('returns function property', () => {
 
         expect(Hoek.reach(obj, 'i.x')).to.equal(5);
-        done();
     });
 
-    it('returns null', function (done) {
+    it('returns null', () => {
 
         expect(Hoek.reach(obj, 'j')).to.equal(null);
-        done();
     });
 
-    it('throws on function property when functions not allowed', function (done) {
+    it('throws on function property when functions not allowed', () => {
 
-        expect(function () {
+        expect(() => {
 
             Hoek.reach(obj, 'i.x', { functions: false });
         }).to.throw('Invalid segment x in reach path  i.x');
-
-        done();
     });
 
-    it('will return a default value if property is not found', function (done) {
+    it('will return a default value if property is not found', () => {
 
         expect(Hoek.reach(obj, 'a.b.q', { default: 'defaultValue' })).to.equal('defaultValue');
-        done();
     });
 
-    it('will return a default value if path is not found', function (done) {
+    it('will return a default value if path is not found', () => {
 
         expect(Hoek.reach(obj, 'q', { default: 'defaultValue' })).to.equal('defaultValue');
-        done();
     });
 
-    it('allows a falsey value to be used as the default value', function (done) {
+    it('allows a falsey value to be used as the default value', () => {
 
         expect(Hoek.reach(obj, 'q', { default: '' })).to.equal('');
-        done();
+    });
+
+    it('allows array-based lookup', () => {
+
+        expect(Hoek.reach(obj, ['a', 'b', 'c', 'd'])).to.equal(1);
+        expect(Hoek.reach(obj, ['k', '1'])).to.equal(8);
+        expect(Hoek.reach(obj, ['k', 1])).to.equal(8);
+        expect(Hoek.reach(obj, ['k', '-2'])).to.equal(9);
+        expect(Hoek.reach(obj, ['k', -2])).to.equal(9);
+    });
+
+    it('allows array-based lookup with symbols', () => {
+
+        expect(Hoek.reach(obj, ['a', sym, 'v'])).to.equal(true);
+        expect(Hoek.reach(obj, ['a', Symbol(), 'v'])).to.equal(undefined);
+    });
+
+    it('returns character in string', () => {
+
+        expect(Hoek.reach(['abc'], [0])).to.equal('abc');
+        expect(Hoek.reach(['abc'], ['0'])).to.equal('abc');
+    });
+
+    it('reaches sets and maps', () => {
+
+        const value = {
+            a: {
+                b: new Set([
+                    { x: 1 },
+                    { x: 2 },
+                    {
+                        y: new Map([
+                            ['v', 4],
+                            ['w', 5]
+                        ])
+                    }
+                ])
+            }
+        };
+
+        expect(Hoek.reach(value, 'a.b.2.y.w')).to.not.exist();
+        expect(Hoek.reach(value, 'a.b.2.y.w', { iterables: true })).to.equal(5);
     });
 });
 
-describe('reachTemplate()', function () {
+describe('reachTemplate()', () => {
 
-    it('applies object to template', function (done) {
+    it('applies object to template', () => {
 
-        var obj = {
+        const obj = {
             a: {
                 b: {
                     c: {
@@ -1598,15 +2046,14 @@
             k: [4, 8, 9, 1]
         };
 
-        var template = '{k.0}:{k.-2}:{a.b.c.d}:{x.y}:{j}';
+        const template = '{k.0}:{k.-2}:{a.b.c.d}:{x.y}:{j}';
 
         expect(Hoek.reachTemplate(obj, template)).to.equal('4:9:1::');
-        done();
     });
 
-    it('applies object to template (options)', function (done) {
+    it('applies object to template (options)', () => {
 
-        var obj = {
+        const obj = {
             a: {
                 b: {
                     c: {
@@ -1618,479 +2065,218 @@
             k: [4, 8, 9, 1]
         };
 
-        var template = '{k/0}:{k/-2}:{a/b/c/d}:{x/y}:{j}';
+        const template = '{k/0}:{k/-2}:{a/b/c/d}:{x/y}:{j}';
 
         expect(Hoek.reachTemplate(obj, template, '/')).to.equal('4:9:1::');
-        done();
-    });
-});
-
-describe('callStack()', function () {
-
-    it('returns the full call stack', function (done) {
-
-        var stack = Hoek.callStack();
-        expect(stack[0][0]).to.contain('index.js');
-        expect(stack[0][2]).to.equal(26);
-        done();
     });
-});
-
-describe('displayStack ()', function () {
-
-    it('returns the full call stack for display', function (done) {
-
-        var stack = Hoek.displayStack();
-        expect(stack[0]).to.contain(Path.normalize('/test/index.js') + ':');
-        done();
-    });
-
-    it('includes constructor functions correctly', function (done) {
-
-        var Something = function (next) {
-
-            next();
-        };
-
-        var something = new Something(function () {
-
-            var stack = Hoek.displayStack();
-            expect(stack[1]).to.contain('new Something');
-            done();
-        });
-    });
-});
-
-describe('abort()', function () {
-
-    it('exits process when not in test mode', function (done) {
-
-        var env = process.env.NODE_ENV;
-        var write = process.stdout.write;
-        var exit = process.exit;
-
-        process.env.NODE_ENV = 'nottatest';
-        process.stdout.write = function () { };
-        process.exit = function (state) {
-
-            process.exit = exit;
-            process.env.NODE_ENV = env;
-            process.stdout.write = write;
-
-            expect(state).to.equal(1);
-            done();
-        };
-
-        Hoek.abort('Boom');
-    });
-
-    it('throws when not in test mode and abortThrow is true', function (done) {
-
-        var env = process.env.NODE_ENV;
-        process.env.NODE_ENV = 'nottatest';
-        Hoek.abortThrow = true;
-
-        var fn = function () {
-
-            Hoek.abort('my error message');
-        };
 
-        expect(fn).to.throw('my error message');
-        Hoek.abortThrow = false;
-        process.env.NODE_ENV = env;
+    it('isn\'t prone to ReDoS given an adversarial template', () => {
 
-        done();
-    });
-
-    it('respects hideStack argument', function (done) {
-
-        var env = process.env.NODE_ENV;
-        var write = process.stdout.write;
-        var exit = process.exit;
-        var output = '';
-
-        process.exit = function () { };
-        process.env.NODE_ENV = '';
-        process.stdout.write = function (message) {
-
-            output = message;
-        };
-
-        Hoek.abort('my error message', true);
-
-        process.env.NODE_ENV = env;
-        process.stdout.write = write;
-        process.exit = exit;
-
-        expect(output).to.equal('ABORT: my error message\n\t\n');
-
-        done();
-    });
-
-    it('throws in test mode', function (done) {
-
-        var env = process.env.NODE_ENV;
-        process.env.NODE_ENV = 'test';
-
-        expect(function () {
-
-            Hoek.abort('my error message', true);
-        }).to.throw('my error message');
-
-        process.env.NODE_ENV = env;
-        done();
-    });
-
-    it('throws in test mode with default message', function (done) {
-
-        var env = process.env.NODE_ENV;
-        process.env.NODE_ENV = 'test';
-
-        expect(function () {
-
-            Hoek.abort('', true);
-        }).to.throw('Unknown error');
-
-        process.env.NODE_ENV = env;
-        done();
-    });
-
-    it('defaults to showing stack', function (done) {
-
-        var env = process.env.NODE_ENV;
-        var write = process.stdout.write;
-        var exit = process.exit;
-        var output = '';
-
-        process.exit = function () { };
-        process.env.NODE_ENV = '';
-        process.stdout.write = function (message) {
-
-            output = message;
-        };
+        const sizes = [0, 1, 2, 3, 4]; // Should be evenly-spaced
+        const times = [];
+        const diffs = [];
+
+        for (const size of sizes) {
+            const start = Date.now();
+            Hoek.reachTemplate({}, '{'.repeat(size * 10000));
+            times.push(Date.now() - start);
+        }
 
-        Hoek.abort('my error message');
+        for (let i = 1; i < times.length; ++i) {
+            diffs.push(times[i] - times[i - 1]);
+        }
 
-        process.env.NODE_ENV = env;
-        process.stdout.write = write;
-        process.exit = exit;
+        // Under ReDoS, as the size of the input increases the timing accelerates upwards,
+        // i.e. each timing diff would be greater than the last.
 
-        expect(output).to.contain('index.js');
+        const diffsMonotonic = diffs[0] < diffs[1] && diffs[1] < diffs[2] && diffs[2] < diffs[3];
 
-        done();
+        expect(diffsMonotonic, 'Timing diffs monotonic').to.be.false();
     });
 });
 
-describe('assert()', function () {
+describe('assert()', () => {
 
-    it('throws an Error when using assert in a test', function (done) {
+    it('throws an Error when using assert in a test', () => {
 
-        var fn = function () {
+        expect(() => {
 
             Hoek.assert(false, 'my error message');
-        };
-
-        expect(fn).to.throw('my error message');
-        done();
+        }).to.throw(Hoek.AssertError, 'my error message');
     });
 
-    it('throws an Error when using assert in a test with no message', function (done) {
+    it('throws an Error when using assert in a test with no message', () => {
 
-        var fn = function () {
+        expect(() => {
 
             Hoek.assert(false);
-        };
-
-        expect(fn).to.throw('Unknown error');
-        done();
+        }).to.throw(Hoek.AssertError, 'Unknown error');
     });
 
-    it('throws an Error when using assert in a test with multipart message', function (done) {
+    it('throws an Error when using assert in a test with multipart message', () => {
 
-        var fn = function () {
+        expect(() => {
 
             Hoek.assert(false, 'This', 'is', 'my message');
-        };
-
-        expect(fn).to.throw('This is my message');
-        done();
+        }).to.throw(Hoek.AssertError, 'This is my message');
     });
 
-    it('throws an Error when using assert in a test with multipart message (empty)', function (done) {
+    it('throws an Error when using assert in a test with multipart message (empty)', () => {
 
-        var fn = function () {
+        expect(() => {
 
             Hoek.assert(false, 'This', 'is', '', 'my message');
-        };
-
-        expect(fn).to.throw('This is my message');
-        done();
+        }).to.throw(Hoek.AssertError, 'This is my message');
     });
 
-    it('throws an Error when using assert in a test with object message', function (done) {
+    it('throws an Error when using assert in a test with object message', () => {
 
-        var fn = function () {
+        expect(() => {
 
             Hoek.assert(false, 'This', 'is', { spinal: 'tap' });
-        };
-
-        expect(fn).to.throw('This is {"spinal":"tap"}');
-        done();
+        }).to.throw(Hoek.AssertError, 'This is {"spinal":"tap"}');
     });
 
-    it('throws an Error when using assert in a test with multipart string and error messages', function (done) {
-
-        var fn = function () {
+    it('throws an Error when using assert in a test with multipart string and error messages', () => {
 
-            Hoek.assert(false, 'This', 'is', new Error('spinal'), new Error('tap'));
-        };
+        expect(() => {
 
-        expect(fn).to.throw('This is spinal tap');
-        done();
+            Hoek.assert(false, new Error('This'), 'is', 'spinal', new Error('tap'));
+        }).to.throw(Hoek.AssertError, 'This is spinal tap');
     });
 
-    it('throws an Error when using assert in a test with error object message', function (done) {
-
-        var fn = function () {
-
-            Hoek.assert(false, new Error('This is spinal tap'));
-        };
+    it('throws an Error when using assert in a test with error object message', () => {
 
-        expect(fn).to.throw('This is spinal tap');
-        done();
+        const err = new TypeError('This is spinal tap');
+        const got = expect(() => Hoek.assert(false, err)).to.throw(TypeError, 'This is spinal tap');
+        expect(got).to.shallow.equal(err);
     });
 
-    it('throws the same Error that is passed to it if there is only one error passed', function (done) {
+    it('throws the same Error that is passed to it if there is only one error passed', () => {
 
-        var error = new Error('ruh roh');
-        var error2 = new Error('ruh roh');
+        const error = new Error('ruh roh');
+        const error2 = new Error('ruh roh');
 
-        var fn = function () {
+        const fn = function () {
 
             Hoek.assert(false, error);
         };
 
         try {
             fn();
-        } catch (err) {
-            expect(error).to.equal(error);  // should be the same reference
-            expect(error).to.not.equal(error2); // error with the same message should not match
         }
-
-        done();
+        catch (err) {
+            expect(err).to.equal(error);  // should be the same reference
+            expect(err).to.not.shallow.equal(error2); // error with the same message should not match
+        }
     });
 });
 
-describe('Timer', function () {
+describe('AssertError', () => {
 
-    it('returns time elapsed', function (done) {
+    it('takes an optional message', () => {
 
-        var timer = new Hoek.Timer();
-        setTimeout(function () {
-
-            expect(timer.elapsed()).to.be.above(9);
-            done();
-        }, 12);
+        expect(new Hoek.AssertError().message).to.equal('Unknown error');
+        expect(new Hoek.AssertError(null).message).to.equal('Unknown error');
+        expect(new Hoek.AssertError('msg').message).to.equal('msg');
     });
-});
 
-describe('Bench', function () {
+    it('has AssertError name property', () => {
 
-    it('returns time elapsed', function (done) {
+        expect(new Hoek.AssertError().name).to.equal('AssertError');
+        expect(new Hoek.AssertError('msg').name).to.equal('AssertError');
+    });
 
-        var timer = new Hoek.Bench();
-        setTimeout(function () {
+    it('uses ctor argument to hide stack', { skip: typeof Error.captureStackTrace !== 'function' }, () => {
 
-            expect(timer.elapsed()).to.be.above(9);
-            done();
-        }, 12);
-    });
-});
+        const parentFn = () => {
 
-describe('escapeRegex()', function () {
+            throw new Hoek.AssertError('msg', parentFn);
+        };
 
-    it('escapes all special regular expression characters', function (done) {
+        const err = expect(parentFn).to.throw(Hoek.AssertError);
 
-        var a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,');
-        expect(a).to.equal('4\\^f\\$s\\.4\\*5\\+\\-_\\?%\\=#\\!\\:@\\|~\\\\\\/`"\\(>\\)\\[<\\]d\\{\\}s\\,');
-        done();
+        expect(err.stack).to.not.contain('parentFn');
     });
 });
 
-describe('Base64Url', function () {
+describe('Bench', () => {
 
-    var base64str = 'AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w';
-    var str = unescape('%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29*+%2C-./0123456789%3A%3B%3C%3D%3E%3F@ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF');
+    it('returns time elapsed', async () => {
 
-    describe('base64urlEncode()', function () {
-
-        it('should base64 URL-safe a string', function (done) {
-
-            expect(Hoek.base64urlEncode(str)).to.equal(base64str);
-            done();
-        });
-
-        it('encodes a buffer', function (done) {
-
-            expect(Hoek.base64urlEncode(new Buffer(str, 'binary'))).to.equal(base64str);
-            done();
-        });
-
-        it('should base64 URL-safe a hex string', function (done) {
-
-            var buffer = new Buffer(str, 'binary');
-            expect(Hoek.base64urlEncode(buffer.toString('hex'), 'hex')).to.equal(base64str);
-            done();
-        });
-
-        it('works on larger input strings', function (done) {
-
-            var input = Fs.readFileSync(Path.join(__dirname, 'index.js')).toString();
-            var encoded = Hoek.base64urlEncode(input);
-
-            expect(encoded).to.not.contain('+');
-            expect(encoded).to.not.contain('/');
-
-            var decoded = Hoek.base64urlDecode(encoded);
-
-            expect(decoded).to.equal(input);
-            done();
-        });
+        const timer = new Hoek.Bench();
+        await Hoek.wait(12);
+        expect(timer.elapsed()).to.be.above(9);
     });
+});
 
-    describe('base64urlDecode()', function () {
-
-        it('should un-base64 URL-safe a string', function (done) {
-
-            expect(Hoek.base64urlDecode(base64str)).to.equal(str);
-            done();
-        });
-
-        it('should un-base64 URL-safe a string into hex', function (done) {
-
-            expect(Hoek.base64urlDecode(base64str, 'hex')).to.equal(new Buffer(str, 'binary').toString('hex'));
-            done();
-        });
-
-        it('should un-base64 URL-safe a string and return a buffer', function (done) {
-
-            var buf = Hoek.base64urlDecode(base64str, 'buffer');
-            expect(buf instanceof Buffer).to.equal(true);
-            expect(buf.toString('binary')).to.equal(str);
-            done();
-        });
-
-        it('returns error on undefined input', function (done) {
-
-            expect(Hoek.base64urlDecode().message).to.exist();
-            done();
-        });
+describe('escapeRegex()', () => {
 
-        it('returns error on invalid input', function (done) {
+    it('escapes all special regular expression characters', () => {
 
-            expect(Hoek.base64urlDecode('*').message).to.exist();
-            done();
-        });
+        const a = Hoek.escapeRegex('4^f$s.4*5+-_?%=#!:@|~\\/`"(>)[<]d{}s,');
+        expect(a).to.equal('4\\^f\\$s\\.4\\*5\\+\\-_\\?%\\=#\\!\\:@\\|~\\\\\\/`"\\(>\\)\\[<\\]d\\{\\}s\\,');
     });
 });
 
-describe('escapeHeaderAttribute()', function () {
+describe('escapeHeaderAttribute()', () => {
 
-    it('should not alter ascii values', function (done) {
+    it('should not alter ascii values', () => {
 
-        var a = Hoek.escapeHeaderAttribute('My Value');
+        const a = Hoek.escapeHeaderAttribute('My Value');
         expect(a).to.equal('My Value');
-        done();
     });
 
-    it('escapes all special HTTP header attribute characters', function (done) {
+    it('escapes all special HTTP header attribute characters', () => {
 
-        var a = Hoek.escapeHeaderAttribute('I said go!!!#"' + String.fromCharCode(92));
+        const a = Hoek.escapeHeaderAttribute('I said go!!!#"' + String.fromCharCode(92));
         expect(a).to.equal('I said go!!!#\\"\\\\');
-        done();
     });
 
-    it('throws on large unicode characters', function (done) {
+    it('throws on large unicode characters', () => {
 
-        var fn = function () {
+        expect(() => {
 
             Hoek.escapeHeaderAttribute('this is a test' + String.fromCharCode(500) + String.fromCharCode(300));
-        };
-
-        expect(fn).to.throw(Error);
-        done();
+        }).to.throw(Error);
     });
 
-    it('throws on CRLF to prevent response splitting', function (done) {
+    it('throws on CRLF to prevent response splitting', () => {
 
-        var fn = function () {
+        expect(() => {
 
             Hoek.escapeHeaderAttribute('this is a test\r\n');
-        };
-
-        expect(fn).to.throw(Error);
-        done();
+        }).to.throw(Error);
     });
 });
 
-describe('escapeHtml()', function () {
+describe('escapeHtml()', () => {
 
-    it('escapes all special HTML characters', function (done) {
+    it('escapes all special HTML characters', () => {
 
-        var a = Hoek.escapeHtml('&<>"\'`');
+        const a = Hoek.escapeHtml('&<>"\'`');
         expect(a).to.equal('&amp;&lt;&gt;&quot;&#x27;&#x60;');
-        done();
     });
 
-    it('returns empty string on falsy input', function (done) {
+    it('returns empty string on falsy input', () => {
 
-        var a = Hoek.escapeHtml('');
+        const a = Hoek.escapeHtml('');
         expect(a).to.equal('');
-        done();
     });
 
-    it('returns unchanged string on no reserved input', function (done) {
+    it('returns unchanged string on no reserved input', () => {
 
-        var a = Hoek.escapeHtml('abc');
+        const a = Hoek.escapeHtml('abc');
         expect(a).to.equal('abc');
-        done();
     });
 });
 
-describe('nextTick()', function () {
-
-    it('calls the provided callback on nextTick', function (done) {
-
-        var a = 0;
-
-        var inc = function (step, next) {
-
-            a += step;
-            next();
-        };
-
-        var ticked = Hoek.nextTick(inc);
-
-        ticked(5, function () {
+describe('once()', () => {
 
-            expect(a).to.equal(6);
-            done();
-        });
+    it('allows function to only execute once', () => {
 
-        expect(a).to.equal(0);
-        inc(1, function () {
-
-            expect(a).to.equal(1);
-        });
-    });
-});
-
-describe('once()', function () {
-
-    it('allows function to only execute once', function (done) {
-
-        var gen = 0;
-        var add = function (x) {
+        let gen = 0;
+        let add = function (x) {
 
             gen += x;
         };
@@ -2102,412 +2288,227 @@
         expect(gen).to.equal(10);
         add(5);
         expect(gen).to.equal(10);
-        done();
     });
 
-    it('double once wraps one time', function (done) {
+    it('double once wraps one time', () => {
 
-        var method = function () { };
+        let method = function () { };
         method = Hoek.once(method);
         method.x = 1;
         method = Hoek.once(method);
         expect(method.x).to.equal(1);
-        done();
     });
 });
 
-describe('isAbsoltePath()', function () {
-
-    it('identifies if path is absolute on Unix without node support', { parallel: false }, function (done) {
-
-        var orig = Path.isAbsolute;
-        Path.isAbsolute = undefined;
-
-        expect(Hoek.isAbsolutePath('')).to.equal(false);
-        expect(Hoek.isAbsolutePath('a')).to.equal(false);
-        expect(Hoek.isAbsolutePath('./a')).to.equal(false);
-        expect(Hoek.isAbsolutePath('/a')).to.equal(true);
-        expect(Hoek.isAbsolutePath('/')).to.equal(true);
+describe('ignore()', () => {
 
-        Path.isAbsolute = orig;
-
-        done();
-    });
-
-    it('identifies if path is absolute with fake node support', { parallel: false }, function (done) {
-
-        var orig = Path.isAbsolute;
-        Path.isAbsolute = function (path) {
-
-            return path[0] === '/';
-        };
+    it('exists', () => {
 
-        expect(Hoek.isAbsolutePath('', 'linux')).to.equal(false);
-        expect(Hoek.isAbsolutePath('a', 'linux')).to.equal(false);
-        expect(Hoek.isAbsolutePath('./a', 'linux')).to.equal(false);
-        expect(Hoek.isAbsolutePath('/a', 'linux')).to.equal(true);
-        expect(Hoek.isAbsolutePath('/', 'linux')).to.equal(true);
-
-        Path.isAbsolute = orig;
-
-        done();
-    });
-
-    it('identifies if path is absolute on Windows without node support', { parallel: false }, function (done) {
-
-        var orig = Path.isAbsolute;
-        Path.isAbsolute = undefined;
-
-        expect(Hoek.isAbsolutePath('//server/file', 'win32')).to.equal(true);
-        expect(Hoek.isAbsolutePath('//server/file', 'win32')).to.equal(true);
-        expect(Hoek.isAbsolutePath('\\\\server\\file', 'win32')).to.equal(true);
-        expect(Hoek.isAbsolutePath('C:/Users/', 'win32')).to.equal(true);
-        expect(Hoek.isAbsolutePath('C:\\Users\\', 'win32')).to.equal(true);
-        expect(Hoek.isAbsolutePath('C:cwd/another', 'win32')).to.equal(false);
-        expect(Hoek.isAbsolutePath('C:cwd\\another', 'win32')).to.equal(false);
-        expect(Hoek.isAbsolutePath('directory/directory', 'win32')).to.equal(false);
-        expect(Hoek.isAbsolutePath('directory\\directory', 'win32')).to.equal(false);
-
-        Path.isAbsolute = orig;
-
-        done();
+        expect(Hoek.ignore).to.exist();
+        expect(typeof Hoek.ignore).to.equal('function');
     });
 });
 
-describe('isInteger()', function () {
+describe('stringify()', () => {
 
-    it('validates integers', function (done) {
+    it('converts object to string', () => {
 
-        expect(Hoek.isInteger(0)).to.equal(true);
-        expect(Hoek.isInteger(1)).to.equal(true);
-        expect(Hoek.isInteger(1394035612500)).to.equal(true);
-        expect(Hoek.isInteger('0')).to.equal(false);
-        expect(Hoek.isInteger(1.0)).to.equal(true);
-        expect(Hoek.isInteger(1.1)).to.equal(false);
-        done();
+        const obj = { a: 1 };
+        expect(Hoek.stringify(obj)).to.equal('{"a":1}');
     });
-});
 
-describe('ignore()', function () {
+    it('returns error in result string', () => {
 
-    it('exists', function (done) {
-
-        expect(Hoek.ignore).to.exist();
-        expect(typeof Hoek.ignore).to.equal('function');
-        done();
+        const obj = { a: 1 };
+        obj.b = obj;
+        expect(Hoek.stringify(obj)).to.contain('Cannot display object');
     });
 });
 
-describe('inherits()', function () {
-
-    it('exists', function (done) {
-
-        expect(Hoek.inherits).to.exist();
-        expect(typeof Hoek.inherits).to.equal('function');
-        done();
-    });
-});
+describe('isPromise()', () => {
 
-describe('format()', function () {
+    it('determines if an object is a promise', async () => {
 
-    it('exists', function (done) {
+        expect(Hoek.isPromise({})).to.be.false();
+        expect(Hoek.isPromise(null)).to.be.false();
+        expect(Hoek.isPromise(false)).to.be.false();
+        expect(Hoek.isPromise(0)).to.be.false();
+        expect(Hoek.isPromise('')).to.be.false();
+        expect(Hoek.isPromise({ then: 1 })).to.be.false();
+        expect(Hoek.isPromise([])).to.be.false();
 
-        expect(Hoek.format).to.exist();
-        expect(typeof Hoek.format).to.equal('function');
-        done();
-    });
+        const items = [
+            Promise.resolve(),
+            Promise.reject()
+        ];
 
-    it('is a reference to Util.format', function (done) {
+        expect(Hoek.isPromise(items[0])).to.be.true();
+        expect(Hoek.isPromise(items[1])).to.be.true();
+        expect(Hoek.isPromise(new Promise(Hoek.ignore))).to.be.true();
+        expect(Hoek.isPromise({ then: Hoek.ignore })).to.be.true();
 
-        expect(Hoek.format('hello %s', 'world')).to.equal('hello world');
-        done();
+        try {
+            await Promise.all(items);
+        }
+        catch (err) { }
     });
 });
 
-describe('transform()', function () {
+describe('wait()', () => {
 
-    var source = {
-        address: {
-            one: '123 main street',
-            two: 'PO Box 1234'
-        },
-        zip: {
-            code: 3321232,
-            province: null
-        },
-        title: 'Warehouse',
-        state: 'CA'
-    };
+    it('delays for timeout ms', async () => {
 
-    var sourcesArray = [{
-        address: {
-            one: '123 main street',
-            two: 'PO Box 1234'
-        },
-        zip: {
-            code: 3321232,
-            province: null
-        },
-        title: 'Warehouse',
-        state: 'CA'
-    }, {
-        address: {
-            one: '456 market street',
-            two: 'PO Box 5678'
-        },
-        zip: {
-            code: 9876,
-            province: null
-        },
-        title: 'Garage',
-        state: 'NY'
-    }];
-
-    it('transforms an object based on the input object', function (done) {
-
-        var result = Hoek.transform(source, {
-            'person.address.lineOne': 'address.one',
-            'person.address.lineTwo': 'address.two',
-            'title': 'title',
-            'person.address.region': 'state',
-            'person.address.zip': 'zip.code',
-            'person.address.location': 'zip.province'
-        });
+        const timeout = {};
+        setTimeout(() => (timeout.before = true), 10);
+        const wait = Hoek.wait(10);
+        setTimeout(() => (timeout.after = true), 10);
 
-        expect(result).to.deep.equal({
-            person: {
-                address: {
-                    lineOne: '123 main street',
-                    lineTwo: 'PO Box 1234',
-                    region: 'CA',
-                    zip: 3321232,
-                    location: null
-                }
-            },
-            title: 'Warehouse'
-        });
+        await wait;
 
-        done();
+        expect(timeout.before).to.be.true();
+        expect(timeout.after).to.be.undefined();
     });
 
-    it('transforms an array of objects based on the input object', function (done) {
-
-        var result = Hoek.transform(sourcesArray, {
-            'person.address.lineOne': 'address.one',
-            'person.address.lineTwo': 'address.two',
-            'title': 'title',
-            'person.address.region': 'state',
-            'person.address.zip': 'zip.code',
-            'person.address.location': 'zip.province'
-        });
-
-        expect(result).to.deep.equal([
-            {
-                person: {
-                    address: {
-                        lineOne: '123 main street',
-                        lineTwo: 'PO Box 1234',
-                        region: 'CA',
-                        zip: 3321232,
-                        location: null
-                    }
-                },
-                title: 'Warehouse'
-            },
-            {
-                person: {
-                    address: {
-                        lineOne: '456 market street',
-                        lineTwo: 'PO Box 5678',
-                        region: 'NY',
-                        zip: 9876,
-                        location: null
-                    }
-                },
-                title: 'Garage'
-            }
-        ]);
-
-        done();
-    });
+    it('delays for timeout ms as bigint', async () => {
 
-    it('uses the reach options passed into it', function (done) {
+        const timeout = {};
+        setTimeout(() => (timeout.before = true), 10);
+        const wait = Hoek.wait(10n);
+        setTimeout(() => (timeout.after = true), 10);
 
-        var schema = {
-            'person.address.lineOne': 'address-one',
-            'person.address.lineTwo': 'address-two',
-            'title': 'title',
-            'person.address.region': 'state',
-            'person.prefix': 'person-title',
-            'person.zip': 'zip-code'
-        };
-        var options = {
-            separator: '-',
-            default: 'unknown'
-        };
-        var result = Hoek.transform(source, schema, options);
-
-        expect(result).to.deep.equal({
-            person: {
-                address: {
-                    lineOne: '123 main street',
-                    lineTwo: 'PO Box 1234',
-                    region: 'CA'
-                },
-                prefix: 'unknown',
-                zip: 3321232
-            },
-            title: 'Warehouse'
-        });
+        await wait;
 
-        done();
+        expect(timeout.before).to.be.true();
+        expect(timeout.after).to.be.undefined();
     });
 
-    it('works to create shallow objects', function (done) {
+    it('handles timeouts >= 2^31', async () => {
 
-        var result = Hoek.transform(source, {
-            lineOne: 'address.one',
-            lineTwo: 'address.two',
-            title: 'title',
-            region: 'state',
-            province: 'zip.province'
-        });
-
-        expect(result).to.deep.equal({
-            lineOne: '123 main street',
-            lineTwo: 'PO Box 1234',
-            title: 'Warehouse',
-            region: 'CA',
-            province: null
-        });
+        const flow = [];
+        let no = 0;
 
-        done();
-    });
+        const fakeTimeout = function (cb, time) {
 
-    it('only allows strings in the map', function (done) {
+            const timer = ++no;
 
-        expect(function () {
+            flow.push(`CALL(${timer}): ${time}`);
+            setImmediate(() => {
 
-            var result = Hoek.transform(source, {
-                lineOne: {}
+                flow.push(`PRE(${timer})`);
+                cb();
+                flow.push(`POST(${timer})`);
             });
-        }).to.throw('All mappings must be "." delineated strings');
+        };
 
-        done();
+        await Hoek.wait(2 ** 31, null, { setTimeout: fakeTimeout });
+        flow.push('DONE1');
+        await Hoek.wait(2 ** 32 + 2 ** 30, null, { setTimeout: fakeTimeout });
+        flow.push('DONE2');
+
+        expect(flow).to.equal([
+            'CALL(1): 2147483647',
+            'PRE(1)',
+            'CALL(2): 1',
+            'POST(1)',
+            'PRE(2)',
+            'POST(2)',
+            'DONE1',
+            'CALL(3): 2147483647',
+            'PRE(3)',
+            'CALL(4): 2147483647',
+            'POST(3)',
+            'PRE(4)',
+            'CALL(5): 1073741826',
+            'POST(4)',
+            'PRE(5)',
+            'POST(5)',
+            'DONE2'
+        ]);
     });
 
-    it('throws an error on invalid arguments', function (done) {
+    it('returns never resolving promise when timeout >= Number.MAX_SAFE_INTEGER', async () => {
 
-        expect(function () {
+        let calls = 0;
+        const fakeTimeout = function (cb) {
 
-            var result = Hoek.transform(NaN, {});
-        }).to.throw('Invalid source object: must be null, undefined, an object, or an array');
-
-        done();
-    });
-
-    it('is safe to pass null', function (done) {
-
-        var result = Hoek.transform(null, {});
-        expect(result).to.deep.equal({});
+            ++calls;
+            process.nextTick(cb);
+        };
 
-        done();
-    });
+        await Hoek.wait(2 ** 31 - 1, null, { setTimeout: fakeTimeout });
+        expect(calls).to.equal(1);
 
-    it('is safe to pass undefined', function (done) {
+        const waited = Symbol('waited');
 
-        var result = Hoek.transform(undefined, {});
-        expect(result).to.deep.equal({});
+        const result = await Promise.race([
+            Hoek.wait(1, waited),
+            Hoek.wait(Number.MAX_SAFE_INTEGER, null, { setTimeout: fakeTimeout }),
+            Hoek.wait(Infinity, null, { setTimeout: fakeTimeout })
+        ]);
 
-        done();
+        expect(result).to.be.equal(waited);
+        expect(calls).to.equal(1);
     });
-});
-
-describe('uniqueFilename()', function () {
 
-    it('generates a random file path', function (done) {
+    it('handles a return value', async () => {
 
-        var result = Hoek.uniqueFilename('./test/modules');
+        const uniqueValue = {};
+        const timeout = {};
+        setTimeout(() => (timeout.before = true), 10);
+        const wait = Hoek.wait(10, uniqueValue);
+        setTimeout(() => (timeout.after = true), 10);
 
-        expect(result).to.exist();
-        expect(result).to.be.a.string();
-        expect(result).to.contain('test/modules');
-        done();
+        expect(await wait).to.shallow.equal(uniqueValue);
+        expect(timeout.before).to.be.true();
+        expect(timeout.after).to.be.undefined();
     });
 
-    it('is random enough to use in fast loops', function (done) {
-
-        var results = [];
-
-        for (var i = 0; i < 10; ++i) {
-            results[i] = Hoek.uniqueFilename('./test/modules');
-        }
-
-        var filter = results.filter(function (item, index, array) {
-
-            return array.indexOf(item) === index;
-        });
+    it('undefined timeout resolves immediately', async () => {
 
-        expect(filter.length).to.equal(10);
-        expect(results.length).to.equal(10);
-        done();
+        const waited = Symbol('waited');
+        const result = await Promise.race([
+            Hoek.wait(undefined, waited),
+            Hoek.wait(0)
+        ]);
 
+        expect(result).to.equal(waited);
     });
 
-    it('combines the random elements with a supplied character', function (done) {
-
-        var result = Hoek.uniqueFilename('./test', 'txt');
+    it('NaN timeout resolves immediately', async () => {
 
-        expect(result).to.contain('test/');
-        expect(result).to.contain('.txt');
+        const waited = Symbol('waited');
+        const result = await Promise.race([
+            Hoek.wait(Number.NaN, waited),
+            Hoek.wait(0)
+        ]);
 
-        done();
+        expect(result).to.equal(waited);
     });
 
-    it('accepts extensions with a "." in it', function (done) {
+    it('rejects on weird timeout values', async () => {
 
-        var result = Hoek.uniqueFilename('./test', '.mp3');
-
-        expect(result).to.contain('test/');
-        expect(result).to.contain('.mp3');
-
-        done();
+        await expect(() => Hoek.wait({})).to.throw();
+        await expect(() => Hoek.wait(Symbol('hi'))).to.throw();
     });
 });
 
-describe('stringify()', function (done) {
-
-    it('converts object to string', function (done) {
-
-        var obj = { a: 1 };
-        expect(Hoek.stringify(obj)).to.equal('{"a":1}');
-        done();
-    });
+describe('block()', () => {
 
-    it('returns error in result string', function (done) {
+    it('returns a promise', () => {
 
-        var obj = { a: 1 };
-        obj.b = obj;
-        expect(Hoek.stringify(obj)).to.equal('[Cannot display object: Converting circular structure to JSON]');
-        done();
+        expect(Hoek.block()).to.be.instanceOf(Promise);
     });
-});
 
-describe('shallow()', function (done) {
+    it('does not immediately reject or resolve', async () => {
 
-    it('shallow copies an object', function (done) {
+        const promise = Hoek.block();
+        const waited = Symbol('waited');
 
-        var obj = {
-            a: 5,
-            b: {
-                c: 6
-            }
-        };
+        const result = await Promise.race([
+            Hoek.wait(1, waited),
+            promise
+        ]);
 
-        var shallow = Hoek.shallow(obj);
-        expect(shallow).to.not.equal(obj);
-        expect(shallow).to.deep.equal(obj);
-        expect(shallow.b).to.equal(obj.b);
-        done();
+        expect(result).to.be.equal(waited);
     });
 });
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test1.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test1.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test1.js	(working copy)
@@ -1 +1,3 @@
+'use strict';
+
 exports.x = 1;
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test2.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test2.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test2.js	(working copy)
@@ -1 +1,3 @@
+'use strict';
+
 exports.y = 2;
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test3.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test3.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/node_modules/hoek/test/modules/test3.js	(working copy)
@@ -1 +1,3 @@
+'use strict';
+
 exports.z = 3;
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/package.json
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/package.json	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/package.json	(working copy)
@@ -1,52 +1,31 @@
 {
   "name": "hawk",
   "description": "HTTP Hawk Authentication Scheme",
-  "version": "3.1.3",
-  "author": {
-    "name": "Eran Hammer",
-    "email": "eran@hammer.io",
-    "url": "http://hueniverse.com"
-  },
-  "contributors": [],
-  "repository": {
-    "type": "git",
-    "url": "git://github.com/hueniverse/hawk"
-  },
+  "version": "9.0.1",
+  "repository": "git://github.com/mozilla/hawk",
   "main": "lib/index.js",
+  "files": [
+    "lib"
+  ],
   "keywords": [
     "http",
     "authentication",
     "scheme",
     "hawk"
   ],
-  "engines": {
-    "node": ">=0.10.32"
-  },
-  "browser": "./lib/browser.js",
   "dependencies": {
-    "hoek": "2.x.x",
-    "boom": "2.x.x",
-    "cryptiles": "2.x.x",
-    "sntp": "1.x.x"
+    "@hapi/b64": "5.x.x",
+    "@hapi/boom": "9.x.x",
+    "@hapi/cryptiles": "5.x.x",
+    "@hapi/hoek": "9.x.x"
   },
   "devDependencies": {
-    "code": "1.x.x",
-    "lab": "5.x.x"
+    "@hapi/code": "8.x.x",
+    "@hapi/lab": "22.x.x"
   },
   "scripts": {
-    "test": "lab -a code -t 100 -L",
-    "test-cov-html": "lab -a code -r html -o coverage.html"
-  },
-  "license": "BSD-3-Clause",
-  "readme": "![hawk Logo](https://raw.github.com/hueniverse/hawk/master/images/hawk.png)\r\n\r\n<img align=\"right\" src=\"https://raw.github.com/hueniverse/hawk/master/images/logo.png\" /> **Hawk** is an HTTP authentication scheme using a message authentication code (MAC) algorithm to provide partial\r\nHTTP request cryptographic verification. For more complex use cases such as access delegation, see [Oz](https://github.com/hueniverse/oz).\r\n\r\nCurrent version: **3.x**\r\n\r\nNote: 3.x and 2.x are the same exact protocol as 1.1. The version increments reflect changes in the node API.\r\n\r\n[![Build Status](https://secure.travis-ci.org/hueniverse/hawk.png)](http://travis-ci.org/hueniverse/hawk)\r\n\r\n# Table of Content\r\n\r\n- [**Introduction**](#introduction)\r\n  - [Replay Protection](#replay-protection)\r\n  - [Usage Example](#usage-example)\r\n  - [Protocol Example](#protocol-example)\r\n    - [Payload Validation](#payload-validation)\r\n    - [Response Payload Validation](#response-payload-validation)\r\n  - [Browser Support and Considerations](#browser-support-and-considerations)\r\n<p></p>\r\n- [**Single URI Authorization**](#single-uri-authorization)\r\n  - [Usage Example](#bewit-usage-example)\r\n<p></p>\r\n- [**Security Considerations**](#security-considerations)\r\n  - [MAC Keys Transmission](#mac-keys-transmission)\r\n  - [Confidentiality of Requests](#confidentiality-of-requests)\r\n  - [Spoofing by Counterfeit Servers](#spoofing-by-counterfeit-servers)\r\n  - [Plaintext Storage of Credentials](#plaintext-storage-of-credentials)\r\n  - [Entropy of Keys](#entropy-of-keys)\r\n  - [Coverage Limitations](#coverage-limitations)\r\n  - [Future Time Manipulation](#future-time-manipulation)\r\n  - [Client Clock Poisoning](#client-clock-poisoning)\r\n  - [Bewit Limitations](#bewit-limitations)\r\n  - [Host Header Forgery](#host-header-forgery)\r\n<p></p>\r\n- [**Frequently Asked Questions**](#frequently-asked-questions)\r\n<p></p>\r\n- [**Implementations**](#implementations)\r\n- [**Acknowledgements**](#acknowledgements)\r\n\r\n# Introduction\r\n\r\n**Hawk** is an HTTP authentication scheme providing mechanisms for making authenticated HTTP requests with\r\npartial cryptographic verification of the request and response, covering the HTTP method, request URI, host,\r\nand optionally the request payload.\r\n\r\nSimilar to the HTTP [Digest access authentication schemes](http://www.ietf.org/rfc/rfc2617.txt), **Hawk** uses a set of\r\nclient credentials which include an identifier (e.g. username) and key (e.g. password). Likewise, just as with the Digest scheme,\r\nthe key is never included in authenticated requests. Instead, it is used to calculate a request MAC value which is\r\nincluded in its place.\r\n\r\nHowever, **Hawk** has several differences from Digest. In particular, while both use a nonce to limit the possibility of\r\nreplay attacks, in **Hawk** the client generates the nonce and uses it in combination with a timestamp, leading to less\r\n\"chattiness\" (interaction with the server).\r\n\r\nAlso unlike Digest, this scheme is not intended to protect the key itself (the password in Digest) because\r\nthe client and server must both have access to the key material in the clear.\r\n\r\nThe primary design goals of this scheme are to:\r\n* simplify and improve HTTP authentication for services that are unwilling or unable to deploy TLS for all resources,\r\n* secure credentials against leakage (e.g., when the client uses some form of dynamic configuration to determine where\r\n  to send an authenticated request), and\r\n* avoid the exposure of credentials sent to a malicious server over an unauthenticated secure channel due to client\r\n  failure to validate the server's identity as part of its TLS handshake.\r\n\r\nIn addition, **Hawk** supports a method for granting third-parties temporary access to individual resources using\r\na query parameter called _bewit_ (in falconry, a leather strap used to attach a tracking device to the leg of a hawk).\r\n\r\nThe **Hawk** scheme requires the establishment of a shared symmetric key between the client and the server,\r\nwhich is beyond the scope of this module. Typically, the shared credentials are established via an initial\r\nTLS-protected phase or derived from some other shared confidential information available to both the client\r\nand the server.\r\n\r\n\r\n## Replay Protection\r\n\r\nWithout replay protection, an attacker can use a compromised (but otherwise valid and authenticated) request more \r\nthan once, gaining access to a protected resource. To mitigate this, clients include both a nonce and a timestamp when \r\nmaking requests. This gives the server enough information to prevent replay attacks.\r\n\r\nThe nonce is generated by the client, and is a string unique across all requests with the same timestamp and\r\nkey identifier combination. \r\n\r\nThe timestamp enables the server to restrict the validity period of the credentials where requests occuring afterwards\r\nare rejected. It also removes the need for the server to retain an unbounded number of nonce values for future checks.\r\nBy default, **Hawk** uses a time window of 1 minute to allow for time skew between the client and server (which in\r\npractice translates to a maximum of 2 minutes as the skew can be positive or negative).\r\n\r\nUsing a timestamp requires the client's clock to be in sync with the server's clock. **Hawk** requires both the client\r\nclock and the server clock to use NTP to ensure synchronization. However, given the limitations of some client types\r\n(e.g. browsers) to deploy NTP, the server provides the client with its current time (in seconds precision) in response\r\nto a bad timestamp.\r\n\r\nThere is no expectation that the client will adjust its system clock to match the server (in fact, this would be a\r\npotential attack vector). Instead, the client only uses the server's time to calculate an offset used only\r\nfor communications with that particular server. The protocol rewards clients with synchronized clocks by reducing\r\nthe number of round trips required to authenticate the first request.\r\n\r\n\r\n## Usage Example\r\n\r\nServer code:\r\n\r\n```javascript\r\nvar Http = require('http');\r\nvar Hawk = require('hawk');\r\n\r\n\r\n// Credentials lookup function\r\n\r\nvar credentialsFunc = function (id, callback) {\r\n\r\n    var credentials = {\r\n        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',\r\n        algorithm: 'sha256',\r\n        user: 'Steve'\r\n    };\r\n\r\n    return callback(null, credentials);\r\n};\r\n\r\n// Create HTTP server\r\n\r\nvar handler = function (req, res) {\r\n\r\n    // Authenticate incoming request\r\n\r\n    Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {\r\n\r\n        // Prepare response\r\n\r\n        var payload = (!err ? 'Hello ' + credentials.user + ' ' + artifacts.ext : 'Shoosh!');\r\n        var headers = { 'Content-Type': 'text/plain' };\r\n\r\n        // Generate Server-Authorization response header\r\n\r\n        var header = Hawk.server.header(credentials, artifacts, { payload: payload, contentType: headers['Content-Type'] });\r\n        headers['Server-Authorization'] = header;\r\n\r\n        // Send the response back\r\n\r\n        res.writeHead(!err ? 200 : 401, headers);\r\n        res.end(payload);\r\n    });\r\n};\r\n\r\n// Start server\r\n\r\nHttp.createServer(handler).listen(8000, 'example.com');\r\n```\r\n\r\nClient code:\r\n\r\n```javascript\r\nvar Request = require('request');\r\nvar Hawk = require('hawk');\r\n\r\n\r\n// Client credentials\r\n\r\nvar credentials = {\r\n    id: 'dh37fgj492je',\r\n    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',\r\n    algorithm: 'sha256'\r\n}\r\n\r\n// Request options\r\n\r\nvar requestOptions = {\r\n    uri: 'http://example.com:8000/resource/1?b=1&a=2',\r\n    method: 'GET',\r\n    headers: {}\r\n};\r\n\r\n// Generate Authorization request header\r\n\r\nvar header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', { credentials: credentials, ext: 'some-app-data' });\r\nrequestOptions.headers.Authorization = header.field;\r\n\r\n// Send authenticated request\r\n\r\nRequest(requestOptions, function (error, response, body) {\r\n\r\n    // Authenticate the server's response\r\n\r\n    var isValid = Hawk.client.authenticate(response, credentials, header.artifacts, { payload: body });\r\n\r\n    // Output results\r\n\r\n    console.log(response.statusCode + ': ' + body + (isValid ? ' (valid)' : ' (invalid)'));\r\n});\r\n```\r\n\r\n**Hawk** utilized the [**SNTP**](https://github.com/hueniverse/sntp) module for time sync management. By default, the local\r\nmachine time is used. To automatically retrieve and synchronice the clock within the application, use the SNTP 'start()' method.\r\n\r\n```javascript\r\nHawk.sntp.start();\r\n```\r\n\r\n\r\n## Protocol Example\r\n\r\nThe client attempts to access a protected resource without authentication, sending the following HTTP request to\r\nthe resource server:\r\n\r\n```\r\nGET /resource/1?b=1&a=2 HTTP/1.1\r\nHost: example.com:8000\r\n```\r\n\r\nThe resource server returns an authentication challenge.\r\n\r\n```\r\nHTTP/1.1 401 Unauthorized\r\nWWW-Authenticate: Hawk\r\n```\r\n\r\nThe client has previously obtained a set of **Hawk** credentials for accessing resources on the \"http://example.com/\"\r\nserver. The **Hawk** credentials issued to the client include the following attributes:\r\n\r\n* Key identifier: dh37fgj492je\r\n* Key: werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn\r\n* Algorithm: sha256\r\n\r\nThe client generates the authentication header by calculating a timestamp (e.g. the number of seconds since January 1,\r\n1970 00:00:00 GMT), generating a nonce, and constructing the normalized request string (each value followed by a newline\r\ncharacter):\r\n\r\n```\r\nhawk.1.header\r\n1353832234\r\nj4h3g2\r\nGET\r\n/resource/1?b=1&a=2\r\nexample.com\r\n8000\r\n\r\nsome-app-ext-data\r\n\r\n```\r\n\r\nThe request MAC is calculated using HMAC with the specified hash algorithm \"sha256\" and the key over the normalized request string.\r\nThe result is base64-encoded to produce the request MAC:\r\n\r\n```\r\n6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=\r\n```\r\n\r\nThe client includes the **Hawk** key identifier, timestamp, nonce, application specific data, and request MAC with the request using\r\nthe HTTP `Authorization` request header field:\r\n\r\n```\r\nGET /resource/1?b=1&a=2 HTTP/1.1\r\nHost: example.com:8000\r\nAuthorization: Hawk id=\"dh37fgj492je\", ts=\"1353832234\", nonce=\"j4h3g2\", ext=\"some-app-ext-data\", mac=\"6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE=\"\r\n```\r\n\r\nThe server validates the request by calculating the request MAC again based on the request received and verifies the validity\r\nand scope of the **Hawk** credentials. If valid, the server responds with the requested resource.\r\n\r\n\r\n### Payload Validation\r\n\r\n**Hawk** provides optional payload validation. When generating the authentication header, the client calculates a payload hash\r\nusing the specified hash algorithm. The hash is calculated over the concatenated value of (each followed by a newline character):\r\n* `hawk.1.payload`\r\n* the content-type in lowercase, without any parameters (e.g. `application/json`)\r\n* the request payload prior to any content encoding (the exact representation requirements should be specified by the server for payloads other than simple single-part ascii to ensure interoperability)\r\n\r\nFor example:\r\n\r\n* Payload: `Thank you for flying Hawk`\r\n* Content Type: `text/plain`\r\n* Hash (sha256): `Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=`\r\n\r\nResults in the following input to the payload hash function (newline terminated values):\r\n\r\n```\r\nhawk.1.payload\r\ntext/plain\r\nThank you for flying Hawk\r\n\r\n```\r\n\r\nWhich produces the following hash value:\r\n\r\n```\r\nYi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=\r\n```\r\n\r\nThe client constructs the normalized request string (newline terminated values):\r\n\r\n```\r\nhawk.1.header\r\n1353832234\r\nj4h3g2\r\nPOST\r\n/resource/1?a=1&b=2\r\nexample.com\r\n8000\r\nYi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=\r\nsome-app-ext-data\r\n\r\n```\r\n\r\nThen calculates the request MAC and includes the **Hawk** key identifier, timestamp, nonce, payload hash, application specific data,\r\nand request MAC, with the request using the HTTP `Authorization` request header field:\r\n\r\n```\r\nPOST /resource/1?a=1&b=2 HTTP/1.1\r\nHost: example.com:8000\r\nAuthorization: Hawk id=\"dh37fgj492je\", ts=\"1353832234\", nonce=\"j4h3g2\", hash=\"Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=\", ext=\"some-app-ext-data\", mac=\"aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw=\"\r\n```\r\n\r\nIt is up to the server if and when it validates the payload for any given request, based solely on it's security policy\r\nand the nature of the data included.\r\n\r\nIf the payload is available at the time of authentication, the server uses the hash value provided by the client to construct\r\nthe normalized string and validates the MAC. If the MAC is valid, the server calculates the payload hash and compares the value\r\nwith the provided payload hash in the header. In many cases, checking the MAC first is faster than calculating the payload hash.\r\n\r\nHowever, if the payload is not available at authentication time (e.g. too large to fit in memory, streamed elsewhere, or processed\r\nat a different stage in the application), the server may choose to defer payload validation for later by retaining the hash value\r\nprovided by the client after validating the MAC.\r\n\r\nIt is important to note that MAC validation does not mean the hash value provided by the client is valid, only that the value\r\nincluded in the header was not modified. Without calculating the payload hash on the server and comparing it to the value provided\r\nby the client, the payload may be modified by an attacker.\r\n\r\n\r\n## Response Payload Validation\r\n\r\n**Hawk** provides partial response payload validation. The server includes the `Server-Authorization` response header which enables the\r\nclient to authenticate the response and ensure it is talking to the right server. **Hawk** defines the HTTP `Server-Authorization` header\r\nas a response header using the exact same syntax as the `Authorization` request header field.\r\n\r\nThe header is contructed using the same process as the client's request header. The server uses the same credentials and other\r\nartifacts provided by the client to constructs the normalized request string. The `ext` and `hash` values are replaced with\r\nnew values based on the server response. The rest as identical to those used by the client.\r\n\r\nThe result MAC digest is included with the optional `hash` and `ext` values:\r\n\r\n```\r\nServer-Authorization: Hawk mac=\"XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=\", hash=\"f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=\", ext=\"response-specific\"\r\n```\r\n\r\n\r\n## Browser Support and Considerations\r\n\r\nA browser script is provided for including using a `<script>` tag in [lib/browser.js](/lib/browser.js). It's also a [component](http://component.io/hueniverse/hawk).\r\n\r\n**Hawk** relies on the _Server-Authorization_ and _WWW-Authenticate_ headers in its response to communicate with the client.\r\nTherefore, in case of CORS requests, it is important to consider sending _Access-Control-Expose-Headers_ with the value\r\n_\"WWW-Authenticate, Server-Authorization\"_ on each response from your server. As explained in the\r\n[specifications](http://www.w3.org/TR/cors/#access-control-expose-headers-response-header), it will indicate that these headers\r\ncan safely be accessed by the client (using getResponseHeader() on the XmlHttpRequest object). Otherwise you will be met with a\r\n[\"simple response header\"](http://www.w3.org/TR/cors/#simple-response-header) which excludes these fields and would prevent the\r\nHawk client from authenticating the requests.You can read more about the why and how in this\r\n[article](http://www.html5rocks.com/en/tutorials/cors/#toc-adding-cors-support-to-the-server)\r\n\r\n\r\n# Single URI Authorization\r\n\r\nThere are cases in which limited and short-term access to a protected resource is granted to a third party which does not\r\nhave access to the shared credentials. For example, displaying a protected image on a web page accessed by anyone. **Hawk**\r\nprovides limited support for such URIs in the form of a _bewit_ - a URI query parameter appended to the request URI which contains\r\nthe necessary credentials to authenticate the request.\r\n\r\nBecause of the significant security risks involved in issuing such access, bewit usage is purposely limited only to GET requests\r\nand for a finite period of time. Both the client and server can issue bewit credentials, however, the server should not use the same\r\ncredentials as the client to maintain clear traceability as to who issued which credentials.\r\n\r\nIn order to simplify implementation, bewit credentials do not support single-use policy and can be replayed multiple times within\r\nthe granted access timeframe. \r\n\r\n\r\n## Bewit Usage Example\r\n\r\nServer code:\r\n\r\n```javascript\r\nvar Http = require('http');\r\nvar Hawk = require('hawk');\r\n\r\n\r\n// Credentials lookup function\r\n\r\nvar credentialsFunc = function (id, callback) {\r\n\r\n    var credentials = {\r\n        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',\r\n        algorithm: 'sha256'\r\n    };\r\n\r\n    return callback(null, credentials);\r\n};\r\n\r\n// Create HTTP server\r\n\r\nvar handler = function (req, res) {\r\n\r\n    Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {\r\n\r\n        res.writeHead(!err ? 200 : 401, { 'Content-Type': 'text/plain' });\r\n        res.end(!err ? 'Access granted' : 'Shoosh!');\r\n    });\r\n};\r\n\r\nHttp.createServer(handler).listen(8000, 'example.com');\r\n```\r\n\r\nBewit code generation:\r\n\r\n```javascript\r\nvar Request = require('request');\r\nvar Hawk = require('hawk');\r\n\r\n\r\n// Client credentials\r\n\r\nvar credentials = {\r\n    id: 'dh37fgj492je',\r\n    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',\r\n    algorithm: 'sha256'\r\n}\r\n\r\n// Generate bewit\r\n\r\nvar duration = 60 * 5;      // 5 Minutes\r\nvar bewit = Hawk.uri.getBewit('http://example.com:8080/resource/1?b=1&a=2', { credentials: credentials, ttlSec: duration, ext: 'some-app-data' });\r\nvar uri = 'http://example.com:8000/resource/1?b=1&a=2' + '&bewit=' + bewit;\r\n```\r\n\r\n\r\n# Security Considerations\r\n\r\nThe greatest sources of security risks are usually found not in **Hawk** but in the policies and procedures surrounding its use.\r\nImplementers are strongly encouraged to assess how this module addresses their security requirements. This section includes\r\nan incomplete list of security considerations that must be reviewed and understood before deploying **Hawk** on the server.\r\nMany of the protections provided in **Hawk** depends on whether and how they are used.\r\n\r\n### MAC Keys Transmission\r\n\r\n**Hawk** does not provide any mechanism for obtaining or transmitting the set of shared credentials required. Any mechanism used\r\nto obtain **Hawk** credentials must ensure that these transmissions are protected using transport-layer mechanisms such as TLS.\r\n\r\n### Confidentiality of Requests\r\n\r\nWhile **Hawk** provides a mechanism for verifying the integrity of HTTP requests, it provides no guarantee of request\r\nconfidentiality. Unless other precautions are taken, eavesdroppers will have full access to the request content. Servers should\r\ncarefully consider the types of data likely to be sent as part of such requests, and employ transport-layer security mechanisms\r\nto protect sensitive resources.\r\n\r\n### Spoofing by Counterfeit Servers\r\n\r\n**Hawk** provides limited verification of the server authenticity. When receiving a response back from the server, the server\r\nmay choose to include a response `Server-Authorization` header which the client can use to verify the response. However, it is up to\r\nthe server to determine when such measure is included, to up to the client to enforce that policy.\r\n\r\nA hostile party could take advantage of this by intercepting the client's requests and returning misleading or otherwise\r\nincorrect responses. Service providers should consider such attacks when developing services using this protocol, and should\r\nrequire transport-layer security for any requests where the authenticity of the resource server or of server responses is an issue.\r\n\r\n### Plaintext Storage of Credentials\r\n\r\nThe **Hawk** key functions the same way passwords do in traditional authentication systems. In order to compute the request MAC,\r\nthe server must have access to the key in plaintext form. This is in contrast, for example, to modern operating systems, which\r\nstore only a one-way hash of user credentials.\r\n\r\nIf an attacker were to gain access to these keys - or worse, to the server's database of all such keys - he or she would be able\r\nto perform any action on behalf of any resource owner. Accordingly, it is critical that servers protect these keys from unauthorized\r\naccess.\r\n\r\n### Entropy of Keys\r\n\r\nUnless a transport-layer security protocol is used, eavesdroppers will have full access to authenticated requests and request\r\nMAC values, and will thus be able to mount offline brute-force attacks to recover the key used. Servers should be careful to\r\nassign keys which are long enough, and random enough, to resist such attacks for at least the length of time that the **Hawk**\r\ncredentials are valid.\r\n\r\nFor example, if the credentials are valid for two weeks, servers should ensure that it is not possible to mount a brute force\r\nattack that recovers the key in less than two weeks. Of course, servers are urged to err on the side of caution, and use the\r\nlongest key reasonable.\r\n\r\nIt is equally important that the pseudo-random number generator (PRNG) used to generate these keys be of sufficiently high\r\nquality. Many PRNG implementations generate number sequences that may appear to be random, but which nevertheless exhibit\r\npatterns or other weaknesses which make cryptanalysis or brute force attacks easier. Implementers should be careful to use\r\ncryptographically secure PRNGs to avoid these problems.\r\n\r\n### Coverage Limitations\r\n\r\nThe request MAC only covers the HTTP `Host` header and optionally the `Content-Type` header. It does not cover any other headers\r\nwhich can often affect how the request body is interpreted by the server. If the server behavior is influenced by the presence\r\nor value of such headers, an attacker can manipulate the request headers without being detected. Implementers should use the\r\n`ext` feature to pass application-specific information via the `Authorization` header which is protected by the request MAC.\r\n\r\nThe response authentication, when performed, only covers the response payload, content-type, and the request information \r\nprovided by the client in it's request (method, resource, timestamp, nonce, etc.). It does not cover the HTTP status code or\r\nany other response header field (e.g. Location) which can affect the client's behaviour.\r\n\r\n### Future Time Manipulation\r\n\r\nThe protocol relies on a clock sync between the client and server. To accomplish this, the server informs the client of its\r\ncurrent time when an invalid timestamp is received.\r\n\r\nIf an attacker is able to manipulate this information and cause the client to use an incorrect time, it would be able to cause\r\nthe client to generate authenticated requests using time in the future. Such requests will fail when sent by the client, and will\r\nnot likely leave a trace on the server (given the common implementation of nonce, if at all enforced). The attacker will then\r\nbe able to replay the request at the correct time without detection.\r\n\r\nThe client must only use the time information provided by the server if:\r\n* it was delivered over a TLS connection and the server identity has been verified, or\r\n* the `tsm` MAC digest calculated using the same client credentials over the timestamp has been verified.\r\n\r\n### Client Clock Poisoning\r\n\r\nWhen receiving a request with a bad timestamp, the server provides the client with its current time. The client must never use\r\nthe time received from the server to adjust its own clock, and must only use it to calculate an offset for communicating with\r\nthat particular server.\r\n\r\n### Bewit Limitations\r\n\r\nSpecial care must be taken when issuing bewit credentials to third parties. Bewit credentials are valid until expiration and cannot\r\nbe revoked or limited without using other means. Whatever resource they grant access to will be completely exposed to anyone with\r\naccess to the bewit credentials which act as bearer credentials for that particular resource. While bewit usage is limited to GET\r\nrequests only and therefore cannot be used to perform transactions or change server state, it can still be used to expose private\r\nand sensitive information.\r\n\r\n### Host Header Forgery\r\n\r\nHawk validates the incoming request MAC against the incoming HTTP Host header. However, unless the optional `host` and `port`\r\noptions are used with `server.authenticate()`, a malicous client can mint new host names pointing to the server's IP address and\r\nuse that to craft an attack by sending a valid request that's meant for another hostname than the one used by the server. Server\r\nimplementors must manually verify that the host header received matches their expectation (or use the options mentioned above).\r\n\r\n# Frequently Asked Questions\r\n\r\n### Where is the protocol specification?\r\n\r\nIf you are looking for some prose explaining how all this works, **this is it**. **Hawk** is being developed as an open source\r\nproject instead of a standard. In other words, the [code](/hueniverse/hawk/tree/master/lib) is the specification. Not sure about\r\nsomething? Open an issue!\r\n\r\n### Is it done?\r\n\r\nAs of version 0.10.0, **Hawk** is feature-complete. However, until this module reaches version 1.0.0 it is considered experimental\r\nand is likely to change. This also means your feedback and contribution are very welcome. Feel free to open issues with questions\r\nand suggestions.\r\n\r\n### Where can I find **Hawk** implementations in other languages?\r\n\r\n**Hawk**'s only reference implementation is provided in JavaScript as a node.js module. However, it has been ported to other languages.\r\nThe full list is maintained [here](https://github.com/hueniverse/hawk/issues?labels=port&state=closed). Please add an issue if you are\r\nworking on another port. A cross-platform test-suite is in the works.\r\n\r\n### Why isn't the algorithm part of the challenge or dynamically negotiated?\r\n\r\nThe algorithm used is closely related to the key issued as different algorithms require different key sizes (and other\r\nrequirements). While some keys can be used for multiple algorithm, the protocol is designed to closely bind the key and algorithm\r\ntogether as part of the issued credentials.\r\n\r\n### Why is Host and Content-Type the only headers covered by the request MAC?\r\n\r\nIt is really hard to include other headers. Headers can be changed by proxies and other intermediaries and there is no\r\nwell-established way to normalize them. Many platforms change the case of header field names and values. The only\r\nstraight-forward solution is to include the headers in some blob (say, base64 encoded JSON) and include that with the request,\r\nan approach taken by JWT and other such formats. However, that design violates the HTTP header boundaries, repeats information,\r\nand introduces other security issues because firewalls will not be aware of these \"hidden\" headers. In addition, any information\r\nrepeated must be compared to the duplicated information in the header and therefore only moves the problem elsewhere.\r\n\r\n### Why not just use HTTP Digest?\r\n\r\nDigest requires pre-negotiation to establish a nonce. This means you can't just make a request - you must first send\r\na protocol handshake to the server. This pattern has become unacceptable for most web services, especially mobile\r\nwhere extra round-trip are costly.\r\n\r\n### Why bother with all this nonce and timestamp business?\r\n\r\n**Hawk** is an attempt to find a reasonable, practical compromise between security and usability. OAuth 1.0 got timestamp\r\nand nonces halfway right but failed when it came to scalability and consistent developer experience. **Hawk** addresses\r\nit by requiring the client to sync its clock, but provides it with tools to accomplish it.\r\n\r\nIn general, replay protection is a matter of application-specific threat model. It is less of an issue on a TLS-protected\r\nsystem where the clients are implemented using best practices and are under the control of the server. Instead of dropping\r\nreplay protection, **Hawk** offers a required time window and an optional nonce verification. Together, it provides developers\r\nwith the ability to decide how to enforce their security policy without impacting the client's implementation.\r\n\r\n### What are `app` and `dlg` in the authorization header and normalized mac string?\r\n\r\nThe original motivation for **Hawk** was to replace the OAuth 1.0 use cases. This included both a simple client-server mode which\r\nthis module is specifically designed for, and a delegated access mode which is being developed separately in\r\n[Oz](https://github.com/hueniverse/oz). In addition to the **Hawk** use cases, Oz requires another attribute: the application id `app`.\r\nThis provides binding between the credentials and the application in a way that prevents an attacker from tricking an application\r\nto use credentials issued to someone else. It also has an optional 'delegated-by' attribute `dlg` which is the application id of the\r\napplication the credentials were directly issued to. The goal of these two additions is to allow Oz to utilize **Hawk** directly,\r\nbut with the additional security of delegated credentials.\r\n\r\n### What is the purpose of the static strings used in each normalized MAC input?\r\n\r\nWhen calculating a hash or MAC, a static prefix (tag) is added. The prefix is used to prevent MAC values from being\r\nused or reused for a purpose other than what they were created for (i.e. prevents switching MAC values between a request,\r\nresponse, and a bewit use cases). It also protects against exploits created after a potential change in how the protocol\r\ncreates the normalized string. For example, if a future version would switch the order of nonce and timestamp, it\r\ncan create an exploit opportunity for cases where the nonce is similar in format to a timestamp.\r\n\r\n### Does **Hawk** have anything to do with OAuth?\r\n\r\nShort answer: no.\r\n\r\n**Hawk** was originally proposed as the OAuth MAC Token specification. However, the OAuth working group in its consistent\r\nincompetence failed to produce a final, usable solution to address one of the most popular use cases of OAuth 1.0 - using it\r\nto authenticate simple client-server transactions (i.e. two-legged). As you can guess, the OAuth working group is still hard\r\nat work to produce more garbage.\r\n\r\n**Hawk** provides a simple HTTP authentication scheme for making client-server requests. It does not address the OAuth use case\r\nof delegating access to a third party. If you are looking for an OAuth alternative, check out [Oz](https://github.com/hueniverse/oz).\r\n\r\n# Implementations\r\n\r\n- [Logibit Hawk in F#/.Net](https://github.com/logibit/logibit.hawk/)\r\n- [Tent Hawk in Ruby](https://github.com/tent/hawk-ruby)\r\n- [Wealdtech in Java](https://github.com/wealdtech/hawk)\r\n- [Kumar's Mohawk in Python](https://github.com/kumar303/mohawk/)\r\n\r\n# Acknowledgements\r\n\r\n**Hawk** is a derivative work of the [HTTP MAC Authentication Scheme](http://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05) proposal\r\nco-authored by Ben Adida, Adam Barth, and Eran Hammer, which in turn was based on the OAuth 1.0 community specification.\r\n\r\nSpecial thanks to Ben Laurie for his always insightful feedback and advice.\r\n\r\nThe **Hawk** logo was created by [Chris Carrasco](http://chriscarrasco.com).\r\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/hueniverse/hawk/issues"
-  },
-  "_id": "hawk@3.1.3",
-  "dist": {
-    "shasum": "c421c2d85b698fe1a7ce4ca2e10019066ba02697"
+    "test": "lab -a @hapi/code -t 100 -L",
+    "test-cov-html": "lab -a @hapi/code -r html -o coverage.html"
   },
-  "_from": "hawk@~3.1.3",
-  "_resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz"
+  "license": "BSD-3-Clause"
 }
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/client.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/client.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/client.js	(working copy)
@@ -1,440 +1,530 @@
-// Load modules
-
-var Url = require('url');
-var Code = require('code');
-var Hawk = require('../lib');
-var Lab = require('lab');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var lab = exports.lab = Lab.script();
-var describe = lab.experiment;
-var it = lab.test;
-var expect = Code.expect;
-
-
-describe('Client', function () {
-
-    describe('header()', function () {
-
-        it('returns a valid authorization header (sha1)', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha1'
-            };
-
-            var header = Hawk.client.header('http://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about' }).field;
-            expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="bsvY3IfUllw6V5rvk4tStEvpBhE=", ext="Bazinga!", mac="qbf1ZPG/r/e06F4ht+T77LXi5vw="');
-            done();
-        });
-
-        it('returns a valid authorization header (sha256)', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field;
-            expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", ext="Bazinga!", mac="q1CwFoSHzPZSkbIvl0oYlD+91rBUEvFk763nMjMndj8="');
-            done();
-        });
-
-        it('returns a valid authorization header (no ext)', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' }).field;
-            expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
-            done();
-        });
-
-        it('returns a valid authorization header (null ext)', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain', ext: null }).field;
-            expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
-            done();
-        });
-
-        it('returns a valid authorization header (empty payload)', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: '', contentType: 'text/plain' }).field;
-            expect(header).to.equal('Hawk id=\"123456\", ts=\"1353809207\", nonce=\"Ygvqdz\", hash=\"q/t+NNAkQZNlq/aAD6PlexImwQTxwgT2MahfTa9XRLA=\", mac=\"U5k16YEzn3UnBHKeBzsDXn067Gu3R4YaY6xOt9PYRZM=\"');
-            done();
-        });
-
-        it('returns a valid authorization header (pre hashed payload)', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var options = { credentials: credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' };
-            options.hash = Hawk.crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
-            var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', options).field;
-            expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
-            done();
-        });
-
-        it('errors on missing uri', function (done) {
-
-            var header = Hawk.client.header('', 'POST');
-            expect(header.field).to.equal('');
-            expect(header.err).to.equal('Invalid argument type');
-            done();
-        });
-
-        it('errors on invalid uri', function (done) {
-
-            var header = Hawk.client.header(4, 'POST');
-            expect(header.field).to.equal('');
-            expect(header.err).to.equal('Invalid argument type');
-            done();
-        });
-
-        it('errors on missing method', function (done) {
-
-            var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', '');
-            expect(header.field).to.equal('');
-            expect(header.err).to.equal('Invalid argument type');
-            done();
-        });
-
-        it('errors on invalid method', function (done) {
-
-            var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 5);
-            expect(header.field).to.equal('');
-            expect(header.err).to.equal('Invalid argument type');
-            done();
-        });
-
-        it('errors on missing options', function (done) {
-
-            var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST');
-            expect(header.field).to.equal('');
-            expect(header.err).to.equal('Invalid argument type');
-            done();
-        });
-
-        it('errors on invalid credentials (id)', function (done) {
-
-            var credentials = {
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 });
-            expect(header.field).to.equal('');
-            expect(header.err).to.equal('Invalid credential object');
-            done();
-        });
-
-        it('errors on missing credentials', function (done) {
-
-            var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { ext: 'Bazinga!', timestamp: 1353809207 });
-            expect(header.field).to.equal('');
-            expect(header.err).to.equal('Invalid credential object');
-            done();
-        });
-
-        it('errors on invalid credentials', function (done) {
-
-            var credentials = {
-                id: '123456',
-                algorithm: 'sha256'
-            };
-
-            var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, ext: 'Bazinga!', timestamp: 1353809207 });
-            expect(header.field).to.equal('');
-            expect(header.err).to.equal('Invalid credential object');
-            done();
-        });
-
-        it('errors on invalid algorithm', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'hmac-sha-0'
-            };
-
-            var header = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials: credentials, payload: 'something, anything!', ext: 'Bazinga!', timestamp: 1353809207 });
-            expect(header.field).to.equal('');
-            expect(header.err).to.equal('Unknown algorithm');
-            done();
-        });
-    });
-
-    describe('authenticate()', function () {
-
-        it('returns false on invalid header', function (done) {
-
-            var res = {
-                headers: {
-                    'server-authorization': 'Hawk mac="abc", bad="xyz"'
-                }
-            };
-
-            expect(Hawk.client.authenticate(res, {})).to.equal(false);
-            done();
-        });
-
-        it('returns false on invalid mac', function (done) {
-
-            var res = {
-                headers: {
-                    'content-type': 'text/plain',
-                    'server-authorization': 'Hawk mac="_IJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
-                }
-            };
-
-            var artifacts = {
-                method: 'POST',
-                host: 'example.com',
-                port: '8080',
-                resource: '/resource/4?filter=a',
-                ts: '1362336900',
-                nonce: 'eb5S_L',
-                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
-                ext: 'some-app-data',
-                app: undefined,
-                dlg: undefined,
-                mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
-                id: '123456'
-            };
-
-            var credentials = {
-                id: '123456',
-                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                algorithm: 'sha256',
-                user: 'steve'
-            };
-
-            expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(false);
-            done();
-        });
-
-        it('returns true on ignoring hash', function (done) {
-
-            var res = {
-                headers: {
-                    'content-type': 'text/plain',
-                    'server-authorization': 'Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
-                }
-            };
-
-            var artifacts = {
-                method: 'POST',
-                host: 'example.com',
-                port: '8080',
-                resource: '/resource/4?filter=a',
-                ts: '1362336900',
-                nonce: 'eb5S_L',
-                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
-                ext: 'some-app-data',
-                app: undefined,
-                dlg: undefined,
-                mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
-                id: '123456'
-            };
-
-            var credentials = {
-                id: '123456',
-                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                algorithm: 'sha256',
-                user: 'steve'
-            };
-
-            expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(true);
-            done();
-        });
-
-        it('fails on invalid WWW-Authenticate header format', function (done) {
-
-            var header = 'Hawk ts="1362346425875", tsm="PhwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", x="Stale timestamp"';
-            expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, {})).to.equal(false);
-            done();
-        });
-
-        it('fails on invalid WWW-Authenticate header format', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                algorithm: 'sha256',
-                user: 'steve'
-            };
-
-            var header = 'Hawk ts="1362346425875", tsm="hwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", error="Stale timestamp"';
-            expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, credentials)).to.equal(false);
-            done();
-        });
-
-        it('skips tsm validation when missing ts', function (done) {
-
-            var header = 'Hawk error="Stale timestamp"';
-            expect(Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, {})).to.equal(true);
-            done();
-        });
-    });
-
-    describe('message()', function () {
-
-        it('generates authorization', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha1'
-            };
-
-            var auth = Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
-            expect(auth).to.exist();
-            expect(auth.ts).to.equal(1353809207);
-            expect(auth.nonce).to.equal('abc123');
-            done();
-        });
-
-        it('errors on invalid host', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha1'
-            };
-
-            var auth = Hawk.client.message(5, 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
-            expect(auth).to.not.exist();
-            done();
-        });
-
-        it('errors on invalid port', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha1'
-            };
-
-            var auth = Hawk.client.message('example.com', '80', 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
-            expect(auth).to.not.exist();
-            done();
-        });
-
-        it('errors on missing host', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha1'
-            };
-
-            var auth = Hawk.client.message('example.com', 0, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
-            expect(auth).to.not.exist();
-            done();
-        });
-
-        it('errors on null message', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha1'
-            };
-
-            var auth = Hawk.client.message('example.com', 80, null, { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
-            expect(auth).to.not.exist();
-            done();
-        });
-
-        it('errors on missing message', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha1'
-            };
-
-            var auth = Hawk.client.message('example.com', 80, undefined, { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
-            expect(auth).to.not.exist();
-            done();
-        });
-
-        it('errors on invalid message', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha1'
-            };
-
-            var auth = Hawk.client.message('example.com', 80, 5, { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
-            expect(auth).to.not.exist();
-            done();
-        });
-
-        it('errors on missing options', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha1'
-            };
-
-            var auth = Hawk.client.message('example.com', 80, 'I am the boodyman');
-            expect(auth).to.not.exist();
-            done();
-        });
-
-        it('errors on invalid credentials (id)', function (done) {
-
-            var credentials = {
-                key: '2983d45yun89q',
-                algorithm: 'sha1'
-            };
-
-            var auth = Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
-            expect(auth).to.not.exist();
-            done();
-        });
-
-        it('errors on invalid credentials (key)', function (done) {
-
-            var credentials = {
-                id: '123456',
-                algorithm: 'sha1'
-            };
-
-            var auth = Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials: credentials, timestamp: 1353809207, nonce: 'abc123' });
-            expect(auth).to.not.exist();
-            done();
-        });
-    });
-});
+'use strict';
+
+const Code = require('@hapi/code');
+const Hawk = require('..');
+const Lab = require('@hapi/lab');
+
+
+const internals = {};
+
+
+const { describe, it } = exports.lab = Lab.script();
+const expect = Code.expect;
+
+
+describe('Client', () => {
+
+    describe('header()', () => {
+
+        it('returns a valid authorization header (sha1)', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha1'
+            };
+
+            const { header } = Hawk.client.header('http://example.net/somewhere/over/the/rainbow', 'POST', { credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about' });
+            expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="bsvY3IfUllw6V5rvk4tStEvpBhE=", ext="Bazinga!", mac="qbf1ZPG/r/e06F4ht+T77LXi5vw="');
+        });
+
+        it('returns a valid authorization header (sha256)', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            const { header } = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials, ext: 'Bazinga!', timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' });
+            expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", ext="Bazinga!", mac="q1CwFoSHzPZSkbIvl0oYlD+91rBUEvFk763nMjMndj8="');
+        });
+
+        it('returns a valid authorization header (no ext)', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            const { header } = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' });
+            expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
+        });
+
+        it('returns a valid authorization header (null ext)', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            const { header } = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain', ext: null });
+            expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
+        });
+
+        it('returns a valid authorization header (empty payload)', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            const { header } = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: '', contentType: 'text/plain' });
+            expect(header).to.equal('Hawk id=\"123456\", ts=\"1353809207\", nonce=\"Ygvqdz\", hash=\"q/t+NNAkQZNlq/aAD6PlexImwQTxwgT2MahfTa9XRLA=\", mac=\"U5k16YEzn3UnBHKeBzsDXn067Gu3R4YaY6xOt9PYRZM=\"');
+        });
+
+        it('returns a valid authorization header (pre hashed payload)', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            const options = { credentials, timestamp: 1353809207, nonce: 'Ygvqdz', payload: 'something to write about', contentType: 'text/plain' };
+            options.hash = Hawk.crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
+            const { header } = Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', options);
+            expect(header).to.equal('Hawk id="123456", ts="1353809207", nonce="Ygvqdz", hash="2QfCt3GuY9HQnHWyWD3wX68ZOKbynqlfYmuO2ZBRqtY=", mac="HTgtd0jPI6E4izx8e4OHdO36q00xFCU0FolNq3RiCYs="');
+        });
+
+        it('errors on missing uri', () => {
+
+            expect(() => Hawk.client.header('', 'POST')).to.throw('Invalid argument type');
+        });
+
+        it('errors on invalid uri', () => {
+
+            expect(() => Hawk.client.header(4, 'POST')).to.throw('Invalid argument type');
+        });
+
+        it('errors on missing method', () => {
+
+            expect(() => Hawk.client.header('https://example.net/somewhere/over/the/rainbow', '')).to.throw('Invalid argument type');
+        });
+
+        it('errors on invalid method', () => {
+
+            expect(() => Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 5)).to.throw('Invalid argument type');
+        });
+
+        it('errors on missing options', () => {
+
+            expect(() => Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST')).to.throw('Invalid argument type');
+        });
+
+        it('errors on invalid options', () => {
+
+            expect(() => Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', 'abc')).to.throw('Invalid argument type');
+        });
+
+        it('errors on invalid credentials (id)', () => {
+
+            const credentials = {
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            expect(() => Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials, ext: 'Bazinga!', timestamp: 1353809207 })).to.throw('Invalid credentials');
+        });
+
+        it('errors on missing credentials', () => {
+
+            expect(() => Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { ext: 'Bazinga!', timestamp: 1353809207 })).to.throw('Invalid credentials');
+        });
+
+        it('errors on invalid credentials (key)', () => {
+
+            const credentials = {
+                id: '123456',
+                algorithm: 'sha256'
+            };
+
+            expect(() => Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials, ext: 'Bazinga!', timestamp: 1353809207 })).to.throw('Invalid credentials');
+        });
+
+        it('errors on invalid credentials (algorithm)', () => {
+
+            const credentials = {
+                id: '123456',
+                key: 'asdasdasd'
+            };
+
+            expect(() => Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials, ext: 'Bazinga!', timestamp: 1353809207 })).to.throw('Invalid credentials');
+        });
+
+        it('errors on invalid algorithm', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'hmac-sha-0'
+            };
+
+            expect(() => Hawk.client.header('https://example.net/somewhere/over/the/rainbow', 'POST', { credentials, payload: 'something, anything!', ext: 'Bazinga!', timestamp: 1353809207 })).to.throw('Unknown algorithm');
+        });
+    });
+
+    describe('authenticate()', () => {
+
+        it('rejects on invalid header', () => {
+
+            const res = {
+                headers: {
+                    'server-authorization': 'Hawk mac="abc", bad="xyz"'
+                }
+            };
+
+            expect(() => Hawk.client.authenticate(res)).to.throw('Invalid Server-Authorization header');
+        });
+
+        it('rejects on invalid mac', () => {
+
+            const res = {
+                headers: {
+                    'content-type': 'text/plain',
+                    'server-authorization': 'Hawk mac="_IJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
+                }
+            };
+
+            const artifacts = {
+                method: 'POST',
+                host: 'example.com',
+                port: '8080',
+                resource: '/resource/4?filter=a',
+                ts: '1362336900',
+                nonce: 'eb5S_L',
+                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                ext: 'some-app-data',
+                app: undefined,
+                dlg: undefined,
+                mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
+                id: '123456'
+            };
+
+            const credentials = {
+                id: '123456',
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            expect(() => Hawk.client.authenticate(res, credentials, artifacts)).to.throw('Bad response mac');
+        });
+
+        it('returns headers on ignoring hash', () => {
+
+            const res = {
+                headers: {
+                    'content-type': 'text/plain',
+                    'server-authorization': 'Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
+                }
+            };
+
+            const artifacts = {
+                method: 'POST',
+                host: 'example.com',
+                port: '8080',
+                resource: '/resource/4?filter=a',
+                ts: '1362336900',
+                nonce: 'eb5S_L',
+                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                ext: 'some-app-data',
+                app: undefined,
+                dlg: undefined,
+                mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
+                id: '123456'
+            };
+
+            const credentials = {
+                id: '123456',
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            const { headers } = Hawk.client.authenticate(res, credentials, artifacts, { payload: null });
+            expect(headers).to.equal({
+                'server-authorization': {
+                    mac: 'XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=',
+                    hash: 'f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=',
+                    ext: 'response-specific'
+                }
+            });
+        });
+
+        it('validates response payload', () => {
+
+            const payload = 'some reply';
+
+            const res = {
+                headers: {
+                    'content-type': 'text/plain',
+                    'server-authorization': 'Hawk mac="odsVGUq0rCoITaiNagW22REIpqkwP9zt5FyqqOW9Zj8=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
+                }
+            };
+
+            const credentials = {
+                id: '123456',
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            const artifacts = {
+                method: 'POST',
+                host: 'example.com',
+                port: '8080',
+                resource: '/resource/4?filter=a',
+                ts: '1453070933',
+                nonce: '3hOHpR',
+                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                ext: 'some-app-data',
+                app: undefined,
+                dlg: undefined,
+                mac: '/DitzeD66F2f7O535SERbX9p+oh9ZnNLqSNHG+c7/vs=',
+                id: '123456'
+            };
+
+            const { headers } = Hawk.client.authenticate(res, credentials, artifacts, { payload });
+            expect(headers).to.equal({
+                'server-authorization': {
+                    mac: 'odsVGUq0rCoITaiNagW22REIpqkwP9zt5FyqqOW9Zj8=',
+                    hash: 'f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=',
+                    ext: 'response-specific'
+                }
+            });
+        });
+
+        it('errors on invalid response payload', () => {
+
+            const payload = 'wrong reply';
+
+            const res = {
+                headers: {
+                    'content-type': 'text/plain',
+                    'server-authorization': 'Hawk mac="odsVGUq0rCoITaiNagW22REIpqkwP9zt5FyqqOW9Zj8=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"'
+                }
+            };
+
+            const credentials = {
+                id: '123456',
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            const artifacts = {
+                method: 'POST',
+                host: 'example.com',
+                port: '8080',
+                resource: '/resource/4?filter=a',
+                ts: '1453070933',
+                nonce: '3hOHpR',
+                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                ext: 'some-app-data',
+                app: undefined,
+                dlg: undefined,
+                mac: '/DitzeD66F2f7O535SERbX9p+oh9ZnNLqSNHG+c7/vs=',
+                id: '123456'
+            };
+
+            expect(() => Hawk.client.authenticate(res, credentials, artifacts, { payload })).to.throw('Bad response payload mac');
+        });
+
+        it('fails on invalid WWW-Authenticate header format', () => {
+
+            const header = 'Hawk ts="1362346425875", tsm="PhwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", x="Stale timestamp"';
+            expect(() => Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, {})).to.throw('Invalid WWW-Authenticate header');
+        });
+
+        it('fails on invalid WWW-Authenticate header format', () => {
+
+            const credentials = {
+                id: '123456',
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            const header = 'Hawk ts="1362346425875", tsm="hwayS28vtnn3qbv0mqRBYSXebN/zggEtucfeZ620Zo=", error="Stale timestamp"';
+            expect(() => Hawk.client.authenticate({ headers: { 'www-authenticate': header } }, credentials)).to.throw('Invalid server timestamp hash');
+        });
+
+        it('skips tsm validation when missing ts', () => {
+
+            const header = 'Hawk error="Stale timestamp"';
+            const { headers } = Hawk.client.authenticate({ headers: { 'www-authenticate': header } });
+            expect(headers).to.equal({ 'www-authenticate': { error: 'Stale timestamp' } });
+        });
+
+        it('errors on missing server-authorization header', () => {
+
+            const res = {
+                headers: {
+                    'content-type': 'text/plain'
+                }
+            };
+
+            const artifacts = {
+                method: 'POST',
+                host: 'example.com',
+                port: '8080',
+                resource: '/resource/4?filter=a',
+                ts: '1362336900',
+                nonce: 'eb5S_L',
+                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                ext: 'some-app-data',
+                app: undefined,
+                dlg: undefined,
+                mac: 'BlmSe8K+pbKIb6YsZCnt4E1GrYvY1AaYayNR82dGpIk=',
+                id: '123456'
+            };
+
+            const credentials = {
+                id: '123456',
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            expect(() => Hawk.client.authenticate(res, credentials, artifacts, { required: true })).to.throw('Missing Server-Authorization header');
+        });
+    });
+
+    describe('message()', () => {
+
+        it('generates authorization', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha1'
+            };
+
+            const auth = Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials, timestamp: 1353809207, nonce: 'abc123' });
+            expect(auth).to.exist();
+            expect(auth.ts).to.equal(1353809207);
+            expect(auth.nonce).to.equal('abc123');
+        });
+
+        it('errors on invalid host', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha1'
+            };
+
+            expect(() => Hawk.client.message(5, 80, 'I am the boodyman', { credentials, timestamp: 1353809207, nonce: 'abc123' })).to.throw('Invalid inputs');
+        });
+
+        it('errors on invalid port', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha1'
+            };
+
+            expect(() => Hawk.client.message('example.com', '80', 'I am the boodyman', { credentials, timestamp: 1353809207, nonce: 'abc123' })).to.throw('Invalid inputs');
+        });
+
+        it('errors on missing host', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha1'
+            };
+
+            expect(() => Hawk.client.message(undefined, 0, 'I am the boodyman', { credentials, timestamp: 1353809207, nonce: 'abc123' })).to.throw('Invalid inputs');
+        });
+
+        it('errors on missing port', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha1'
+            };
+
+            expect(() => Hawk.client.message('example.com', undefined, 'I am the boodyman', { credentials, timestamp: 1353809207, nonce: 'abc123' })).to.throw('Invalid inputs');
+        });
+
+        it('errors on null message', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha1'
+            };
+
+            expect(() => Hawk.client.message('example.com', 80, null, { credentials, timestamp: 1353809207, nonce: 'abc123' })).to.throw('Invalid inputs');
+        });
+
+        it('errors on missing message', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha1'
+            };
+
+            expect(() => Hawk.client.message('example.com', 80, undefined, { credentials, timestamp: 1353809207, nonce: 'abc123' })).to.throw('Invalid inputs');
+        });
+
+        it('errors on invalid message', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha1'
+            };
+
+            expect(() => Hawk.client.message('example.com', 80, 5, { credentials, timestamp: 1353809207, nonce: 'abc123' })).to.throw('Invalid inputs');
+        });
+
+        it('errors on invalid credentials', () => {
+
+            expect(() => Hawk.client.message('example.com', 80, 'I am the boodyman')).to.throw('Invalid credentials');
+        });
+
+        it('errors on invalid options', () => {
+
+            expect(() => Hawk.client.message('example.com', 80, 'I am the boodyman', '123')).to.throw('Invalid inputs');
+        });
+
+        it('errors on invalid credentials (id)', () => {
+
+            const credentials = {
+                key: '2983d45yun89q',
+                algorithm: 'sha1'
+            };
+
+            expect(() => Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials, timestamp: 1353809207, nonce: 'abc123' })).to.throw('Invalid credentials');
+        });
+
+        it('errors on invalid credentials (algorithm)', () => {
+
+            const credentials = {
+                key: '2983d45yun89q',
+                id: '123'
+            };
+
+            expect(() => Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials, timestamp: 1353809207, nonce: 'abc123' })).to.throw('Invalid credentials');
+        });
+
+        it('errors on invalid credentials (key)', () => {
+
+            const credentials = {
+                id: '123456',
+                algorithm: 'sha1'
+            };
+
+            expect(() => Hawk.client.message('example.com', 80, 'I am the boodyman', { credentials, timestamp: 1353809207, nonce: 'abc123' })).to.throw('Invalid credentials');
+        });
+    });
+});
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/crypto.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/crypto.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/crypto.js	(working copy)
@@ -1,70 +1,58 @@
-// Load modules
-
-var Code = require('code');
-var Hawk = require('../lib');
-var Lab = require('lab');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var lab = exports.lab = Lab.script();
-var describe = lab.experiment;
-var it = lab.test;
-var expect = Code.expect;
-
-
-describe('Crypto', function () {
-
-    describe('generateNormalizedString()', function () {
-
-        it('should return a valid normalized string', function (done) {
-
-            expect(Hawk.crypto.generateNormalizedString('header', {
-                ts: 1357747017,
-                nonce: 'k3k4j5',
-                method: 'GET',
-                resource: '/resource/something',
-                host: 'example.com',
-                port: 8080
-            })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\n\n\n');
-
-            done();
-        });
-
-        it('should return a valid normalized string (ext)', function (done) {
-
-            expect(Hawk.crypto.generateNormalizedString('header', {
-                ts: 1357747017,
-                nonce: 'k3k4j5',
-                method: 'GET',
-                resource: '/resource/something',
-                host: 'example.com',
-                port: 8080,
-                ext: 'this is some app data'
-            })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\n\nthis is some app data\n');
-
-            done();
-        });
-
-        it('should return a valid normalized string (payload + ext)', function (done) {
-
-            expect(Hawk.crypto.generateNormalizedString('header', {
-                ts: 1357747017,
-                nonce: 'k3k4j5',
-                method: 'GET',
-                resource: '/resource/something',
-                host: 'example.com',
-                port: 8080,
-                hash: 'U4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=',
-                ext: 'this is some app data'
-            })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\nU4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=\nthis is some app data\n');
-
-            done();
-        });
-    });
-});
+'use strict';
+
+const Code = require('@hapi/code');
+const Hawk = require('..');
+const Lab = require('@hapi/lab');
+
+
+const internals = {};
+
+
+const { describe, it } = exports.lab = Lab.script();
+const expect = Code.expect;
+
+
+describe('Crypto', () => {
+
+    describe('generateNormalizedString()', () => {
+
+        it('should return a valid normalized string', () => {
+
+            expect(Hawk.crypto.generateNormalizedString('header', {
+                ts: 1357747017,
+                nonce: 'k3k4j5',
+                method: 'GET',
+                resource: '/resource/something',
+                host: 'example.com',
+                port: 8080
+            })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\n\n\n');
+        });
+
+        it('should return a valid normalized string (ext)', () => {
+
+            expect(Hawk.crypto.generateNormalizedString('header', {
+                ts: 1357747017,
+                nonce: 'k3k4j5',
+                method: 'GET',
+                resource: '/resource/something',
+                host: 'example.com',
+                port: 8080,
+                ext: 'this is some app data'
+            })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\n\nthis is some app data\n');
+        });
+
+        it('should return a valid normalized string (payload + ext)', () => {
+
+            expect(Hawk.crypto.generateNormalizedString('header', {
+                ts: 1357747017,
+                nonce: 'k3k4j5',
+                method: 'GET',
+                resource: '/resource/something',
+                host: 'example.com',
+                port: 8080,
+                hash: 'U4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=',
+                ext: 'this is some app data'
+            })).to.equal('hawk.1.header\n1357747017\nk3k4j5\nGET\n/resource/something\nexample.com\n8080\nU4MKKSmiVxk37JCCrAVIjV/OhB3y+NdwoCr6RShbVkE=\nthis is some app data\n');
+        });
+    });
+});
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/index.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/index.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/index.js	(working copy)
@@ -1,378 +1,346 @@
-// Load modules
-
-var Url = require('url');
-var Code = require('code');
-var Hawk = require('../lib');
-var Lab = require('lab');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var lab = exports.lab = Lab.script();
-var describe = lab.experiment;
-var it = lab.test;
-var expect = Code.expect;
-
-
-describe('Hawk', function () {
-
-    var credentialsFunc = function (id, callback) {
-
-        var credentials = {
-            id: id,
-            key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-            algorithm: (id === '1' ? 'sha1' : 'sha256'),
-            user: 'steve'
-        };
-
-        return callback(null, credentials);
-    };
-
-    it('generates a header then successfully parse it (configuration)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials1) {
-
-            req.authorization = Hawk.client.header(Url.parse('http://example.com:8080/resource/4?filter=a'), req.method, { credentials: credentials1, ext: 'some-app-data' }).field;
-            expect(req.authorization).to.exist();
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
-
-                expect(err).to.not.exist();
-                expect(credentials2.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                done();
-            });
-        });
-    });
-
-    it('generates a header then successfully parse it (node request)', function (done) {
-
-        var req = {
-            method: 'POST',
-            url: '/resource/4?filter=a',
-            headers: {
-                host: 'example.com:8080',
-                'content-type': 'text/plain;x=y'
-            }
-        };
-
-        var payload = 'some not so random text';
-
-        credentialsFunc('123456', function (err, credentials1) {
-
-            var reqHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
-            req.headers.authorization = reqHeader.field;
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
-
-                expect(err).to.not.exist();
-                expect(credentials2.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true);
-
-                var res = {
-                    headers: {
-                        'content-type': 'text/plain'
-                    }
-                };
-
-                res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
-                expect(res.headers['server-authorization']).to.exist();
-
-                expect(Hawk.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.equal(true);
-                done();
-            });
-        });
-    });
-
-    it('generates a header then successfully parse it (absolute request uri)', function (done) {
-
-        var req = {
-            method: 'POST',
-            url: 'http://example.com:8080/resource/4?filter=a',
-            headers: {
-                host: 'example.com:8080',
-                'content-type': 'text/plain;x=y'
-            }
-        };
-
-        var payload = 'some not so random text';
-
-        credentialsFunc('123456', function (err, credentials1) {
-
-            var reqHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
-            req.headers.authorization = reqHeader.field;
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
-
-                expect(err).to.not.exist();
-                expect(credentials2.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true);
-
-                var res = {
-                    headers: {
-                        'content-type': 'text/plain'
-                    }
-                };
-
-                res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
-                expect(res.headers['server-authorization']).to.exist();
-
-                expect(Hawk.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.equal(true);
-                done();
-            });
-        });
-    });
-
-    it('generates a header then successfully parse it (no server header options)', function (done) {
-
-        var req = {
-            method: 'POST',
-            url: '/resource/4?filter=a',
-            headers: {
-                host: 'example.com:8080',
-                'content-type': 'text/plain;x=y'
-            }
-        };
-
-        var payload = 'some not so random text';
-
-        credentialsFunc('123456', function (err, credentials1) {
-
-            var reqHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
-            req.headers.authorization = reqHeader.field;
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
-
-                expect(err).to.not.exist();
-                expect(credentials2.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true);
-
-                var res = {
-                    headers: {
-                        'content-type': 'text/plain'
-                    }
-                };
-
-                res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts);
-                expect(res.headers['server-authorization']).to.exist();
-
-                expect(Hawk.client.authenticate(res, credentials2, artifacts)).to.equal(true);
-                done();
-            });
-        });
-    });
-
-    it('generates a header then fails to parse it (missing server header hash)', function (done) {
-
-        var req = {
-            method: 'POST',
-            url: '/resource/4?filter=a',
-            headers: {
-                host: 'example.com:8080',
-                'content-type': 'text/plain;x=y'
-            }
-        };
-
-        var payload = 'some not so random text';
-
-        credentialsFunc('123456', function (err, credentials1) {
-
-            var reqHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', payload: payload, contentType: req.headers['content-type'] });
-            req.headers.authorization = reqHeader.field;
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
-
-                expect(err).to.not.exist();
-                expect(credentials2.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.equal(true);
-
-                var res = {
-                    headers: {
-                        'content-type': 'text/plain'
-                    }
-                };
-
-                res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts);
-                expect(res.headers['server-authorization']).to.exist();
-
-                expect(Hawk.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.equal(false);
-                done();
-            });
-        });
-    });
-
-    it('generates a header then successfully parse it (with hash)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials1) {
-
-            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
-
-                expect(err).to.not.exist();
-                expect(credentials2.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                done();
-            });
-        });
-    });
-
-    it('generates a header then successfully parse it then validate payload', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials1) {
-
-            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
-
-                expect(err).to.not.exist();
-                expect(credentials2.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(Hawk.server.authenticatePayload('hola!', credentials2, artifacts)).to.be.true();
-                expect(Hawk.server.authenticatePayload('hello!', credentials2, artifacts)).to.be.false();
-                done();
-            });
-        });
-    });
-
-    it('generates a header then successfully parses and validates payload', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials1) {
-
-            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, { payload: 'hola!' }, function (err, credentials2, artifacts) {
-
-                expect(err).to.not.exist();
-                expect(credentials2.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                done();
-            });
-        });
-    });
-
-    it('generates a header then successfully parse it (app)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials1) {
-
-            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', app: 'asd23ased' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
-
-                expect(err).to.not.exist();
-                expect(credentials2.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(artifacts.app).to.equal('asd23ased');
-                done();
-            });
-        });
-    });
-
-    it('generates a header then successfully parse it (app, dlg)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials1) {
-
-            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', app: 'asd23ased', dlg: '23434szr3q4d' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
-
-                expect(err).to.not.exist();
-                expect(credentials2.user).to.equal('steve');
-                expect(artifacts.ext).to.equal('some-app-data');
-                expect(artifacts.app).to.equal('asd23ased');
-                expect(artifacts.dlg).to.equal('23434szr3q4d');
-                done();
-            });
-        });
-    });
-
-    it('generates a header then fail authentication due to bad hash', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials1) {
-
-            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).field;
-            Hawk.server.authenticate(req, credentialsFunc, { payload: 'byebye!' }, function (err, credentials2, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Bad payload hash');
-                done();
-            });
-        });
-    });
-
-    it('generates a header for one resource then fail to authenticate another', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?filter=a',
-            host: 'example.com',
-            port: 8080
-        };
-
-        credentialsFunc('123456', function (err, credentials1) {
-
-            req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data' }).field;
-            req.url = '/something/else';
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials2, artifacts) {
-
-                expect(err).to.exist();
-                expect(credentials2).to.exist();
-                done();
-            });
-        });
-    });
-});
+'use strict';
+
+const Url = require('url');
+
+const Code = require('@hapi/code');
+const Hawk = require('..');
+const Lab = require('@hapi/lab');
+
+
+const internals = {};
+
+
+const { describe, it } = exports.lab = Lab.script();
+const expect = Code.expect;
+
+
+describe('Hawk', () => {
+
+    const credentialsFunc = function (id) {
+
+        return {
+            id,
+            key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+            algorithm: (id === '1' ? 'sha1' : 'sha256'),
+            user: 'steve'
+        };
+    };
+
+    it('generates a header then successfully parse it (configuration)', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const credentials1 = credentialsFunc('123456');
+
+        req.authorization = Hawk.client.header(Url.parse('http://example.com:8080/resource/4?filter=a'), req.method, { credentials: credentials1, ext: 'some-app-data' }).header;
+        expect(req.authorization).to.exist();
+
+        const { credentials: credentials2, artifacts } = await Hawk.server.authenticate(req, credentialsFunc);
+        expect(credentials2.user).to.equal('steve');
+        expect(artifacts.ext).to.equal('some-app-data');
+    });
+
+    it('generates a header then successfully parse it (node request)', async () => {
+
+        const req = {
+            method: 'POST',
+            url: '/resource/4?filter=a',
+            headers: {
+                host: 'example.com:8080',
+                'content-type': 'text/plain;x=y'
+            }
+        };
+
+        const payload = 'some not so random text';
+
+        const credentials1 = credentialsFunc('123456');
+
+        const reqHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', payload, contentType: req.headers['content-type'] });
+        req.headers.authorization = reqHeader.header;
+
+        const { credentials: credentials2, artifacts } = await Hawk.server.authenticate(req, credentialsFunc);
+        expect(credentials2.user).to.equal('steve');
+        expect(artifacts.ext).to.equal('some-app-data');
+        expect(() => Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.not.throw();
+
+        const res = {
+            headers: {
+                'content-type': 'text/plain'
+            }
+        };
+
+        res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
+        expect(res.headers['server-authorization']).to.exist();
+
+        expect(() => Hawk.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.not.throw();
+    });
+
+    it('generates a header then successfully parse it (absolute request uri)', async () => {
+
+        const req = {
+            method: 'POST',
+            url: 'http://example.com:8080/resource/4?filter=a',
+            headers: {
+                host: 'example.com:8080',
+                'content-type': 'text/plain;x=y'
+            }
+        };
+
+        const payload = 'some not so random text';
+
+        const credentials1 = credentialsFunc('123456');
+
+        const reqHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', payload, contentType: req.headers['content-type'] });
+        req.headers.authorization = reqHeader.header;
+
+        const { credentials: credentials2, artifacts } = await Hawk.server.authenticate(req, credentialsFunc);
+        expect(credentials2.user).to.equal('steve');
+        expect(artifacts.ext).to.equal('some-app-data');
+        expect(() => Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.not.throw();
+
+        const res = {
+            headers: {
+                'content-type': 'text/plain'
+            }
+        };
+
+        res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
+        expect(res.headers['server-authorization']).to.exist();
+
+        expect(() => Hawk.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.not.throw();
+    });
+
+    it('generates a header then successfully parse it (no server header options)', async () => {
+
+        const req = {
+            method: 'POST',
+            url: '/resource/4?filter=a',
+            headers: {
+                host: 'example.com:8080',
+                'content-type': 'text/plain;x=y'
+            }
+        };
+
+        const payload = 'some not so random text';
+
+        const credentials1 = credentialsFunc('123456');
+
+        const reqHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', payload, contentType: req.headers['content-type'] });
+        req.headers.authorization = reqHeader.header;
+
+        const { credentials: credentials2, artifacts } = await Hawk.server.authenticate(req, credentialsFunc);
+        expect(credentials2.user).to.equal('steve');
+        expect(artifacts.ext).to.equal('some-app-data');
+        expect(() => Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.not.throw();
+
+        const res = {
+            headers: {
+                'content-type': 'text/plain'
+            }
+        };
+
+        res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts);
+        expect(res.headers['server-authorization']).to.exist();
+
+        expect(() => Hawk.client.authenticate(res, credentials2, artifacts)).to.not.throw();
+    });
+
+    it('generates a header then fails to parse it (missing server header hash)', async () => {
+
+        const req = {
+            method: 'POST',
+            url: '/resource/4?filter=a',
+            headers: {
+                host: 'example.com:8080',
+                'content-type': 'text/plain;x=y'
+            }
+        };
+
+        const payload = 'some not so random text';
+
+        const credentials1 = credentialsFunc('123456');
+
+        const reqHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', payload, contentType: req.headers['content-type'] });
+        req.headers.authorization = reqHeader.header;
+
+        const { credentials: credentials2, artifacts } = await Hawk.server.authenticate(req, credentialsFunc);
+        expect(credentials2.user).to.equal('steve');
+        expect(artifacts.ext).to.equal('some-app-data');
+        expect(() => Hawk.server.authenticatePayload(payload, credentials2, artifacts, req.headers['content-type'])).to.not.throw();
+
+        const res = {
+            headers: {
+                'content-type': 'text/plain'
+            }
+        };
+
+        res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts);
+        expect(res.headers['server-authorization']).to.exist();
+
+        expect(() => Hawk.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.throw('Missing response hash attribute');
+    });
+
+    it('generates a header then successfully parse it (with hash)', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const credentials1 = credentialsFunc('123456');
+
+        req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).header;
+        const { credentials: credentials2, artifacts } = await Hawk.server.authenticate(req, credentialsFunc);
+        expect(credentials2.user).to.equal('steve');
+        expect(artifacts.ext).to.equal('some-app-data');
+    });
+
+    it('generates a header then successfully parse it then validate payload', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const credentials1 = credentialsFunc('123456');
+
+        req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).header;
+        const { credentials: credentials2, artifacts } = await Hawk.server.authenticate(req, credentialsFunc);
+        expect(credentials2.user).to.equal('steve');
+        expect(artifacts.ext).to.equal('some-app-data');
+        expect(() => Hawk.server.authenticatePayload('hola!', credentials2, artifacts)).to.not.throw();
+        expect(() => Hawk.server.authenticatePayload('hello!', credentials2, artifacts)).to.throw('Bad payload hash');
+    });
+
+    it('generates a header then successfully parses and validates payload', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const credentials1 = credentialsFunc('123456');
+
+        req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, payload: 'hola!', ext: 'some-app-data' }).header;
+        const { credentials: credentials2, artifacts } = await Hawk.server.authenticate(req, credentialsFunc, { payload: 'hola!' });
+        expect(credentials2.user).to.equal('steve');
+        expect(artifacts.ext).to.equal('some-app-data');
+    });
+
+    it('generates a header then successfully parse it (app)', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const credentials1 = credentialsFunc('123456');
+
+        req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', app: 'asd23ased' }).header;
+        const { credentials: credentials2, artifacts } = await Hawk.server.authenticate(req, credentialsFunc);
+        expect(credentials2.user).to.equal('steve');
+        expect(artifacts.ext).to.equal('some-app-data');
+        expect(artifacts.app).to.equal('asd23ased');
+    });
+
+    it('generates a header then successfully parse it (app, dlg)', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const credentials1 = credentialsFunc('123456');
+
+        req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', app: 'asd23ased', dlg: '23434szr3q4d' }).header;
+        const { credentials: credentials2, artifacts } = await Hawk.server.authenticate(req, credentialsFunc);
+        expect(credentials2.user).to.equal('steve');
+        expect(artifacts.ext).to.equal('some-app-data');
+        expect(artifacts.app).to.equal('asd23ased');
+        expect(artifacts.dlg).to.equal('23434szr3q4d');
+    });
+
+    it('generates a header then fail authentication due to bad hash', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const credentials = credentialsFunc('123456');
+
+        req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials, payload: 'hola!', ext: 'some-app-data' }).header;
+        await expect(Hawk.server.authenticate(req, credentialsFunc, { payload: 'byebye!' })).to.reject('Bad payload hash');
+    });
+
+    it('generates a header for one resource then fail to authenticate another', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const credentials = credentialsFunc('123456');
+
+        req.authorization = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials, ext: 'some-app-data' }).header;
+        req.url = '/something/else';
+
+        const err = await expect(Hawk.server.authenticate(req, credentialsFunc)).to.reject();
+        expect(err.credentials).to.exist();
+    });
+
+    it('generates a header then fails to parse it (payload tampering)', async () => {
+
+        const req = {
+            method: 'POST',
+            url: '/resource/4?filter=a',
+            headers: {
+                host: 'example.com:8080',
+                'content-type': 'text/plain;x=y'
+            }
+        };
+
+        const payload = 'some not so random text';
+
+        const credentials1 = credentialsFunc('123456');
+
+        const reqHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', req.method, { credentials: credentials1, ext: 'some-app-data', payload, contentType: req.headers['content-type'] });
+        req.headers.authorization = reqHeader.header;
+
+        const { credentials: credentials2, artifacts } = await Hawk.server.authenticate(req, credentialsFunc);
+        expect(credentials2.user).to.equal('steve');
+        expect(artifacts.ext).to.equal('some-app-data');
+        expect(() => Hawk.server.authenticatePayload('tampered text', credentials2, artifacts, req.headers['content-type'])).to.throw('Bad payload hash');
+
+        const res = {
+            headers: {
+                'content-type': 'text/plain'
+            }
+        };
+
+        res.headers['server-authorization'] = Hawk.server.header(credentials2, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
+        expect(res.headers['server-authorization']).to.exist();
+
+        expect(() => Hawk.client.authenticate(res, credentials2, artifacts, { payload: 'some reply' })).to.not.throw();
+    });
+
+});
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/readme.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/readme.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/readme.js	(working copy)
@@ -1,95 +1,83 @@
-// Load modules
-
-var Code = require('code');
-var Hawk = require('../lib');
-var Hoek = require('hoek');
-var Lab = require('lab');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var lab = exports.lab = Lab.script();
-var describe = lab.experiment;
-var it = lab.test;
-var expect = Code.expect;
-
-
-describe('README', function () {
-
-    describe('core', function () {
-
-        var credentials = {
-            id: 'dh37fgj492je',
-            key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-            algorithm: 'sha256'
-        };
-
-        var options = {
-            credentials: credentials,
-            timestamp: 1353832234,
-            nonce: 'j4h3g2',
-            ext: 'some-app-ext-data'
-        };
-
-        it('should generate a header protocol example', function (done) {
-
-            var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', options).field;
-
-            expect(header).to.equal('Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="');
-            done();
-        });
-
-        it('should generate a normalized string protocol example', function (done) {
-
-            var normalized = Hawk.crypto.generateNormalizedString('header', {
-                credentials: credentials,
-                ts: options.timestamp,
-                nonce: options.nonce,
-                method: 'GET',
-                resource: '/resource?a=1&b=2',
-                host: 'example.com',
-                port: 8000,
-                ext: options.ext
-            });
-
-            expect(normalized).to.equal('hawk.1.header\n1353832234\nj4h3g2\nGET\n/resource?a=1&b=2\nexample.com\n8000\n\nsome-app-ext-data\n');
-            done();
-        });
-
-        var payloadOptions = Hoek.clone(options);
-        payloadOptions.payload = 'Thank you for flying Hawk';
-        payloadOptions.contentType = 'text/plain';
-
-        it('should generate a header protocol example (with payload)', function (done) {
-
-            var header = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'POST', payloadOptions).field;
-
-            expect(header).to.equal('Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=", ext="some-app-ext-data", mac="aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw="');
-            done();
-        });
-
-        it('should generate a normalized string protocol example (with payload)', function (done) {
-
-            var normalized = Hawk.crypto.generateNormalizedString('header', {
-                credentials: credentials,
-                ts: options.timestamp,
-                nonce: options.nonce,
-                method: 'POST',
-                resource: '/resource?a=1&b=2',
-                host: 'example.com',
-                port: 8000,
-                hash: Hawk.crypto.calculatePayloadHash(payloadOptions.payload, credentials.algorithm, payloadOptions.contentType),
-                ext: options.ext
-            });
-
-            expect(normalized).to.equal('hawk.1.header\n1353832234\nj4h3g2\nPOST\n/resource?a=1&b=2\nexample.com\n8000\nYi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=\nsome-app-ext-data\n');
-            done();
-        });
-    });
-});
-
+'use strict';
+
+const Code = require('@hapi/code');
+const Hawk = require('..');
+const Hoek = require('@hapi/hoek');
+const Lab = require('@hapi/lab');
+
+
+const internals = {};
+
+
+const { describe, it } = exports.lab = Lab.script();
+const expect = Code.expect;
+
+
+describe('README', () => {
+
+    describe('core', () => {
+
+        const credentials = {
+            id: 'dh37fgj492je',
+            key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+            algorithm: 'sha256'
+        };
+
+        const options = {
+            credentials,
+            timestamp: 1353832234,
+            nonce: 'j4h3g2',
+            ext: 'some-app-ext-data'
+        };
+
+        it('should generate a header protocol example', () => {
+
+            const { header } = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'GET', options);
+            expect(header).to.equal('Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", ext="some-app-ext-data", mac="6R4rV5iE+NPoym+WwjeHzjAGXUtLNIxmo1vpMofpLAE="');
+        });
+
+        it('should generate a normalized string protocol example', () => {
+
+            const normalized = Hawk.crypto.generateNormalizedString('header', {
+                credentials,
+                ts: options.timestamp,
+                nonce: options.nonce,
+                method: 'GET',
+                resource: '/resource/1?b=1&a=2',
+                host: 'example.com',
+                port: 8000,
+                ext: options.ext
+            });
+
+            expect(normalized).to.equal('hawk.1.header\n1353832234\nj4h3g2\nGET\n/resource/1?b=1&a=2\nexample.com\n8000\n\nsome-app-ext-data\n');
+        });
+
+        const payloadOptions = Hoek.clone(options);
+        payloadOptions.payload = 'Thank you for flying Hawk';
+        payloadOptions.contentType = 'text/plain';
+
+        it('should generate a header protocol example (with payload)', () => {
+
+            const { header } = Hawk.client.header('http://example.com:8000/resource/1?b=1&a=2', 'POST', payloadOptions);
+            expect(header).to.equal('Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=", ext="some-app-ext-data", mac="aSe1DERmZuRl3pI36/9BdZmnErTw3sNzOOAUlfeKjVw="');
+        });
+
+        it('should generate a normalized string protocol example (with payload)', () => {
+
+            const normalized = Hawk.crypto.generateNormalizedString('header', {
+                credentials,
+                ts: options.timestamp,
+                nonce: options.nonce,
+                method: 'POST',
+                resource: '/resource/1?b=1&a=2',
+                host: 'example.com',
+                port: 8000,
+                hash: Hawk.crypto.calculatePayloadHash(payloadOptions.payload, credentials.algorithm, payloadOptions.contentType),
+                ext: options.ext
+            });
+
+            expect(normalized).to.equal('hawk.1.header\n1353832234\nj4h3g2\nPOST\n/resource/1?b=1&a=2\nexample.com\n8000\nYi9LfIIFRtBEPt74PVmbTF/xVAwPn7ub15ePICfgnuY=\nsome-app-ext-data\n');
+        });
+    });
+});
+
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/server.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/server.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/server.js	(working copy)
@@ -1,1329 +1,1180 @@
-// Load modules
-
-var Url = require('url');
-var Code = require('code');
-var Hawk = require('../lib');
-var Hoek = require('hoek');
-var Lab = require('lab');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var lab = exports.lab = Lab.script();
-var describe = lab.experiment;
-var it = lab.test;
-var expect = Code.expect;
-
-
-describe('Server', function () {
-
-    var credentialsFunc = function (id, callback) {
-
-        var credentials = {
-            id: id,
-            key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-            algorithm: (id === '1' ? 'sha1' : 'sha256'),
-            user: 'steve'
-        };
-
-        return callback(null, credentials);
-    };
-
-    describe('authenticate()', function () {
-
-        it('parses a valid authentication header (sha1)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist();
-                expect(credentials.user).to.equal('steve');
-                done();
-            });
-        });
-
-        it('parses a valid authentication header (sha256)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/1?b=1&a=2',
-                host: 'example.com',
-                port: 8000,
-                authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="m8r1rHbXN6NgO+KIIhjO7sFRyd78RNGVUwehe8Cp2dU=", ext="some-app-data"'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353832234000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist();
-                expect(credentials.user).to.equal('steve');
-                done();
-            });
-        });
-
-        it('parses a valid authentication header (host override)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                headers: {
-                    host: 'example1.com:8080',
-                    authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"'
-                }
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { host: 'example.com', localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist();
-                expect(credentials.user).to.equal('steve');
-                done();
-            });
-        });
-
-        it('parses a valid authentication header (host port override)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                headers: {
-                    host: 'example1.com:80',
-                    authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"'
-                }
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { host: 'example.com', port: 8080, localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist();
-                expect(credentials.user).to.equal('steve');
-                done();
-            });
-        });
-
-        it('parses a valid authentication header (POST with payload)', function (done) {
-
-            var req = {
-                method: 'POST',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123456", ts="1357926341", nonce="1AwuJD", hash="qAiXIVv+yjDATneWxZP2YCTa9aHRgQdnH9b3Wc+o3dg=", ext="some-app-data", mac="UeYcj5UoTVaAWXNvJfLVia7kU3VabxCqrccXP8sUGC4="'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1357926341000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.not.exist();
-                expect(credentials.user).to.equal('steve');
-                done();
-            });
-        });
-
-        it('errors on missing hash', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/1?b=1&a=2',
-                host: 'example.com',
-                port: 8000,
-                authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="m8r1rHbXN6NgO+KIIhjO7sFRyd78RNGVUwehe8Cp2dU=", ext="some-app-data"'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { payload: 'body', localtimeOffsetMsec: 1353832234000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Missing required payload hash');
-                done();
-            });
-        });
-
-        it('errors on a stale timestamp', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123456", ts="1362337299", nonce="UzmxSs", ext="some-app-data", mac="wnNUxchvvryMH2RxckTdZ/gY3ijzvccx4keVvELC61w="'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Stale timestamp');
-                var header = err.output.headers['WWW-Authenticate'];
-                var ts = header.match(/^Hawk ts\=\"(\d+)\"\, tsm\=\"([^\"]+)\"\, error=\"Stale timestamp\"$/);
-                var now = Hawk.utils.now();
-                expect(parseInt(ts[1], 10) * 1000).to.be.within(now - 1000, now + 1000);
-
-                var res = {
-                    headers: {
-                        'www-authenticate': header
-                    }
-                };
-
-                expect(Hawk.client.authenticate(res, credentials, artifacts)).to.equal(true);
-                done();
-            });
-        });
-
-        it('errors on a replay', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="bXx7a7p1h9QYQNZ8x7QhvDQym8ACgab4m3lVSFn4DBw=", ext="hello"'
-            };
-
-            var memoryCache = {};
-            var options = {
-                localtimeOffsetMsec: 1353788437000 - Hawk.utils.now(),
-                nonceFunc: function (key, nonce, ts, callback) {
-
-                    if (memoryCache[key + nonce]) {
-                        return callback(new Error());
-                    }
-
-                    memoryCache[key + nonce] = true;
-                    return callback();
-                }
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, options, function (err, credentials1, artifacts1) {
-
-                expect(err).to.not.exist();
-                expect(credentials1.user).to.equal('steve');
-
-                Hawk.server.authenticate(req, credentialsFunc, options, function (err, credentials2, artifacts2) {
-
-                    expect(err).to.exist();
-                    expect(err.output.payload.message).to.equal('Invalid nonce');
-                    done();
-                });
-            });
-        });
-
-        it('does not error on nonce collision if keys differ', function (done) {
-
-            var reqSteve = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="bXx7a7p1h9QYQNZ8x7QhvDQym8ACgab4m3lVSFn4DBw=", ext="hello"'
-            };
-
-            var reqBob = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="456", ts="1353788437", nonce="k3j4h2", mac="LXfmTnRzrLd9TD7yfH+4se46Bx6AHyhpM94hLCiNia4=", ext="hello"'
-            };
-
-            var credentialsFuncion = function (id, callback) {
-
-                var credentials = {
-                    '123': {
-                        id: id,
-                        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                        algorithm: (id === '1' ? 'sha1' : 'sha256'),
-                        user: 'steve'
-                    },
-                    '456': {
-                        id: id,
-                        key: 'xrunpaw3489ruxnpa98w4rxnwerxhqb98rpaxn39848',
-                        algorithm: (id === '1' ? 'sha1' : 'sha256'),
-                        user: 'bob'
-                    }
-                };
-
-                return callback(null, credentials[id]);
-            };
-
-            var memoryCache = {};
-            var options = {
-                localtimeOffsetMsec: 1353788437000 - Hawk.utils.now(),
-                nonceFunc: function (key, nonce, ts, callback) {
-
-                    if (memoryCache[key + nonce]) {
-                        return callback(new Error());
-                    }
-
-                    memoryCache[key + nonce] = true;
-                    return callback();
-                }
-            };
-
-            Hawk.server.authenticate(reqSteve, credentialsFuncion, options, function (err, credentials1, artifacts1) {
-
-                expect(err).to.not.exist();
-                expect(credentials1.user).to.equal('steve');
-
-                Hawk.server.authenticate(reqBob, credentialsFuncion, options, function (err, credentials2, artifacts2) {
-
-                    expect(err).to.not.exist();
-                    expect(credentials2.user).to.equal('bob');
-                    done();
-                });
-            });
-        });
-
-        it('errors on an invalid authentication header: wrong scheme', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Basic asdasdasdasd'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.not.exist();
-                done();
-            });
-        });
-
-        it('errors on an invalid authentication header: no scheme', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: '!@#'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Invalid header syntax');
-                done();
-            });
-        });
-
-        it('errors on an missing authorization header', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, {}, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.isMissing).to.equal(true);
-                done();
-            });
-        });
-
-        it('errors on an missing host header', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                headers: {
-                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                }
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Invalid Host header');
-                done();
-            });
-        });
-
-        it('errors on an missing authorization attribute (id)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Missing attributes');
-                done();
-            });
-        });
-
-        it('errors on an missing authorization attribute (ts)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Missing attributes');
-                done();
-            });
-        });
-
-        it('errors on an missing authorization attribute (nonce)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123", ts="1353788437", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Missing attributes');
-                done();
-            });
-        });
-
-        it('errors on an missing authorization attribute (mac)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", ext="hello"'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Missing attributes');
-                done();
-            });
-        });
-
-        it('errors on an unknown authorization attribute', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", x="3", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Unknown attribute: x');
-                done();
-            });
-        });
-
-        it('errors on an bad authorization header format', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123\\", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Bad header format');
-                done();
-            });
-        });
-
-        it('errors on an bad authorization attribute value', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="\t", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Bad attribute value: id');
-                done();
-            });
-        });
-
-        it('errors on an empty authorization attribute value', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Bad attribute value: id');
-                done();
-            });
-        });
-
-        it('errors on duplicated authorization attribute key', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123", id="456", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Duplicate attribute: id');
-                done();
-            });
-        });
-
-        it('errors on an invalid authorization header format', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk'
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Invalid header syntax');
-                done();
-            });
-        });
-
-        it('errors on an bad host header (missing host)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                headers: {
-                    host: ':8080',
-                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                }
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Invalid Host header');
-                done();
-            });
-        });
-
-        it('errors on an bad host header (pad port)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                headers: {
-                    host: 'example.com:something',
-                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-                }
-            };
-
-            Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Invalid Host header');
-                done();
-            });
-        });
-
-        it('errors on credentialsFunc error', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-            };
-
-            var credentialsFuncion = function (id, callback) {
-
-                return callback(new Error('Unknown user'));
-            };
-
-            Hawk.server.authenticate(req, credentialsFuncion, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.message).to.equal('Unknown user');
-                done();
-            });
-        });
-
-        it('errors on credentialsFunc error (with credentials)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-            };
-
-            var credentialsFuncion = function (id, callback) {
-
-                return callback(new Error('Unknown user'), { some: 'value' });
-            };
-
-            Hawk.server.authenticate(req, credentialsFuncion, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.message).to.equal('Unknown user');
-                expect(credentials.some).to.equal('value');
-                done();
-            });
-        });
-
-        it('errors on missing credentials', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-            };
-
-            var credentialsFuncion = function (id, callback) {
-
-                return callback(null, null);
-            };
-
-            Hawk.server.authenticate(req, credentialsFuncion, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Unknown credentials');
-                done();
-            });
-        });
-
-        it('errors on invalid credentials (id)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-            };
-
-            var credentialsFuncion = function (id, callback) {
-
-                var credentials = {
-                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                    user: 'steve'
-                };
-
-                return callback(null, credentials);
-            };
-
-            Hawk.server.authenticate(req, credentialsFuncion, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.message).to.equal('Invalid credentials');
-                expect(err.output.payload.message).to.equal('An internal server error occurred');
-                done();
-            });
-        });
-
-        it('errors on invalid credentials (key)', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-            };
-
-            var credentialsFuncion = function (id, callback) {
-
-                var credentials = {
-                    id: '23434d3q4d5345d',
-                    user: 'steve'
-                };
-
-                return callback(null, credentials);
-            };
-
-            Hawk.server.authenticate(req, credentialsFuncion, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.message).to.equal('Invalid credentials');
-                expect(err.output.payload.message).to.equal('An internal server error occurred');
-                done();
-            });
-        });
-
-        it('errors on unknown credentials algorithm', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-            };
-
-            var credentialsFuncion = function (id, callback) {
-
-                var credentials = {
-                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                    algorithm: 'hmac-sha-0',
-                    user: 'steve'
-                };
-
-                return callback(null, credentials);
-            };
-
-            Hawk.server.authenticate(req, credentialsFuncion, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.message).to.equal('Unknown algorithm');
-                expect(err.output.payload.message).to.equal('An internal server error occurred');
-                done();
-            });
-        });
-
-        it('errors on unknown bad mac', function (done) {
-
-            var req = {
-                method: 'GET',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcU4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
-            };
-
-            var credentialsFuncion = function (id, callback) {
-
-                var credentials = {
-                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                    algorithm: 'sha256',
-                    user: 'steve'
-                };
-
-                return callback(null, credentials);
-            };
-
-            Hawk.server.authenticate(req, credentialsFuncion, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() }, function (err, credentials, artifacts) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Bad mac');
-                done();
-            });
-        });
-    });
-
-    describe('header()', function () {
-
-        it('generates header', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                algorithm: 'sha256',
-                user: 'steve'
-            };
-
-            var artifacts = {
-                method: 'POST',
-                host: 'example.com',
-                port: '8080',
-                resource: '/resource/4?filter=a',
-                ts: '1398546787',
-                nonce: 'xUwusx',
-                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
-                ext: 'some-app-data',
-                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
-                id: '123456'
-            };
-
-            var header = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
-            expect(header).to.equal('Hawk mac=\"n14wVJK4cOxAytPUMc5bPezQzuJGl5n7MYXhFQgEKsE=\", hash=\"f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=\", ext=\"response-specific\"');
-            done();
-        });
-
-        it('generates header (empty payload)', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                algorithm: 'sha256',
-                user: 'steve'
-            };
-
-            var artifacts = {
-                method: 'POST',
-                host: 'example.com',
-                port: '8080',
-                resource: '/resource/4?filter=a',
-                ts: '1398546787',
-                nonce: 'xUwusx',
-                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
-                ext: 'some-app-data',
-                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
-                id: '123456'
-            };
-
-            var header = Hawk.server.header(credentials, artifacts, { payload: '', contentType: 'text/plain', ext: 'response-specific' });
-            expect(header).to.equal('Hawk mac=\"i8/kUBDx0QF+PpCtW860kkV/fa9dbwEoe/FpGUXowf0=\", hash=\"q/t+NNAkQZNlq/aAD6PlexImwQTxwgT2MahfTa9XRLA=\", ext=\"response-specific\"');
-            done();
-        });
-
-        it('generates header (pre calculated hash)', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                algorithm: 'sha256',
-                user: 'steve'
-            };
-
-            var artifacts = {
-                method: 'POST',
-                host: 'example.com',
-                port: '8080',
-                resource: '/resource/4?filter=a',
-                ts: '1398546787',
-                nonce: 'xUwusx',
-                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
-                ext: 'some-app-data',
-                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
-                id: '123456'
-            };
-
-            var options = { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' };
-            options.hash = Hawk.crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
-            var header = Hawk.server.header(credentials, artifacts, options);
-            expect(header).to.equal('Hawk mac=\"n14wVJK4cOxAytPUMc5bPezQzuJGl5n7MYXhFQgEKsE=\", hash=\"f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=\", ext=\"response-specific\"');
-            done();
-        });
-
-        it('generates header (null ext)', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                algorithm: 'sha256',
-                user: 'steve'
-            };
-
-            var artifacts = {
-                method: 'POST',
-                host: 'example.com',
-                port: '8080',
-                resource: '/resource/4?filter=a',
-                ts: '1398546787',
-                nonce: 'xUwusx',
-                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
-                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
-                id: '123456'
-            };
-
-            var header = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: null });
-            expect(header).to.equal('Hawk mac=\"6PrybJTJs20jsgBw5eilXpcytD8kUbaIKNYXL+6g0ns=\", hash=\"f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=\"');
-            done();
-        });
-
-        it('errors on missing artifacts', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                algorithm: 'sha256',
-                user: 'steve'
-            };
-
-            var header = Hawk.server.header(credentials, null, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
-            expect(header).to.equal('');
-            done();
-        });
-
-        it('errors on invalid artifacts', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                algorithm: 'sha256',
-                user: 'steve'
-            };
-
-            var header = Hawk.server.header(credentials, 5, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
-            expect(header).to.equal('');
-            done();
-        });
-
-        it('errors on missing credentials', function (done) {
-
-            var artifacts = {
-                method: 'POST',
-                host: 'example.com',
-                port: '8080',
-                resource: '/resource/4?filter=a',
-                ts: '1398546787',
-                nonce: 'xUwusx',
-                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
-                ext: 'some-app-data',
-                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
-                id: '123456'
-            };
-
-            var header = Hawk.server.header(null, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
-            expect(header).to.equal('');
-            done();
-        });
-
-        it('errors on invalid credentials (key)', function (done) {
-
-            var credentials = {
-                id: '123456',
-                algorithm: 'sha256',
-                user: 'steve'
-            };
-
-            var artifacts = {
-                method: 'POST',
-                host: 'example.com',
-                port: '8080',
-                resource: '/resource/4?filter=a',
-                ts: '1398546787',
-                nonce: 'xUwusx',
-                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
-                ext: 'some-app-data',
-                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
-                id: '123456'
-            };
-
-            var header = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
-            expect(header).to.equal('');
-            done();
-        });
-
-        it('errors on invalid algorithm', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-                algorithm: 'x',
-                user: 'steve'
-            };
-
-            var artifacts = {
-                method: 'POST',
-                host: 'example.com',
-                port: '8080',
-                resource: '/resource/4?filter=a',
-                ts: '1398546787',
-                nonce: 'xUwusx',
-                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
-                ext: 'some-app-data',
-                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
-                id: '123456'
-            };
-
-            var header = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
-            expect(header).to.equal('');
-            done();
-        });
-    });
-
-    describe('authenticateBewit()', function () {
-
-        it('errors on uri too long', function (done) {
-
-            var long = '/';
-            for (var i = 0; i < 5000; ++i) {
-                long += 'x';
-            }
-
-            var req = {
-                method: 'GET',
-                url: long,
-                host: 'example.com',
-                port: 8080,
-                authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"'
-            };
-
-            Hawk.server.authenticateBewit(req, credentialsFunc, {}, function (err, credentials, bewit) {
-
-                expect(err).to.exist();
-                expect(err.output.statusCode).to.equal(400);
-                expect(err.message).to.equal('Resource path exceeds max length');
-                done();
-            });
-        });
-    });
-
-    describe('authenticateMessage()', function () {
-
-        it('errors on invalid authorization (ts)', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                delete auth.ts;
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Invalid authorization');
-                    done();
-                });
-            });
-        });
-
-        it('errors on invalid authorization (nonce)', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                delete auth.nonce;
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Invalid authorization');
-                    done();
-                });
-            });
-        });
-
-        it('errors on invalid authorization (hash)', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                delete auth.hash;
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Invalid authorization');
-                    done();
-                });
-            });
-        });
-
-        it('errors with credentials', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, function (id, callback) {
-
-                    callback(new Error('something'), { some: 'value' });
-                }, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('something');
-                    expect(credentials2.some).to.equal('value');
-                    done();
-                });
-            });
-        });
-
-        it('errors on nonce collision', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {
-                    nonceFunc: function (key, nonce, ts, nonceCallback) {
-
-                        nonceCallback(true);
-                    }
-                }, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Invalid nonce');
-                    done();
-                });
-            });
-        });
-
-        it('should generate an authorization then successfully parse it', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.not.exist();
-                    expect(credentials2.user).to.equal('steve');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on mismatching host', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                Hawk.server.authenticateMessage('example1.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Bad mac');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on stale timestamp', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { localtimeOffsetMsec: 100000 }, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Stale timestamp');
-                    done();
-                });
-            });
-        });
-
-        it('overrides timestampSkewSec', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1, localtimeOffsetMsec: 100000 });
-                expect(auth).to.exist();
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { timestampSkewSec: 500 }, function (err, credentials2) {
-
-                    expect(err).to.not.exist();
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on invalid authorization', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-                delete auth.id;
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Invalid authorization');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on bad hash', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message1', auth, credentialsFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Bad message hash');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on nonce error', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {
-                    nonceFunc: function (key, nonce, ts, callback) {
-
-                        callback(new Error('kaboom'));
-                    }
-                }, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Invalid nonce');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on credentials error', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                var errFunc = function (id, callback) {
-
-                    callback(new Error('kablooey'));
-                };
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('kablooey');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on missing credentials', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                var errFunc = function (id, callback) {
-
-                    callback();
-                };
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Unknown credentials');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on invalid credentials', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                var errFunc = function (id, callback) {
-
-                    callback(null, {});
-                };
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Invalid credentials');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on invalid credentials algorithm', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                var errFunc = function (id, callback) {
-
-                    callback(null, { key: '123', algorithm: '456' });
-                };
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Unknown algorithm');
-                    done();
-                });
-            });
-        });
-
-        it('should fail on missing host', function (done) {
-
-            credentialsFunc('123456', function (err, credentials) {
-
-                var auth = Hawk.client.message(null, 8080, 'some message', { credentials: credentials });
-                expect(auth).to.not.exist();
-                done();
-            });
-        });
-
-        it('should fail on missing credentials', function (done) {
-
-            var auth = Hawk.client.message('example.com', 8080, 'some message', {});
-            expect(auth).to.not.exist();
-            done();
-        });
-
-        it('should fail on invalid algorithm', function (done) {
-
-            credentialsFunc('123456', function (err, credentials) {
-
-                var creds = Hoek.clone(credentials);
-                creds.algorithm = 'blah';
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: creds });
-                expect(auth).to.not.exist();
-                done();
-            });
-        });
-    });
-
-    describe('authenticatePayloadHash()', function () {
-
-        it('checks payload hash', function (done) {
-
-            expect(Hawk.server.authenticatePayloadHash('abcdefg', { hash: 'abcdefg' })).to.equal(true);
-            expect(Hawk.server.authenticatePayloadHash('1234567', { hash: 'abcdefg' })).to.equal(false);
-            done();
-        });
-    });
-});
-
+'use strict';
+
+const Code = require('@hapi/code');
+const Hawk = require('..');
+const Hoek = require('@hapi/hoek');
+const Lab = require('@hapi/lab');
+
+
+const internals = {};
+
+
+const { describe, it } = exports.lab = Lab.script();
+const expect = Code.expect;
+
+
+describe('Server', () => {
+
+    const credentialsFunc = function (id) {
+
+        return {
+            id,
+            key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+            algorithm: (id === '1' ? 'sha1' : 'sha256'),
+            user: 'steve'
+        };
+    };
+
+    describe('authenticate()', () => {
+
+        it('parses a valid authentication header (sha1)', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"'
+            };
+
+            const { credentials } = await Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() });
+            expect(credentials.user).to.equal('steve');
+        });
+
+        it('parses a valid authentication header (sha256)', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/1?b=1&a=2',
+                host: 'example.com',
+                port: 8000,
+                authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="m8r1rHbXN6NgO+KIIhjO7sFRyd78RNGVUwehe8Cp2dU=", ext="some-app-data"'
+            };
+
+            const { credentials } = await Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353832234000 - Hawk.utils.now() });
+            expect(credentials.user).to.equal('steve');
+        });
+
+        it('parses a valid authentication header (host override)', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                headers: {
+                    host: 'example1.com:8080',
+                    authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"'
+                }
+            };
+
+            const { credentials } = await Hawk.server.authenticate(req, credentialsFunc, { host: 'example.com', localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() });
+            expect(credentials.user).to.equal('steve');
+        });
+
+        it('parses a valid authentication header (host port override)', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                headers: {
+                    host: 'example1.com:80',
+                    authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"'
+                }
+            };
+
+            const { credentials } = await Hawk.server.authenticate(req, credentialsFunc, { host: 'example.com', port: 8080, localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() });
+            expect(credentials.user).to.equal('steve');
+        });
+
+        it('parses a valid authentication header (POST with payload)', async () => {
+
+            const req = {
+                method: 'POST',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123456", ts="1357926341", nonce="1AwuJD", hash="qAiXIVv+yjDATneWxZP2YCTa9aHRgQdnH9b3Wc+o3dg=", ext="some-app-data", mac="UeYcj5UoTVaAWXNvJfLVia7kU3VabxCqrccXP8sUGC4="'
+            };
+
+            const { credentials } = await Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1357926341000 - Hawk.utils.now() });
+            expect(credentials.user).to.equal('steve');
+        });
+
+        it('errors on missing hash', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/1?b=1&a=2',
+                host: 'example.com',
+                port: 8000,
+                authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="m8r1rHbXN6NgO+KIIhjO7sFRyd78RNGVUwehe8Cp2dU=", ext="some-app-data"'
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { payload: 'body', localtimeOffsetMsec: 1353832234000 - Hawk.utils.now() })).to.reject('Missing required payload hash');
+        });
+
+        it('errors on missing hash (empty payload)', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/1?b=1&a=2',
+                host: 'example.com',
+                port: 8000,
+                authorization: 'Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", mac="m8r1rHbXN6NgO+KIIhjO7sFRyd78RNGVUwehe8Cp2dU=", ext="some-app-data"'
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { payload: '', localtimeOffsetMsec: 1353832234000 - Hawk.utils.now() })).to.reject('Missing required payload hash');
+        });
+
+        it('errors on a stale timestamp', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123456", ts="1362337299", nonce="UzmxSs", ext="some-app-data", mac="wnNUxchvvryMH2RxckTdZ/gY3ijzvccx4keVvELC61w="'
+            };
+
+            const err = await expect(Hawk.server.authenticate(req, credentialsFunc)).to.reject('Stale timestamp');
+            const header = err.output.headers['WWW-Authenticate'];
+            const ts = header.match(/^Hawk ts\=\"(\d+)\"\, tsm\=\"([^\"]+)\"\, error=\"Stale timestamp\"$/);
+            const now = Hawk.utils.now();
+            expect(parseInt(ts[1], 10) * 1000).to.be.within(now - 1000, now + 1000);
+
+            const res = {
+                headers: {
+                    'www-authenticate': header
+                }
+            };
+
+            expect(() => Hawk.client.authenticate(res, err.credentials, err.artifacts)).to.not.throw();
+        });
+
+        it('errors on a replay', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="bXx7a7p1h9QYQNZ8x7QhvDQym8ACgab4m3lVSFn4DBw=", ext="hello"'
+            };
+
+            const memoryCache = {};
+            const options = {
+                localtimeOffsetMsec: 1353788437000 - Hawk.utils.now(),
+                nonceFunc: function (key, nonce, ts) {
+
+                    if (memoryCache[key + nonce]) {
+                        throw new Error();
+                    }
+
+                    memoryCache[key + nonce] = true;
+                }
+            };
+
+            const { credentials } = await Hawk.server.authenticate(req, credentialsFunc, options);
+            expect(credentials.user).to.equal('steve');
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, options)).to.reject('Invalid nonce');
+        });
+
+        it('does not error on nonce collision if keys differ', async () => {
+
+            const reqSteve = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="bXx7a7p1h9QYQNZ8x7QhvDQym8ACgab4m3lVSFn4DBw=", ext="hello"'
+            };
+
+            const reqBob = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="456", ts="1353788437", nonce="k3j4h2", mac="LXfmTnRzrLd9TD7yfH+4se46Bx6AHyhpM94hLCiNia4=", ext="hello"'
+            };
+
+            const credentialsFuncion = function (id) {
+
+                const credentials = {
+                    '123': {
+                        id,
+                        key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                        algorithm: (id === '1' ? 'sha1' : 'sha256'),
+                        user: 'steve'
+                    },
+                    '456': {
+                        id,
+                        key: 'xrunpaw3489ruxnpa98w4rxnwerxhqb98rpaxn39848',
+                        algorithm: (id === '1' ? 'sha1' : 'sha256'),
+                        user: 'bob'
+                    }
+                };
+
+                return credentials[id];
+            };
+
+            const memoryCache = {};
+            const options = {
+                localtimeOffsetMsec: 1353788437000 - Hawk.utils.now(),
+                nonceFunc: function (key, nonce, ts) {
+
+                    if (memoryCache[key + nonce]) {
+                        throw new Error();
+                    }
+
+                    memoryCache[key + nonce] = true;
+                }
+            };
+
+            const { credentials: credentials1 } = await Hawk.server.authenticate(reqSteve, credentialsFuncion, options);
+            expect(credentials1.user).to.equal('steve');
+
+            const { credentials: credentials2 } = await Hawk.server.authenticate(reqBob, credentialsFuncion, options);
+            expect(credentials2.user).to.equal('bob');
+        });
+
+        it('errors on an invalid authentication header: wrong scheme', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Basic asdasdasdasd'
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Unauthorized');
+        });
+
+        it('errors on an invalid authentication header: no scheme', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: '!@#'
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Invalid header syntax');
+        });
+
+        it('errors on an missing authorization header', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080
+            };
+
+            const err = await expect(Hawk.server.authenticate(req, credentialsFunc)).to.reject();
+            expect(err.isMissing).to.equal(true);
+        });
+
+        it('errors on an missing host header', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                headers: {
+                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                }
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Invalid Host header');
+        });
+
+        it('errors on an missing authorization attribute (id)', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Missing attributes');
+        });
+
+        it('errors on an missing authorization attribute (ts)', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Missing attributes');
+        });
+
+        it('errors on an missing authorization attribute (nonce)', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123", ts="1353788437", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Missing attributes');
+        });
+
+        it('errors on an missing authorization attribute (mac)', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", ext="hello"'
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Missing attributes');
+        });
+
+        it('errors on an unknown authorization attribute', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", x="3", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Unknown attribute: x');
+        });
+
+        it('errors on an bad authorization header format', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123\\", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Bad header format');
+        });
+
+        it('errors on an bad authorization attribute value', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="\t", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Bad attribute value: id');
+        });
+
+        it('errors on an empty authorization attribute value', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Bad attribute value: id');
+        });
+
+        it('errors on duplicated authorization attribute key', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123", id="456", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Duplicate attribute: id');
+        });
+
+        it('errors on an invalid authorization header format', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk'
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Invalid header syntax');
+        });
+
+        it('errors on an bad host header (missing host)', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                headers: {
+                    host: ':8080',
+                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                }
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Invalid Host header');
+        });
+
+        it('errors on an bad host header (includes path and query)', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                headers: {
+                    host: 'example.com:8080/path?x=z',
+                    authorization: 'Hawk'
+                }
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Invalid Host header');
+        });
+
+        it('errors on an bad host header (pad port)', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                headers: {
+                    host: 'example.com:something',
+                    authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+                }
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Invalid Host header');
+        });
+
+        it('errors on credentialsFunc error', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+            };
+
+            const credentialsFuncion = function (id) {
+
+                throw new Error('Unknown user');
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFuncion, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Unknown user');
+        });
+
+        it('errors on credentialsFunc error (with credentials)', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+            };
+
+            const credentialsFuncion = function (id) {
+
+                const error = new Error('Unknown user');
+                error.credentials = { some: 'value' };
+                throw error;
+            };
+
+            const err = await expect(Hawk.server.authenticate(req, credentialsFuncion, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Unknown user');
+            expect(err.credentials.some).to.equal('value');
+        });
+
+        it('errors on missing credentials', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+            };
+
+            const credentialsFuncion = function (id) {
+
+                return null;
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFuncion, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Unknown credentials');
+        });
+
+        it('errors on invalid credentials (id)', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+            };
+
+            const credentialsFuncion = function (id) {
+
+                return {
+                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                    user: 'steve'
+                };
+            };
+
+            const err = await expect(Hawk.server.authenticate(req, credentialsFuncion, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Invalid credentials');
+            expect(err.output.payload.message).to.equal('An internal server error occurred');
+        });
+
+        it('errors on invalid credentials (key)', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+            };
+
+            const credentialsFuncion = function (id) {
+
+                return {
+                    id: '23434d3q4d5345d',
+                    user: 'steve'
+                };
+            };
+
+            const err = await expect(Hawk.server.authenticate(req, credentialsFuncion, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Invalid credentials');
+            expect(err.output.payload.message).to.equal('An internal server error occurred');
+        });
+
+        it('errors on unknown credentials algorithm', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcUyW6EEgUH4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+            };
+
+            const credentialsFuncion = function (id) {
+
+                return {
+                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                    algorithm: 'hmac-sha-0',
+                    user: 'steve'
+                };
+            };
+
+            const err = await expect(Hawk.server.authenticate(req, credentialsFuncion, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Unknown algorithm');
+            expect(err.output.payload.message).to.equal('An internal server error occurred');
+        });
+
+        it('errors on unknown bad mac', async () => {
+
+            const req = {
+                method: 'GET',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="123", ts="1353788437", nonce="k3j4h2", mac="/qwS4UjfVWMcU4jlr7T/wuKe3dKijvTvSos=", ext="hello"'
+            };
+
+            const credentialsFuncion = function (id) {
+
+                return {
+                    key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                    algorithm: 'sha256',
+                    user: 'steve'
+                };
+            };
+
+            await expect(Hawk.server.authenticate(req, credentialsFuncion, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Bad mac');
+        });
+    });
+
+    describe('header()', () => {
+
+        it('generates header', () => {
+
+            const credentials = {
+                id: '123456',
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            const artifacts = {
+                method: 'POST',
+                host: 'example.com',
+                port: '8080',
+                resource: '/resource/4?filter=a',
+                ts: '1398546787',
+                nonce: 'xUwusx',
+                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                ext: 'some-app-data',
+                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
+                id: '123456'
+            };
+
+            const header = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' });
+            expect(header).to.equal('Hawk mac=\"n14wVJK4cOxAytPUMc5bPezQzuJGl5n7MYXhFQgEKsE=\", hash=\"f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=\", ext=\"response-specific\"');
+        });
+
+        it('generates header (empty payload)', () => {
+
+            const credentials = {
+                id: '123456',
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            const artifacts = {
+                method: 'POST',
+                host: 'example.com',
+                port: '8080',
+                resource: '/resource/4?filter=a',
+                ts: '1398546787',
+                nonce: 'xUwusx',
+                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                ext: 'some-app-data',
+                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
+                id: '123456'
+            };
+
+            const header = Hawk.server.header(credentials, artifacts, { payload: '', contentType: 'text/plain', ext: 'response-specific' });
+            expect(header).to.equal('Hawk mac=\"i8/kUBDx0QF+PpCtW860kkV/fa9dbwEoe/FpGUXowf0=\", hash=\"q/t+NNAkQZNlq/aAD6PlexImwQTxwgT2MahfTa9XRLA=\", ext=\"response-specific\"');
+        });
+
+        it('generates header (empty ext)', () => {
+
+            const credentials = {
+                id: '123456',
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            const artifacts = {
+                method: 'POST',
+                host: 'example.com',
+                port: '8080',
+                resource: '/resource/4?filter=a',
+                ts: '1398546787',
+                nonce: 'xUwusx',
+                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                ext: '',
+                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
+                id: '123456'
+            };
+
+            const header = Hawk.server.header(credentials, artifacts, { payload: '', contentType: 'text/plain', ext: '' });
+            expect(header).to.equal('Hawk mac=\"q+fdjQv3kF56JGKLYeLzAS9dYGcvDqAXRG7MTVHAFKE=\", hash=\"q/t+NNAkQZNlq/aAD6PlexImwQTxwgT2MahfTa9XRLA=\"');
+        });
+
+        it('generates header (pre calculated hash)', () => {
+
+            const credentials = {
+                id: '123456',
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            const artifacts = {
+                method: 'POST',
+                host: 'example.com',
+                port: '8080',
+                resource: '/resource/4?filter=a',
+                ts: '1398546787',
+                nonce: 'xUwusx',
+                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                ext: 'some-app-data',
+                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
+                id: '123456'
+            };
+
+            const options = { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' };
+            options.hash = Hawk.crypto.calculatePayloadHash(options.payload, credentials.algorithm, options.contentType);
+            const header = Hawk.server.header(credentials, artifacts, options);
+            expect(header).to.equal('Hawk mac=\"n14wVJK4cOxAytPUMc5bPezQzuJGl5n7MYXhFQgEKsE=\", hash=\"f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=\", ext=\"response-specific\"');
+        });
+
+        it('generates header (null ext)', () => {
+
+            const credentials = {
+                id: '123456',
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            const artifacts = {
+                method: 'POST',
+                host: 'example.com',
+                port: '8080',
+                resource: '/resource/4?filter=a',
+                ts: '1398546787',
+                nonce: 'xUwusx',
+                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
+                id: '123456'
+            };
+
+            const header = Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: null });
+            expect(header).to.equal('Hawk mac=\"6PrybJTJs20jsgBw5eilXpcytD8kUbaIKNYXL+6g0ns=\", hash=\"f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=\"');
+        });
+
+        it('errors on missing artifacts', () => {
+
+            const credentials = {
+                id: '123456',
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            expect(() => Hawk.server.header(credentials, null, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' })).to.throw('Invalid inputs');
+        });
+
+        it('errors on invalid artifacts', () => {
+
+            const credentials = {
+                id: '123456',
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            expect(() => Hawk.server.header(credentials, 5, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' })).to.throw('Invalid inputs');
+        });
+
+        it('errors on missing credentials', () => {
+
+            const artifacts = {
+                method: 'POST',
+                host: 'example.com',
+                port: '8080',
+                resource: '/resource/4?filter=a',
+                ts: '1398546787',
+                nonce: 'xUwusx',
+                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                ext: 'some-app-data',
+                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
+                id: '123456'
+            };
+
+            expect(() => Hawk.server.header(null, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' })).to.throw('Invalid credentials');
+        });
+
+        it('errors on invalid credentials (key)', () => {
+
+            const credentials = {
+                id: '123456',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            const artifacts = {
+                method: 'POST',
+                host: 'example.com',
+                port: '8080',
+                resource: '/resource/4?filter=a',
+                ts: '1398546787',
+                nonce: 'xUwusx',
+                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                ext: 'some-app-data',
+                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
+                id: '123456'
+            };
+
+            expect(() => Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' })).to.throw('Invalid credentials');
+        });
+
+        it('errors on invalid credentials (algorithm)', () => {
+
+            const credentials = {
+                id: '123456',
+                key: 'asdasd',
+                user: 'steve'
+            };
+
+            const artifacts = {
+                method: 'POST',
+                host: 'example.com',
+                port: '8080',
+                resource: '/resource/4?filter=a',
+                ts: '1398546787',
+                nonce: 'xUwusx',
+                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                ext: 'some-app-data',
+                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
+                id: '123456'
+            };
+
+            expect(() => Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' })).to.throw('Invalid credentials');
+        });
+
+        it('errors on invalid algorithm', () => {
+
+            const credentials = {
+                id: '123456',
+                key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+                algorithm: 'x',
+                user: 'steve'
+            };
+
+            const artifacts = {
+                method: 'POST',
+                host: 'example.com',
+                port: '8080',
+                resource: '/resource/4?filter=a',
+                ts: '1398546787',
+                nonce: 'xUwusx',
+                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                ext: 'some-app-data',
+                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
+                id: '123456'
+            };
+
+            expect(() => Hawk.server.header(credentials, artifacts, { payload: 'some reply', contentType: 'text/plain', ext: 'response-specific' })).to.throw('Unknown algorithm');
+        });
+
+        it('errors on invalid options', () => {
+
+            const credentials = {
+                id: '123456',
+                algorithm: 'sha256',
+                user: 'steve'
+            };
+
+            const artifacts = {
+                method: 'POST',
+                host: 'example.com',
+                port: '8080',
+                resource: '/resource/4?filter=a',
+                ts: '1398546787',
+                nonce: 'xUwusx',
+                hash: 'nJjkVtBE5Y/Bk38Aiokwn0jiJxt/0S2WRSUwWLCf5xk=',
+                ext: 'some-app-data',
+                mac: 'dvIvMThwi28J61Jc3P0ryAhuKpanU63GXdx6hkmQkJA=',
+                id: '123456'
+            };
+
+            expect(() => Hawk.server.header(credentials, artifacts, 'abc')).to.throw('Invalid inputs');
+        });
+    });
+
+    describe('authenticateBewit()', () => {
+
+        it('errors on uri too long', async () => {
+
+            let long = '/';
+            for (let i = 0; i < 5000; ++i) {
+                long += 'x';
+            }
+
+            const req = {
+                method: 'GET',
+                url: long,
+                host: 'example.com',
+                port: 8080,
+                authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"'
+            };
+
+            const err = await expect(Hawk.server.authenticateBewit(req, credentialsFunc, {})).to.reject('Resource path exceeds max length');
+            expect(err.output.statusCode).to.equal(400);
+        });
+    });
+
+    describe('authenticateMessage()', () => {
+
+        it('errors on invalid authorization (ts)', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+            delete auth.ts;
+
+            await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc)).to.reject('Invalid authorization');
+        });
+
+        it('errors on invalid authorization (mac)', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+            delete auth.mac;
+
+            await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc)).to.reject('Invalid authorization');
+        });
+
+        it('errors on invalid authorization (nonce)', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+            delete auth.nonce;
+
+            await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc)).to.reject('Invalid authorization');
+        });
+
+        it('errors on invalid authorization (hash)', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+            delete auth.hash;
+
+            await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc)).to.reject('Invalid authorization');
+        });
+
+        it('errors with credentials', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+
+            const err = await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, (id) => {
+
+                const error = new Error('something');
+                error.credentials = { some: 'value' };
+                throw error;
+            })).to.reject('something');
+            expect(err.credentials.some).to.equal('value');
+        });
+
+        it('errors on nonce collision', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+
+            const nonceFunc = function (key, nonce, ts) {
+
+                throw new Error();
+            };
+
+            await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { nonceFunc })).to.reject('Invalid nonce');
+        });
+
+        it('should generate an authorization then successfully parse it', async () => {
+
+            const credentials1 = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
+            expect(auth).to.exist();
+
+            const { credentials: credentials2 } = await Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc);
+            expect(credentials2.user).to.equal('steve');
+        });
+
+        it('should fail authorization on mismatching host', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+            expect(auth).to.exist();
+
+            await expect(Hawk.server.authenticateMessage('example1.com', 8080, 'some message', auth, credentialsFunc)).to.reject('Bad mac');
+        });
+
+        it('should fail authorization on stale timestamp', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+            expect(auth).to.exist();
+
+            await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { localtimeOffsetMsec: 100000 })).to.reject('Stale timestamp');
+        });
+
+        it('overrides timestampSkewSec', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials, localtimeOffsetMsec: 100000 });
+            expect(auth).to.exist();
+
+            await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { timestampSkewSec: 500 })).to.not.reject();
+        });
+
+        it('should fail authorization on invalid authorization', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+            expect(auth).to.exist();
+            delete auth.id;
+
+            await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc)).to.reject('Invalid authorization');
+        });
+
+        it('should fail authorization on bad hash', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+            expect(auth).to.exist();
+
+            await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message1', auth, credentialsFunc)).to.reject('Bad message hash');
+        });
+
+        it('should fail authorization on nonce error', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+            expect(auth).to.exist();
+
+            await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {
+                nonceFunc: function (key, nonce, ts) {
+
+                    throw new Error('kaboom');
+                }
+            })).to.reject('Invalid nonce');
+        });
+
+        it('should fail authorization on credentials error', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+            expect(auth).to.exist();
+
+            const errFunc = function (id) {
+
+                throw new Error('kablooey');
+            };
+
+            await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc)).to.reject('kablooey');
+        });
+
+        it('should fail authorization on missing credentials', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+            expect(auth).to.exist();
+
+            const errFunc = function (id) { };
+            await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc)).to.reject('Unknown credentials');
+        });
+
+        it('should fail authorization on invalid credentials', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+            expect(auth).to.exist();
+
+            const errFunc = function (id) {
+
+                return {};
+            };
+
+            await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc)).to.reject('Invalid credentials');
+        });
+
+        it('should fail authorization on invalid credentials (algorithm)', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+            expect(auth).to.exist();
+
+            const errFunc = function (id) {
+
+                return { key: 'asdasd' };
+            };
+
+            await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc)).to.reject('Invalid credentials');
+        });
+
+        it('should fail authorization on invalid credentials algorithm', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const auth = Hawk.client.message('example.com', 8080, 'some message', { credentials });
+            expect(auth).to.exist();
+
+            const errFunc = function (id) {
+
+                return { key: '123', algorithm: '456' };
+            };
+
+            await expect(Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc)).to.reject('Unknown algorithm');
+        });
+
+        it('should fail on missing host', () => {
+
+            const credentials = credentialsFunc('123456');
+            expect(() => Hawk.client.message(null, 8080, 'some message', { credentials })).to.throw('Invalid inputs');
+        });
+
+        it('should fail on missing credentials', () => {
+
+            expect(() => Hawk.client.message('example.com', 8080, 'some message')).to.throw('Invalid credentials');
+        });
+
+        it('should fail on invalid algorithm', () => {
+
+            const credentials = credentialsFunc('123456');
+            const creds = Hoek.clone(credentials);
+            creds.algorithm = 'blah';
+            expect(() => Hawk.client.message('example.com', 8080, 'some message', { credentials: creds })).to.throw('Unknown algorithm');
+        });
+
+        it('coverage for calculateMac arguments to calculatePayloadHash', async () => {
+
+            const credentials = credentialsFunc('123456');
+            const payload = 'some not so random text';
+            const req = {
+                method: 'POST',
+                url: '/resource/4?filter=a',
+                host: 'example.com',
+                port: 8080,
+                headers: {
+                    host: 'example.com:8080',
+                    'content-type': 'text/plain'
+                }
+            };
+
+            const exp = Math.floor(Hawk.utils.now() / 1000) + 60;
+            const ext = 'some-app-data';
+            const nonce = '1AwuJD';
+            const hash = Hawk.crypto.calculatePayloadHash(payload, 'sha256', req.headers['content-type']);
+            const opts = {
+                ts: exp,
+                nonce,
+                method: req.method,
+                resource: req.url,
+                host: req.host,
+                port: req.port,
+                hash,
+                ext
+            };
+            const mac = Hawk.crypto.calculateServerMac('header', credentials, opts, payload, req.headers['content-type']);
+            const header = 'Hawk id="' + credentials.id +
+                '", ts="' + exp +
+                '", nonce="' + nonce +
+                '", hash="' + hash +
+                '", ext="' + ext +
+                '", mac="' + mac + '"';
+
+            req.headers.authorization = header;
+            // missing contentType
+            Hawk.crypto.calculateServerMac('header', credentials, opts, payload);
+            Hawk.crypto.calculateMac('header', credentials, opts);
+            await expect(Hawk.server.authenticate(req, credentialsFunc)).to.not.reject();
+        });
+
+    });
+
+    describe('authenticatePayloadHash()', () => {
+
+        it('checks payload hash', () => {
+
+            expect(() => Hawk.server.authenticatePayloadHash('abcdefg', { hash: 'abcdefg' })).to.not.throw();
+            expect(() => Hawk.server.authenticatePayloadHash('1234567', { hash: 'abcdefg' })).to.throw('Bad payload hash');
+        });
+    });
+});
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/uri.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/uri.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/uri.js	(working copy)
@@ -1,838 +1,535 @@
-// Load modules
-
-var Http = require('http');
-var Url = require('url');
-var Code = require('code');
-var Hawk = require('../lib');
-var Hoek = require('hoek');
-var Lab = require('lab');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var lab = exports.lab = Lab.script();
-var describe = lab.experiment;
-var it = lab.test;
-var expect = Code.expect;
-
-
-describe('Uri', function () {
-
-    var credentialsFunc = function (id, callback) {
-
-        var credentials = {
-            id: id,
-            key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
-            algorithm: (id === '1' ? 'sha1' : 'sha256'),
-            user: 'steve'
-        };
-
-        return callback(null, credentials);
-    };
-
-    it('should generate a bewit then successfully authenticate it', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?a=1&b=2',
-            host: 'example.com',
-            port: 80
-        };
-
-        credentialsFunc('123456', function (err, credentials1) {
-
-            var bewit = Hawk.uri.getBewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials1, ttlSec: 60 * 60 * 24 * 365 * 100, ext: 'some-app-data' });
-            req.url += '&bewit=' + bewit;
-
-            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials2, attributes) {
-
-                expect(err).to.not.exist();
-                expect(credentials2.user).to.equal('steve');
-                expect(attributes.ext).to.equal('some-app-data');
-                done();
-            });
-        });
-    });
-
-    it('should generate a bewit then successfully authenticate it (no ext)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?a=1&b=2',
-            host: 'example.com',
-            port: 80
-        };
-
-        credentialsFunc('123456', function (err, credentials1) {
-
-            var bewit = Hawk.uri.getBewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials1, ttlSec: 60 * 60 * 24 * 365 * 100 });
-            req.url += '&bewit=' + bewit;
-
-            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials2, attributes) {
-
-                expect(err).to.not.exist();
-                expect(credentials2.user).to.equal('steve');
-                done();
-            });
-        });
-    });
-
-    it('should successfully authenticate a request (last param)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?a=1&b=2&bewit=MTIzNDU2XDQ1MTE0ODQ2MjFcMzFjMmNkbUJFd1NJRVZDOVkva1NFb2c3d3YrdEVNWjZ3RXNmOGNHU2FXQT1cc29tZS1hcHAtZGF0YQ',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-            expect(err).to.not.exist();
-            expect(credentials.user).to.equal('steve');
-            expect(attributes.ext).to.equal('some-app-data');
-            done();
-        });
-    });
-
-    it('should successfully authenticate a request (first param)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2MjFcMzFjMmNkbUJFd1NJRVZDOVkva1NFb2c3d3YrdEVNWjZ3RXNmOGNHU2FXQT1cc29tZS1hcHAtZGF0YQ&a=1&b=2',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-            expect(err).to.not.exist();
-            expect(credentials.user).to.equal('steve');
-            expect(attributes.ext).to.equal('some-app-data');
-            done();
-        });
-    });
-
-    it('should successfully authenticate a request (only param)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2NDFcZm1CdkNWT3MvcElOTUUxSTIwbWhrejQ3UnBwTmo4Y1VrSHpQd3Q5OXJ1cz1cc29tZS1hcHAtZGF0YQ',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-            expect(err).to.not.exist();
-            expect(credentials.user).to.equal('steve');
-            expect(attributes.ext).to.equal('some-app-data');
-            done();
-        });
-    });
-
-    it('should fail on multiple authentication', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2NDFcZm1CdkNWT3MvcElOTUUxSTIwbWhrejQ3UnBwTmo4Y1VrSHpQd3Q5OXJ1cz1cc29tZS1hcHAtZGF0YQ',
-            host: 'example.com',
-            port: 8080,
-            authorization: 'Basic asdasdasdasd'
-        };
-
-        Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-            expect(err).to.exist();
-            expect(err.output.payload.message).to.equal('Multiple authentications');
-            done();
-        });
-    });
-
-    it('should fail on method other than GET', function (done) {
-
-        credentialsFunc('123456', function (err, credentials1) {
-
-            var req = {
-                method: 'POST',
-                url: '/resource/4?filter=a',
-                host: 'example.com',
-                port: 8080
-            };
-
-            var exp = Math.floor(Hawk.utils.now() / 1000) + 60;
-            var ext = 'some-app-data';
-            var mac = Hawk.crypto.calculateMac('bewit', credentials1, {
-                timestamp: exp,
-                nonce: '',
-                method: req.method,
-                resource: req.url,
-                host: req.host,
-                port: req.port,
-                ext: ext
-            });
-
-            var bewit = credentials1.id + '\\' + exp + '\\' + mac + '\\' + ext;
-
-            req.url += '&bewit=' + Hoek.base64urlEncode(bewit);
-
-            Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials2, attributes) {
-
-                expect(err).to.exist();
-                expect(err.output.payload.message).to.equal('Invalid method');
-                done();
-            });
-        });
-    });
-
-    it('should fail on invalid host header', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
-            headers: {
-                host: 'example.com:something'
-            }
-        };
-
-        Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-            expect(err).to.exist();
-            expect(err.output.payload.message).to.equal('Invalid Host header');
-            done();
-        });
-    });
-
-    it('should fail on empty bewit', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?bewit=',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-            expect(err).to.exist();
-            expect(err.output.payload.message).to.equal('Empty bewit');
-            expect(err.isMissing).to.not.exist();
-            done();
-        });
-    });
-
-    it('should fail on invalid bewit', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?bewit=*',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-            expect(err).to.exist();
-            expect(err.output.payload.message).to.equal('Invalid bewit encoding');
-            expect(err.isMissing).to.not.exist();
-            done();
-        });
-    });
-
-    it('should fail on missing bewit', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-            expect(err).to.exist();
-            expect(err.output.payload.message).to.not.exist();
-            expect(err.isMissing).to.equal(true);
-            done();
-        });
-    });
-
-    it('should fail on invalid bewit structure', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?bewit=abc',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-            expect(err).to.exist();
-            expect(err.output.payload.message).to.equal('Invalid bewit structure');
-            done();
-        });
-    });
-
-    it('should fail on empty bewit attribute', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?bewit=YVxcY1xk',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-            expect(err).to.exist();
-            expect(err.output.payload.message).to.equal('Missing bewit attributes');
-            done();
-        });
-    });
-
-    it('should fail on missing bewit id attribute', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?bewit=XDQ1NTIxNDc2MjJcK0JFbFhQMXhuWjcvd1Nrbm1ldGhlZm5vUTNHVjZNSlFVRHk4NWpTZVJ4VT1cc29tZS1hcHAtZGF0YQ',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-            expect(err).to.exist();
-            expect(err.output.payload.message).to.equal('Missing bewit attributes');
-            done();
-        });
-    });
-
-    it('should fail on expired access', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?a=1&b=2&bewit=MTIzNDU2XDEzNTY0MTg1ODNcWk1wZlMwWU5KNHV0WHpOMmRucTRydEk3NXNXTjFjeWVITTcrL0tNZFdVQT1cc29tZS1hcHAtZGF0YQ',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, credentialsFunc, {}, function (err, credentials, attributes) {
-
-            expect(err).to.exist();
-            expect(err.output.payload.message).to.equal('Access expired');
-            done();
-        });
-    });
-
-    it('should fail on credentials function error', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, function (id, callback) {
-
-            callback(Hawk.error.badRequest('Boom'));
-        }, {}, function (err, credentials, attributes) {
-
-            expect(err).to.exist();
-            expect(err.output.payload.message).to.equal('Boom');
-            done();
-        });
-    });
-
-    it('should fail on credentials function error with credentials', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, function (id, callback) {
-
-            callback(Hawk.error.badRequest('Boom'), { some: 'value' });
-        }, {}, function (err, credentials, attributes) {
-
-            expect(err).to.exist();
-            expect(err.output.payload.message).to.equal('Boom');
-            expect(credentials.some).to.equal('value');
-            done();
-        });
-    });
-
-    it('should fail on null credentials function response', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, function (id, callback) {
-
-            callback(null, null);
-        }, {}, function (err, credentials, attributes) {
-
-            expect(err).to.exist();
-            expect(err.output.payload.message).to.equal('Unknown credentials');
-            done();
-        });
-    });
-
-    it('should fail on invalid credentials function response', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, function (id, callback) {
-
-            callback(null, {});
-        }, {}, function (err, credentials, attributes) {
-
-            expect(err).to.exist();
-            expect(err.message).to.equal('Invalid credentials');
-            done();
-        });
-    });
-
-    it('should fail on invalid credentials function response (unknown algorithm)', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, function (id, callback) {
-
-            callback(null, { key: 'xxx', algorithm: 'xxx' });
-        }, {}, function (err, credentials, attributes) {
-
-            expect(err).to.exist();
-            expect(err.message).to.equal('Unknown algorithm');
-            done();
-        });
-    });
-
-    it('should fail on expired access', function (done) {
-
-        var req = {
-            method: 'GET',
-            url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
-            host: 'example.com',
-            port: 8080
-        };
-
-        Hawk.uri.authenticate(req, function (id, callback) {
-
-            callback(null, { key: 'xxx', algorithm: 'sha256' });
-        }, {}, function (err, credentials, attributes) {
-
-            expect(err).to.exist();
-            expect(err.output.payload.message).to.equal('Bad mac');
-            done();
-        });
-    });
-
-    describe('getBewit()', function () {
-
-        it('returns a valid bewit value', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
-            expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdca3NjeHdOUjJ0SnBQMVQxekRMTlBiQjVVaUtJVTl0T1NKWFRVZEc3WDloOD1ceGFuZHlhbmR6');
-            done();
-        });
-
-        it('returns a valid bewit value (explicit port)', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var bewit = Hawk.uri.getBewit('https://example.com:8080/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
-            expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdcaFpiSjNQMmNLRW80a3kwQzhqa1pBa1J5Q1p1ZWc0V1NOYnhWN3ZxM3hIVT1ceGFuZHlhbmR6');
-            done();
-        });
-
-        it('returns a valid bewit value (null ext)', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: null });
-            expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdcSUdZbUxnSXFMckNlOEN4dktQczRKbFdJQStValdKSm91d2dBUmlWaENBZz1c');
-            done();
-        });
-
-        it('returns a valid bewit value (parsed uri)', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var bewit = Hawk.uri.getBewit(Url.parse('https://example.com/somewhere/over/the/rainbow'), { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
-            expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdca3NjeHdOUjJ0SnBQMVQxekRMTlBiQjVVaUtJVTl0T1NKWFRVZEc3WDloOD1ceGFuZHlhbmR6');
-            done();
-        });
-
-        it('errors on invalid options', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', 4);
-            expect(bewit).to.equal('');
-            done();
-        });
-
-        it('errors on missing uri', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var bewit = Hawk.uri.getBewit('', { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
-            expect(bewit).to.equal('');
-            done();
-        });
-
-        it('errors on invalid uri', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var bewit = Hawk.uri.getBewit(5, { credentials: credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
-            expect(bewit).to.equal('');
-            done();
-        });
-
-        it('errors on invalid credentials (id)', function (done) {
-
-            var credentials = {
-                key: '2983d45yun89q',
-                algorithm: 'sha256'
-            };
-
-            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 3000, ext: 'xandyandz' });
-            expect(bewit).to.equal('');
-            done();
-        });
-
-        it('errors on missing credentials', function (done) {
-
-            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { ttlSec: 3000, ext: 'xandyandz' });
-            expect(bewit).to.equal('');
-            done();
-        });
-
-        it('errors on invalid credentials (key)', function (done) {
-
-            var credentials = {
-                id: '123456',
-                algorithm: 'sha256'
-            };
-
-            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 3000, ext: 'xandyandz' });
-            expect(bewit).to.equal('');
-            done();
-        });
-
-        it('errors on invalid algorithm', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'hmac-sha-0'
-            };
-
-            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials: credentials, ttlSec: 300, ext: 'xandyandz' });
-            expect(bewit).to.equal('');
-            done();
-        });
-
-        it('errors on missing options', function (done) {
-
-            var credentials = {
-                id: '123456',
-                key: '2983d45yun89q',
-                algorithm: 'hmac-sha-0'
-            };
-
-            var bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow');
-            expect(bewit).to.equal('');
-            done();
-        });
-    });
-
-    describe('authenticateMessage()', function () {
-
-        it('should generate an authorization then successfully parse it', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.not.exist();
-                    expect(credentials2.user).to.equal('steve');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on mismatching host', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                Hawk.server.authenticateMessage('example1.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Bad mac');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on stale timestamp', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { localtimeOffsetMsec: 100000 }, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Stale timestamp');
-                    done();
-                });
-            });
-        });
-
-        it('overrides timestampSkewSec', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1, localtimeOffsetMsec: 100000 });
-                expect(auth).to.exist();
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, { timestampSkewSec: 500 }, function (err, credentials2) {
-
-                    expect(err).to.not.exist();
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on invalid authorization', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-                delete auth.id;
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Invalid authorization');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on bad hash', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message1', auth, credentialsFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Bad message hash');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on nonce error', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, credentialsFunc, {
-                    nonceFunc: function (key, nonce, ts, callback) {
-
-                        callback(new Error('kaboom'));
-                    }
-                }, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Invalid nonce');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on credentials error', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                var errFunc = function (id, callback) {
-
-                    callback(new Error('kablooey'));
-                };
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('kablooey');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on missing credentials', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                var errFunc = function (id, callback) {
-
-                    callback();
-                };
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Unknown credentials');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on invalid credentials', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                var errFunc = function (id, callback) {
-
-                    callback(null, {});
-                };
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Invalid credentials');
-                    done();
-                });
-            });
-        });
-
-        it('should fail authorization on invalid credentials algorithm', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.exist();
-
-                var errFunc = function (id, callback) {
-
-                    callback(null, { key: '123', algorithm: '456' });
-                };
-
-                Hawk.server.authenticateMessage('example.com', 8080, 'some message', auth, errFunc, {}, function (err, credentials2) {
-
-                    expect(err).to.exist();
-                    expect(err.message).to.equal('Unknown algorithm');
-                    done();
-                });
-            });
-        });
-
-        it('should fail on missing host', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var auth = Hawk.client.message(null, 8080, 'some message', { credentials: credentials1 });
-                expect(auth).to.not.exist();
-                done();
-            });
-        });
-
-        it('should fail on missing credentials', function (done) {
-
-            var auth = Hawk.client.message('example.com', 8080, 'some message', {});
-            expect(auth).to.not.exist();
-            done();
-        });
-
-        it('should fail on invalid algorithm', function (done) {
-
-            credentialsFunc('123456', function (err, credentials1) {
-
-                var creds = Hoek.clone(credentials1);
-                creds.algorithm = 'blah';
-                var auth = Hawk.client.message('example.com', 8080, 'some message', { credentials: creds });
-                expect(auth).to.not.exist();
-                done();
-            });
-        });
-    });
-});
-
+'use strict';
+
+const Url = require('url');
+
+const B64 = require('@hapi/b64');
+const Boom = require('@hapi/boom');
+const Code = require('@hapi/code');
+const Hawk = require('..');
+const Lab = require('@hapi/lab');
+
+
+const internals = {};
+
+
+const { describe, it } = exports.lab = Lab.script();
+const expect = Code.expect;
+
+
+describe('Uri', () => {
+
+    const credentialsFunc = function (id) {
+
+        return {
+            id,
+            key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
+            algorithm: (id === '1' ? 'sha1' : 'sha256'),
+            user: 'steve'
+        };
+    };
+
+    it('should generate a bewit then successfully authenticate it', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?a=1&b=2',
+            host: 'example.com',
+            port: 80
+        };
+
+        const credentials1 = credentialsFunc('123456');
+        const bewit = Hawk.uri.getBewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials1, ttlSec: 60 * 60 * 24 * 365 * 100, ext: 'some-app-data' });
+        req.url += '&bewit=' + bewit;
+
+        const { credentials: credentials2, attributes } = await Hawk.uri.authenticate(req, credentialsFunc);
+        expect(credentials2.user).to.equal('steve');
+        expect(attributes.ext).to.equal('some-app-data');
+    });
+
+    it('should generate a bewit then successfully authenticate it (HEAD)', async () => {
+
+        const req = {
+            method: 'HEAD',
+            url: '/resource/4?a=1&b=2',
+            host: 'example.com',
+            port: 80
+        };
+
+        const credentials1 = credentialsFunc('123456');
+        const bewit = Hawk.uri.getBewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials1, ttlSec: 60 * 60 * 24 * 365 * 100, ext: 'some-app-data' });
+        req.url += '&bewit=' + bewit;
+
+        const { credentials: credentials2, attributes } = await Hawk.uri.authenticate(req, credentialsFunc);
+        expect(credentials2.user).to.equal('steve');
+        expect(attributes.ext).to.equal('some-app-data');
+    });
+
+    it('should generate a bewit then successfully authenticate it (no ext)', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?a=1&b=2',
+            host: 'example.com',
+            port: 80
+        };
+
+        const credentials1 = credentialsFunc('123456');
+        const bewit = Hawk.uri.getBewit('http://example.com/resource/4?a=1&b=2', { credentials: credentials1, ttlSec: 60 * 60 * 24 * 365 * 100 });
+        req.url += '&bewit=' + bewit;
+
+        const { credentials: credentials2 } = await Hawk.uri.authenticate(req, credentialsFunc);
+        expect(credentials2.user).to.equal('steve');
+    });
+
+    it('should successfully authenticate a request (last param)', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?a=1&b=2&bewit=MTIzNDU2XDQ1MTE0ODQ2MjFcMzFjMmNkbUJFd1NJRVZDOVkva1NFb2c3d3YrdEVNWjZ3RXNmOGNHU2FXQT1cc29tZS1hcHAtZGF0YQ',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const { credentials, attributes } = await Hawk.uri.authenticate(req, credentialsFunc);
+        expect(credentials.user).to.equal('steve');
+        expect(attributes.ext).to.equal('some-app-data');
+    });
+
+    it('should successfully authenticate a request (first param)', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2MjFcMzFjMmNkbUJFd1NJRVZDOVkva1NFb2c3d3YrdEVNWjZ3RXNmOGNHU2FXQT1cc29tZS1hcHAtZGF0YQ&a=1&b=2',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const { credentials, attributes } = await Hawk.uri.authenticate(req, credentialsFunc);
+        expect(credentials.user).to.equal('steve');
+        expect(attributes.ext).to.equal('some-app-data');
+    });
+
+    it('should successfully authenticate a request (only param)', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2NDFcZm1CdkNWT3MvcElOTUUxSTIwbWhrejQ3UnBwTmo4Y1VrSHpQd3Q5OXJ1cz1cc29tZS1hcHAtZGF0YQ',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const { credentials, attributes } = await Hawk.uri.authenticate(req, credentialsFunc);
+        expect(credentials.user).to.equal('steve');
+        expect(attributes.ext).to.equal('some-app-data');
+    });
+
+    it('fails on multiple authentication', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=MTIzNDU2XDQ1MTE0ODQ2NDFcZm1CdkNWT3MvcElOTUUxSTIwbWhrejQ3UnBwTmo4Y1VrSHpQd3Q5OXJ1cz1cc29tZS1hcHAtZGF0YQ',
+            host: 'example.com',
+            port: 8080,
+            authorization: 'Basic asdasdasdasd'
+        };
+
+        await expect(Hawk.uri.authenticate(req, credentialsFunc)).to.reject('Multiple authentications');
+    });
+
+    it('fails on method other than GET', async () => {
+
+        const credentials = credentialsFunc('123456');
+
+        const req = {
+            method: 'POST',
+            url: '/resource/4?filter=a',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const exp = Math.floor(Hawk.utils.now() / 1000) + 60;
+        const ext = 'some-app-data';
+        const mac = Hawk.crypto.generateRequestMac('bewit', credentials, {
+            ts: exp,
+            nonce: '',
+            method: req.method,
+            resource: req.url,
+            host: req.host,
+            port: req.port,
+            ext
+        });
+
+        const bewit = credentials.id + '\\' + exp + '\\' + mac + '\\' + ext;
+
+        req.url += '&bewit=' + B64.base64urlEncode(bewit);
+
+        await expect(Hawk.uri.authenticate(req, credentialsFunc)).to.reject('Invalid method');
+    });
+
+    it('fails on invalid host header', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
+            headers: {
+                host: 'example.com:something'
+            }
+        };
+
+        await expect(Hawk.uri.authenticate(req, credentialsFunc)).to.reject('Invalid Host header');
+    });
+
+    it('fails on empty bewit', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const err = await expect(Hawk.uri.authenticate(req, credentialsFunc)).to.reject('Empty bewit');
+        expect(err.isMissing).to.not.exist();
+    });
+
+    it('fails on invalid bewit', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=*',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const err = await expect(Hawk.uri.authenticate(req, credentialsFunc)).to.reject('Invalid bewit encoding');
+        expect(err.isMissing).to.not.exist();
+    });
+
+    it('fails on missing bewit', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const err = await expect(Hawk.uri.authenticate(req, credentialsFunc)).to.reject('Unauthorized');
+        expect(err.isMissing).to.equal(true);
+    });
+
+    it('fails on invalid bewit structure', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=abc',
+            host: 'example.com',
+            port: 8080
+        };
+
+        await expect(Hawk.uri.authenticate(req, credentialsFunc)).to.reject('Invalid bewit structure');
+    });
+
+    it('fails on empty bewit attribute', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=YVxcY1xk',
+            host: 'example.com',
+            port: 8080
+        };
+
+        await expect(Hawk.uri.authenticate(req, credentialsFunc)).to.reject('Missing bewit attributes');
+    });
+
+    it('fails on missing bewit id attribute', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=XDQ1NTIxNDc2MjJcK0JFbFhQMXhuWjcvd1Nrbm1ldGhlZm5vUTNHVjZNSlFVRHk4NWpTZVJ4VT1cc29tZS1hcHAtZGF0YQ',
+            host: 'example.com',
+            port: 8080
+        };
+
+        await expect(Hawk.uri.authenticate(req, credentialsFunc)).to.reject('Missing bewit attributes');
+    });
+
+    it('fails on missing bewit mac attribute', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=MTIzNDU2XDQ3MDkzMTY5NjNcXHNvbWUtYXBwLWRhdGE',
+            host: 'example.com',
+            port: 8080
+        };
+
+        await expect(Hawk.uri.authenticate(req, credentialsFunc)).to.reject('Missing bewit attributes');
+    });
+
+    it('fails on expired access', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource',
+            host: 'example.com',
+            port: 8080
+        };
+        const credentials = credentialsFunc('123456');
+        const bewit = Hawk.uri.getBewit('https://example.com:8080/resource', { credentials, ttlSec: -10 });
+        req.url += '?bewit=' + bewit;
+
+        await expect(Hawk.uri.authenticate(req, credentialsFunc)).to.reject('Access expired');
+    });
+
+    it('validates mac before expiry', async () => {
+
+        const credentials = credentialsFunc('123456');
+        const exp = '1';
+        const expiredInvalidBewit = B64.base64urlEncode(credentials.id + '\\' + exp + '\\somemac\\');
+        const req = {
+            method: 'GET',
+            url: '/resource?bewit=' + expiredInvalidBewit,
+            host: 'example.com',
+            port: 8080
+        };
+
+        await expect(Hawk.uri.authenticate(req, credentialsFunc, {})).to.reject('Bad mac');
+    });
+
+    it('fails on credentials function error', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
+            host: 'example.com',
+            port: 8080
+        };
+
+        await expect(Hawk.uri.authenticate(req, (id) => {
+
+            throw Boom.badRequest('Boom');
+        })).to.reject('Boom');
+    });
+
+    it('fails on credentials function error with credentials', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
+            host: 'example.com',
+            port: 8080
+        };
+
+        const err = await expect(Hawk.uri.authenticate(req, (id, callback) => {
+
+            const error = Boom.badRequest('Boom');
+            error.credentials = { some: 'value' };
+            throw error;
+        })).to.reject('Boom');
+        expect(err.credentials.some).to.equal('value');
+    });
+
+    it('fails on null credentials function response', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
+            host: 'example.com',
+            port: 8080
+        };
+
+        await expect(Hawk.uri.authenticate(req, (id) => null)).to.reject('Unknown credentials');
+    });
+
+    it('fails on invalid credentials function response', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
+            host: 'example.com',
+            port: 8080
+        };
+
+        await expect(Hawk.uri.authenticate(req, (id) => ({}))).to.reject('Invalid credentials');
+    });
+
+    it('fails on invalid credentials function response (algorithm)', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
+            host: 'example.com',
+            port: 8080
+        };
+
+        await expect(Hawk.uri.authenticate(req, (id) => ({ key: '123123' }))).to.reject('Invalid credentials');
+    });
+
+    it('fails on invalid credentials function response (unknown algorithm)', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
+            host: 'example.com',
+            port: 8080
+        };
+
+        await expect(Hawk.uri.authenticate(req, (id) => ({ key: 'xxx', algorithm: 'xxx' }))).to.reject('Unknown algorithm');
+    });
+
+    it('fails on invalid credentials function response (bad mac)', async () => {
+
+        const req = {
+            method: 'GET',
+            url: '/resource/4?bewit=MTIzNDU2XDQ1MDk5OTE3MTlcTUE2eWkwRWRwR0pEcWRwb0JkYVdvVDJrL0hDSzA1T0Y3MkhuZlVmVy96Zz1cc29tZS1hcHAtZGF0YQ',
+            host: 'example.com',
+            port: 8080
+        };
+
+        await expect(Hawk.uri.authenticate(req, (id) => ({ key: 'xxx', algorithm: 'sha256' }))).to.reject('Bad mac');
+    });
+
+    describe('getBewit()', () => {
+
+        it('returns a valid bewit value', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            const bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
+            expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdca3NjeHdOUjJ0SnBQMVQxekRMTlBiQjVVaUtJVTl0T1NKWFRVZEc3WDloOD1ceGFuZHlhbmR6');
+        });
+
+        it('returns a valid bewit value (explicit port)', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            const bewit = Hawk.uri.getBewit('https://example.com:8080/somewhere/over/the/rainbow', { credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
+            expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdcaFpiSjNQMmNLRW80a3kwQzhqa1pBa1J5Q1p1ZWc0V1NOYnhWN3ZxM3hIVT1ceGFuZHlhbmR6');
+        });
+
+        it('returns a valid bewit value (null ext)', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            const bewit = Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: null });
+            expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdcSUdZbUxnSXFMckNlOEN4dktQczRKbFdJQStValdKSm91d2dBUmlWaENBZz1c');
+        });
+
+        it('returns a valid bewit value (parsed uri)', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            const bewit = Hawk.uri.getBewit(Url.parse('https://example.com/somewhere/over/the/rainbow'), { credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' });
+            expect(bewit).to.equal('MTIzNDU2XDEzNTY0MjA3MDdca3NjeHdOUjJ0SnBQMVQxekRMTlBiQjVVaUtJVTl0T1NKWFRVZEc3WDloOD1ceGFuZHlhbmR6');
+        });
+
+        it('errors on invalid options', () => {
+
+            expect(() => Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', 4)).to.throw('Invalid inputs');
+        });
+
+        it('errors on missing options.ttlSec', () => {
+
+            expect(() => Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', {})).to.throw('Invalid inputs');
+        });
+
+        it('errors on missing uri', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            expect(() => Hawk.uri.getBewit('', { credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' })).to.throw('Invalid inputs');
+        });
+
+        it('errors on invalid uri', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            expect(() => Hawk.uri.getBewit(5, { credentials, ttlSec: 300, localtimeOffsetMsec: 1356420407232 - Hawk.utils.now(), ext: 'xandyandz' })).to.throw('Invalid inputs');
+        });
+
+        it('errors on invalid credentials (id)', () => {
+
+            const credentials = {
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            expect(() => Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials, ttlSec: 3000, ext: 'xandyandz' })).to.throw('Invalid credentials');
+        });
+
+        it('errors on invalid credentials (id)', () => {
+
+            const credentials = {
+                key: '2983d45yun89q',
+                algorithm: 'sha256'
+            };
+
+            expect(() => Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials, ttlSec: 3000, ext: 'xandyandz' })).to.throw('Invalid credentials');
+        });
+
+        it('errors on invalid credentials (algorithm)', () => {
+
+            const credentials = {
+                key: '2983d45yun89q',
+                id: '123'
+            };
+
+            expect(() => Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials, ttlSec: 3000, ext: 'xandyandz' })).to.throw('Invalid credentials');
+        });
+
+        it('errors on missing credentials', () => {
+
+            expect(() => Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { ttlSec: 3000, ext: 'xandyandz' })).to.throw('Invalid credentials');
+        });
+
+        it('errors on invalid credentials (key)', () => {
+
+            const credentials = {
+                id: '123456',
+                algorithm: 'sha256'
+            };
+
+            expect(() => Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials, ttlSec: 3000, ext: 'xandyandz' })).to.throw('Invalid credentials');
+        });
+
+        it('errors on invalid algorithm', () => {
+
+            const credentials = {
+                id: '123456',
+                key: '2983d45yun89q',
+                algorithm: 'hmac-sha-0'
+            };
+
+            expect(() => Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow', { credentials, ttlSec: 300, ext: 'xandyandz' })).to.throw('Unknown algorithm');
+        });
+
+        it('errors on missing options', () => {
+
+            expect(() => Hawk.uri.getBewit('https://example.com/somewhere/over/the/rainbow')).to.throw('Invalid inputs');
+        });
+    });
+});
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/utils.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/utils.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/hawk/test/utils.js	(working copy)
@@ -1,149 +1,148 @@
-// Load modules
-
-var Code = require('code');
-var Hawk = require('../lib');
-var Lab = require('lab');
-var Package = require('../package.json');
-
-
-// Declare internals
-
-var internals = {};
-
-
-// Test shortcuts
-
-var lab = exports.lab = Lab.script();
-var describe = lab.experiment;
-var it = lab.test;
-var expect = Code.expect;
-
-
-describe('Utils', function () {
-
-    describe('parseHost()', function () {
-
-        it('returns port 80 for non tls node request', function (done) {
-
-            var req = {
-                method: 'POST',
-                url: '/resource/4?filter=a',
-                headers: {
-                    host: 'example.com',
-                    'content-type': 'text/plain;x=y'
-                }
-            };
-
-            expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(80);
-            done();
-        });
-
-        it('returns port 443 for non tls node request', function (done) {
-
-            var req = {
-                method: 'POST',
-                url: '/resource/4?filter=a',
-                headers: {
-                    host: 'example.com',
-                    'content-type': 'text/plain;x=y'
-                },
-                connection: {
-                    encrypted: true
-                }
-            };
-
-            expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(443);
-            done();
-        });
-
-        it('returns port 443 for non tls node request (IPv6)', function (done) {
-
-            var req = {
-                method: 'POST',
-                url: '/resource/4?filter=a',
-                headers: {
-                    host: '[123:123:123]',
-                    'content-type': 'text/plain;x=y'
-                },
-                connection: {
-                    encrypted: true
-                }
-            };
-
-            expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(443);
-            done();
-        });
-
-        it('parses IPv6 headers', function (done) {
-
-            var req = {
-                method: 'POST',
-                url: '/resource/4?filter=a',
-                headers: {
-                    host: '[123:123:123]:8000',
-                    'content-type': 'text/plain;x=y'
-                },
-                connection: {
-                    encrypted: true
-                }
-            };
-
-            var host = Hawk.utils.parseHost(req, 'Host');
-            expect(host.port).to.equal('8000');
-            expect(host.name).to.equal('[123:123:123]');
-            done();
-        });
-
-        it('errors on header too long', function (done) {
-
-            var long = '';
-            for (var i = 0; i < 5000; ++i) {
-                long += 'x';
-            }
-
-            expect(Hawk.utils.parseHost({ headers: { host: long } })).to.be.null();
-            done();
-        });
-    });
-
-    describe('parseAuthorizationHeader()', function () {
-
-        it('errors on header too long', function (done) {
-
-            var long = 'Scheme a="';
-            for (var i = 0; i < 5000; ++i) {
-                long += 'x';
-            }
-            long += '"';
-
-            var err = Hawk.utils.parseAuthorizationHeader(long, ['a']);
-            expect(err).to.be.instanceof(Error);
-            expect(err.message).to.equal('Header length too long');
-            done();
-        });
-    });
-
-    describe('version()', function () {
-
-        it('returns the correct package version number', function (done) {
-
-            expect(Hawk.utils.version()).to.equal(Package.version);
-            done();
-        });
-    });
-
-    describe('unauthorized()', function () {
-
-        it('returns a hawk 401', function (done) {
-
-            expect(Hawk.utils.unauthorized('kaboom').output.headers['WWW-Authenticate']).to.equal('Hawk error="kaboom"');
-            done();
-        });
-
-        it('supports attributes', function (done) {
-
-            expect(Hawk.utils.unauthorized('kaboom', { a: 'b' }).output.headers['WWW-Authenticate']).to.equal('Hawk a="b", error="kaboom"');
-            done();
-        });
-    });
-});
+'use strict';
+
+const Code = require('@hapi/code');
+const Hawk = require('..');
+const Lab = require('@hapi/lab');
+
+const Package = require('../package.json');
+
+
+const internals = {};
+
+
+const { describe, it, after } = exports.lab = Lab.script();
+const expect = Code.expect;
+
+
+describe('Utils', () => {
+
+    describe('parseHost()', () => {
+
+        it('returns port 80 for non tls node request', () => {
+
+            const req = {
+                method: 'POST',
+                url: '/resource/4?filter=a',
+                headers: {
+                    host: 'example.com',
+                    'content-type': 'text/plain;x=y'
+                }
+            };
+
+            expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(80);
+        });
+
+        it('returns port 443 for non tls node request', () => {
+
+            const req = {
+                method: 'POST',
+                url: '/resource/4?filter=a',
+                headers: {
+                    host: 'example.com',
+                    'content-type': 'text/plain;x=y'
+                },
+                connection: {
+                    encrypted: true
+                }
+            };
+
+            expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(443);
+        });
+
+        it('returns port 443 for non tls node request (IPv6)', () => {
+
+            const req = {
+                method: 'POST',
+                url: '/resource/4?filter=a',
+                headers: {
+                    host: '[123:123::123]',
+                    'content-type': 'text/plain;x=y'
+                },
+                connection: {
+                    encrypted: true
+                }
+            };
+
+            expect(Hawk.utils.parseHost(req, 'Host').port).to.equal(443);
+        });
+
+        it('parses IPv6 headers', () => {
+
+            const req = {
+                method: 'POST',
+                url: '/resource/4?filter=a',
+                headers: {
+                    host: '[123:123::123]:8000',
+                    'content-type': 'text/plain;x=y'
+                },
+                connection: {
+                    encrypted: true
+                }
+            };
+
+            const host = Hawk.utils.parseHost(req, 'Host');
+            expect(host.port).to.equal('8000');
+            expect(host.name).to.equal('[123:123::123]');
+        });
+
+        it('errors on header too long', () => {
+
+            let long = '';
+            for (let i = 0; i < 5000; ++i) {
+                long += 'x';
+            }
+
+            expect(Hawk.utils.parseHost({ headers: { host: long } })).to.be.null();
+        });
+    });
+
+    describe('parseAuthorizationHeader()', () => {
+
+        it('errors on header too long', () => {
+
+            let long = 'Scheme a="';
+            for (let i = 0; i < 5000; ++i) {
+                long += 'x';
+            }
+
+            long += '"';
+
+            expect(() => Hawk.utils.parseAuthorizationHeader(long, ['a'])).to.throw('Header length too long');
+        });
+    });
+
+    describe('version()', () => {
+
+        it('returns the correct package version number', () => {
+
+            expect(Hawk.utils.version()).to.equal(Package.version);
+        });
+    });
+
+    describe('setTimeFunction()', () => {
+
+        after(() => {
+
+            Hawk.utils.setTimeFunction(Date.now);
+        });
+
+        it('creates the value that now() will return', () => {
+
+            Hawk.utils.setTimeFunction(() => 269323200000);
+            expect(Hawk.utils.now()).to.equal(269323200000);
+        });
+    });
+
+    describe('unauthorized()', () => {
+
+        it('returns a hawk 401', () => {
+
+            expect(Hawk.utils.unauthorized('kaboom').output.headers['WWW-Authenticate']).to.equal('Hawk error="kaboom"');
+        });
+
+        it('supports attributes', () => {
+
+            expect(Hawk.utils.unauthorized('kaboom', { a: 'b' }).output.headers['WWW-Authenticate']).to.equal('Hawk a="b", error="kaboom"');
+        });
+    });
+});
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/jsprim/node_modules/json-schema/README.md
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/jsprim/node_modules/json-schema/README.md	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/jsprim/node_modules/json-schema/README.md	(working copy)
@@ -1,5 +1,421 @@
-JSON Schema is a repository for the JSON Schema specification, reference schemas and a CommonJS implementation of JSON Schema (not the only JavaScript implementation of JSON Schema, JSV is another excellent JavaScript validator).
-
-Code is licensed under the AFL or BSD license as part of the Persevere 
-project which is administered under the Dojo foundation,
-and all contributions require a Dojo CLA.
\ No newline at end of file
+[![Build Status](https://secure.travis-ci.org/tdegrunt/jsonschema.svg)](http://travis-ci.org/tdegrunt/jsonschema)
+
+# jsonschema
+
+[JSON schema](http://json-schema.org/) validator, which is designed to be fast and simple to use. JSON Schema versions through draft-07 are fully supported.
+
+## Contributing & bugs
+
+Please fork the repository, make the changes in your fork and include tests. Once you're done making changes, send in a pull request.
+
+### Bug reports
+
+Please include a test which shows why the code fails.
+
+## Usage
+
+### Simple
+
+Simple object validation using JSON schemas.
+
+```javascript
+var Validator = require('jsonschema').Validator;
+var v = new Validator();
+var instance = 4;
+var schema = {"type": "number"};
+console.log(v.validate(instance, schema));
+```
+
+### Even simpler
+
+```javascript
+var validate = require('jsonschema').validate;
+console.log(validate(4, {"type": "number"}));
+```
+
+### Complex example, with split schemas and references
+
+```javascript
+var Validator = require('jsonschema').Validator;
+var v = new Validator();
+
+// Address, to be embedded on Person
+var addressSchema = {
+  "id": "/SimpleAddress",
+  "type": "object",
+  "properties": {
+    "lines": {
+      "type": "array",
+      "items": {"type": "string"}
+    },
+    "zip": {"type": "string"},
+    "city": {"type": "string"},
+    "country": {"type": "string"}
+  },
+  "required": ["country"]
+};
+
+// Person
+var schema = {
+  "id": "/SimplePerson",
+  "type": "object",
+  "properties": {
+    "name": {"type": "string"},
+    "address": {"$ref": "/SimpleAddress"},
+    "votes": {"type": "integer", "minimum": 1}
+  }
+};
+
+var p = {
+  "name": "Barack Obama",
+  "address": {
+    "lines": [ "1600 Pennsylvania Avenue Northwest" ],
+    "zip": "DC 20500",
+    "city": "Washington",
+    "country": "USA"
+  },
+  "votes": "lots"
+};
+
+v.addSchema(addressSchema, '/SimpleAddress');
+console.log(v.validate(p, schema));
+```
+### Example for Array schema
+
+```json
+var arraySchema = {
+        "type": "array",
+        "items": {
+            "properties": {
+                "name": { "type": "string" },
+                "lastname": { "type": "string" }
+            },
+            "required": ["name", "lastname"]
+        }
+    }
+```
+For a comprehensive, annotated example illustrating all possible validation options, see [examples/all.js](./examples/all.js)
+
+## Features
+
+### Definitions
+
+All schema definitions are supported, $schema is ignored.
+
+### Types
+
+All types are supported
+
+### Handling `undefined`
+
+`undefined` is not a value known to JSON, and by default, the validator treats it as if it is not invalid. i.e., it will return valid.
+
+```javascript
+var res = validate(undefined, {type: 'string'});
+res.valid // true
+```
+
+This behavior may be changed with the "required" option:
+
+```javascript
+var res = validate(undefined, {type: 'string'}, {required: true});
+res.valid // false
+```
+
+### Formats
+
+#### Disabling the format keyword.
+
+You may disable format validation by providing `disableFormat: true` to the validator
+options.
+
+#### String Formats
+
+All formats are supported, phone numbers are expected to follow the [E.123](http://en.wikipedia.org/wiki/E.123) standard.
+
+#### Custom Formats
+
+You may add your own custom format functions.  Format functions accept the input
+being validated and return a boolean value.  If the returned value is `true`, then
+validation succeeds.  If the returned value is `false`, then validation fails.
+
+* Formats added to `Validator.prototype.customFormats` do not affect previously instantiated
+Validators.  This is to prevent validator instances from being altered once created.
+It is conceivable that multiple validators may be created to handle multiple schemas
+with different formats in a program.
+* Formats added to `validator.customFormats` affect only that Validator instance.
+
+Here is an example that uses custom formats:
+
+```javascript
+Validator.prototype.customFormats.myFormat = function(input) {
+  return input === 'myFormat';
+};
+
+var validator = new Validator();
+validator.validate('myFormat', {type: 'string', format: 'myFormat'}).valid; // true
+validator.validate('foo', {type: 'string', format: 'myFormat'}).valid; // false
+```
+
+### Results
+
+By default, results will be returned in a `ValidatorResult` object with the following properties:
+
+* `instance`: any.
+* `schema`: Schema.
+* `errors`: ValidationError[].
+* `valid`: boolean.
+
+Each item in `errors` is a `ValidationError` with the following properties:
+
+* path: array. An array of property keys or array offsets, indicating where inside objects or arrays the instance was found.
+* property: string. Describes the property path. Starts with `instance`, and is delimited with a dot (`.`).
+* message: string. A human-readable message for debugging use. Provided in English and subject to change.
+* schema: object. The schema containing the keyword that failed
+* instance: any. The instance that failed
+* name: string. The keyword within the schema that failed.
+* argument: any. Provides information about the keyword that failed.
+
+The validator can be configured to throw in the event of a validation error:
+
+* If the `throwFirst` option is set, the validator will terminate validation at the first encountered error and throw a `ValidatorResultError` object.
+
+* If the `throwAll` option is set, the validator will throw a `ValidatorResultError` object after the entire instance has been validated.
+
+* If the `throwError` option is set, it will throw at the first encountered validation error (like `throwFirst`), but the `ValidationError` object itself will be thrown. Note that, despite the name, this does not inherit from Error like `ValidatorResultError` does.
+
+The `ValidatorResultError` object has the same properties as `ValidatorResult` and additionally inherits from Error.
+
+#### "nestedErrors" option
+
+When `oneOf` or `anyOf` validations fail, errors that caused any of the sub-schemas referenced therein to fail are normally suppressed, because it is not necessary to fix all of them. And in the case of `oneOf`, it would itself be an error to fix all of the listed errors.
+
+This behavior may be configured with `options.nestedErrors`. If truthy, it will emit all the errors from the subschemas. This option may be useful when troubleshooting validation errors in complex schemas:
+
+```javascript
+var schema = {
+  oneOf: [
+    { type: 'string', minLength: 32, maxLength: 32 },
+    { type: 'string', maxLength: 16 },
+    { type: 'number' },
+  ]
+};
+var validator = new Validator();
+var result = validator.validate('This string is 28 chars long', schema, {nestedErrors: true});
+
+// result.toString() reads out:
+// 0: instance does not meet minimum length of 32
+// 1: instance does not meet maximum length of 16
+// 2: instance is not of a type(s) number
+// 3: instance is not exactly one from [subschema 0],[subschema 1],[subschema 2]
+```
+
+#### Localizing Error Messages
+
+To provide localized, human-readable errors, use the `name` string as a translation key. Feel free to open an issue for support relating to localizing error messages. For example:
+
+```
+var localized = result.errors.map(function(err){
+  return localeService.translate(err.name);
+});
+```
+
+### Custom keywords
+
+Specify your own JSON Schema keywords with the validator.attributes property:
+
+```javascript
+validator.attributes.contains = function validateContains(instance, schema, options, ctx) {
+  if(typeof instance !== 'string') return;
+  if(typeof schema.contains !== 'string') throw new jsonschema.SchemaError('"contains" expects a string', schema);
+  if(instance.indexOf(schema.contains)<0){
+    return 'does not contain the string ' + JSON.stringify(schema.contains);
+  }
+}
+var result = validator.validate("I am an instance", { type:"string", contains: "I am" });
+// result.valid === true;
+```
+
+The instance passes validation if the function returns nothing. A single validation error is produced
+if the function returns a string. Any number of errors (maybe none at all) may be returned by passing a
+`ValidatorResult` object, which may be used like so:
+
+```javascript
+  var result = new ValidatorResult(instance, schema, options, ctx);
+  while(someErrorCondition()){
+    result.addError('fails some validation test');
+  }
+  return result;
+```
+
+### Dereferencing schemas
+
+Sometimes you may want to download schemas from remote sources, like a database, or over HTTP. When importing a schema,
+unknown references are inserted into the `validator.unresolvedRefs` Array. Asynchronously shift elements off this array and import
+them:
+
+```javascript
+var Validator = require('jsonschema').Validator;
+var v = new Validator();
+v.addSchema(initialSchema);
+function importNextSchema(){
+  var nextSchema = v.unresolvedRefs.shift();
+  if(!nextSchema){ done(); return; }
+  databaseGet(nextSchema, function(schema){
+    v.addSchema(schema);
+    importNextSchema();
+  });
+}
+importNextSchema();
+```
+
+### Default base URI
+
+Schemas should typically have an `id` with an absolute, full URI. However if the schema you are using contains only relative URI references, the `base` option will be used to resolve these.
+
+This following example would throw a `SchemaError` if the `base` option were unset:
+
+```javascript
+var result = validate(["Name"], {
+  id: "/schema.json",
+  type: "array",
+  items: { $ref: "http://example.com/schema.json#/definitions/item" },
+  definitions: {
+    item: { type: "string" },
+  },
+}, { base: 'http://example.com/' });
+```
+
+### Rewrite Hook
+
+The `rewrite` option lets you change the value of an instance after it has successfully been validated. This will mutate the `instance` passed to the validate function. This can be useful for unmarshalling data and parsing it into native instances, such as changing a string to a `Date` instance.
+
+The `rewrite` option accepts a function with the following arguments:
+
+* instance: any
+* schema: object
+* options: object
+* ctx: object
+* return value: any new value for the instance
+
+The value may be removed by returning `undefined`.
+If you don't want to change the value, call `return instance`.
+
+Here is an example that can convert a property expecting a date into a Date instance:
+
+```javascript
+const schema = {
+  properties: {
+    date: {id: 'http://example.com/date', type: 'string'},
+  },
+};
+
+const value = {
+  date: '2020-09-30T23:39:27.060Z',
+};
+
+function unmarshall(instance, schema){
+  if(schema.id === 'http://example.com/date'){
+    return new Date(instance);
+  }
+  return instance;
+}
+
+const v = new Validator();
+const res = v.validate(value, schema, {rewrite: unmarshall});
+
+assert(res.instance.date instanceof Date);
+```
+
+
+### Pre-Property Validation Hook
+
+If some processing of properties is required prior to validation a function may be passed via the options parameter of the validate function. For example, say you needed to perform type coercion for some properties:
+
+```javascript
+// See examples/coercion.js
+function preValidateProperty(object, key, schema, options, ctx) {
+  var value = object[key];
+  if (typeof value === 'undefined') return;
+
+  // Test if the schema declares a type, but the type keyword fails validation
+  if (schema.type && validator.attributes.type.call(validator, value, schema, options, ctx.makeChild(schema, key))) {
+    // If the type is "number" but the instance is not a number, cast it
+    if(schema.type==='number' && typeof value!=='number'){
+      object[key] = parseFloat(value);
+      return;
+    }
+    // If the type is "string" but the instance is not a string, cast it
+    if(schema.type==='string' && typeof value!=='string'){
+      object[key] = String(value).toString();
+      return;
+    }
+  }
+};
+
+// And now, to actually perform validation with the coercion hook!
+v.validate(instance, schema, { preValidateProperty });
+```
+
+### Skip validation of certain keywords
+
+Use the "skipAttributes" option to skip validation of certain keywords. Provide an array of keywords to ignore.
+
+For skipping the "format" keyword, see the disableFormat option.
+
+### Fail on unknown keywords
+
+By default, JSON Schema is supposed to ignore unknown schema keywords.
+
+You can change this behavior to require that all keywords used in a schema have a defined behavior, by using setting the "allowUnknownAttributes" option to false.
+
+This example will throw a `SchemaError`:
+
+```javascript
+var schema = {
+  type: "string",
+  format: "email",
+  example: "foo",
+};
+var result = validate("Name", schema, { allowUnknownAttributes: false });
+```
+
+## Tests
+
+Uses [JSON Schema Test Suite](https://github.com/json-schema/JSON-Schema-Test-Suite) as well as our own tests.
+You'll need to update and init the git submodules:
+
+    git submodule update --init
+    npm test
+
+## Contributions
+
+This library would not be possible without the valuable contributions by:
+
+- Austin Wright
+
+... and many others!
+
+## License
+
+    jsonschema is licensed under MIT license.
+
+    Copyright (C) 2012-2019 Tom de Grunt <tom@degrunt.nl>
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy of
+    this software and associated documentation files (the "Software"), to deal in
+    the Software without restriction, including without limitation the rights to
+    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+    of the Software, and to permit persons to whom the Software is furnished to do
+    so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in all
+    copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+    SOFTWARE.
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/jsprim/node_modules/json-schema/package.json
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/jsprim/node_modules/json-schema/package.json	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/jsprim/node_modules/json-schema/package.json	(working copy)
@@ -1,53 +1,42 @@
 {
-  "name": "json-schema",
-  "version": "0.2.3",
-  "author": {
-    "name": "Kris Zyp"
-  },
-  "description": "JSON Schema validation and specifications",
-  "maintainers": [
+  "author": "Tom de Grunt <tom@degrunt.nl>",
+  "name": "jsonschema",
+  "version": "1.4.1",
+  "license": "MIT",
+  "dependencies": {},
+  "contributors": [
     {
-      "name": "Kris Zyp",
-      "email": "kriszyp@gmail.com"
+      "name": "Austin Wright"
     }
   ],
+  "main": "./lib/index.js",
+  "typings": "./lib/index.d.ts",
+  "devDependencies": {
+    "@stryker-mutator/core": "^4.0.0",
+    "@stryker-mutator/mocha-runner": "^4.0.0",
+    "chai": "~4.2.0",
+    "eslint": "^7.7.0",
+    "json-metaschema": "^1.2.0",
+    "mocha": "~8.1.1"
+  },
+  "optionalDependencies": {},
+  "engines": {
+    "node": "*"
+  },
   "keywords": [
     "json",
-    "schema"
-  ],
-  "licenses": [
-    {
-      "type": "AFLv2.1",
-      "url": "http://trac.dojotoolkit.org/browser/dojo/trunk/LICENSE#L43"
-    },
-    {
-      "type": "BSD",
-      "url": "http://trac.dojotoolkit.org/browser/dojo/trunk/LICENSE#L13"
-    }
+    "schema",
+    "jsonschema",
+    "validator",
+    "validation"
   ],
   "repository": {
     "type": "git",
-    "url": "http://github.com/kriszyp/json-schema"
-  },
-  "directories": {
-    "lib": "./lib"
-  },
-  "main": "./lib/validate.js",
-  "devDependencies": {
-    "vows": "*"
+    "url": "git://github.com/tdegrunt/jsonschema.git"
   },
+  "description": "A fast and easy to use JSON Schema validator",
   "scripts": {
-    "test": "echo TESTS DISABLED vows --spec test/*.js"
-  },
-  "readme": "JSON Schema is a repository for the JSON Schema specification, reference schemas and a CommonJS implementation of JSON Schema (not the only JavaScript implementation of JSON Schema, JSV is another excellent JavaScript validator).\r\n\r\nCode is licensed under the AFL or BSD license as part of the Persevere \r\nproject which is administered under the Dojo foundation,\r\nand all contributions require a Dojo CLA.",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/kriszyp/json-schema/issues"
-  },
-  "_id": "json-schema@0.2.3",
-  "dist": {
-    "shasum": "2cf45b1e9dc12840e2e74eb96496e6934ae92aed"
-  },
-  "_from": "json-schema@0.2.3",
-  "_resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz"
+    "stryker": "stryker run",
+    "test": "./node_modules/.bin/mocha -R spec"
+  }
 }
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/README.md
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/README.md	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/README.md	(working copy)
@@ -126,6 +126,9 @@
   - `rfc4253`: raw OpenSSH wire format
   - `openssh`: new post-OpenSSH 6.5 internal format, produced by 
                `ssh-keygen -o`
+  - `dnssec`: `.key` file format output by `dnssec-keygen` etc
+  - `putty`: the PuTTY `.ppk` file format (supports truncated variant without
+             all the lines from `Private-Lines:` onwards)
 - `options` -- Optional Object, extra options, with keys:
   - `filename` -- Optional String, name for the key being parsed 
                   (eg. the filename that was opened). Used to generate
@@ -174,7 +177,7 @@
 
 Same as `this.toBuffer(format).toString()`.
 
-### `Key#fingerprint([algorithm = 'sha256'])`
+### `Key#fingerprint([algorithm = 'sha256'[, hashType = 'ssh']])`
 
 Creates a new `Fingerprint` object representing this Key's fingerprint.
 
@@ -182,6 +185,9 @@
 
 - `algorithm` -- String name of hash algorithm to use, valid options are `md5`,
                  `sha1`, `sha256`, `sha384`, `sha512`
+- `hashType` -- String name of fingerprint hash type to use, valid options are
+                `ssh` (the type of fingerprint used by OpenSSH, e.g. in
+                `ssh-keygen`), `spki` (used by HPKP, some OpenSSL applications)
 
 ### `Key#createVerify([hashAlgorithm])`
 
@@ -227,17 +233,31 @@
 - `format` -- String name of format to use, valid options are:
   - `auto`: choose automatically from all below
   - `pem`: supports both PKCS#1 and PKCS#8
-  - `ssh`, `openssh`: new post-OpenSSH 6.5 internal format, produced by 
+  - `ssh`, `openssh`: new post-OpenSSH 6.5 internal format, produced by
                       `ssh-keygen -o`
   - `pkcs1`, `pkcs8`: variants of `pem`
   - `rfc4253`: raw OpenSSH wire format
+  - `dnssec`: `.private` format output by `dnssec-keygen` etc.
 - `options` -- Optional Object, extra options, with keys:
-  - `filename` -- Optional String, name for the key being parsed 
+  - `filename` -- Optional String, name for the key being parsed
                   (eg. the filename that was opened). Used to generate
                   Error messages
   - `passphrase` -- Optional String, encryption passphrase used to decrypt an
                     encrypted PEM file
 
+### `generatePrivateKey(type[, options])`
+
+Generates a new private key of a certain key type, from random data.
+
+Parameters
+
+- `type` -- String, type of key to generate. Currently supported are `'ecdsa'`
+            and `'ed25519'`
+- `options` -- optional Object, with keys:
+  - `curve` -- optional String, for `'ecdsa'` keys, specifies the curve to use.
+               If ECDSA is specified and this option is not given, defaults to
+               using `'nistp256'`.
+
 ### `PrivateKey.isPrivateKey(obj)`
 
 Returns `true` if the given object is a valid `PrivateKey` object created by a
@@ -320,7 +340,7 @@
 
 ## Fingerprints
 
-### `parseFingerprint(fingerprint[, algorithms])`
+### `parseFingerprint(fingerprint[, options])`
 
 Pre-parses a fingerprint, creating a `Fingerprint` object that can be used to
 quickly locate a key by using the `Fingerprint#matches` function.
@@ -328,9 +348,15 @@
 Parameters
 
 - `fingerprint` -- String, the fingerprint value, in any supported format
-- `algorithms` -- Optional list of strings, names of hash algorithms to limit
-                  support to. If `fingerprint` uses a hash algorithm not on
-                  this list, throws `InvalidAlgorithmError`.
+- `options` -- Optional Object, with properties:
+  - `algorithms` -- Array of strings, names of hash algorithms to limit
+                support to. If `fingerprint` uses a hash algorithm not on
+                this list, throws `InvalidAlgorithmError`.
+  - `hashType` -- String, the type of hash the fingerprint uses, either `ssh`
+                  or `spki` (normally auto-detected based on the format, but
+                  can be overridden)
+  - `type` -- String, the entity this fingerprint identifies, either `key` or
+              `certificate`
 
 ### `Fingerprint.isFingerprint(obj)`
 
@@ -351,14 +377,19 @@
               `base64`. If this `Fingerprint` uses the `md5` algorithm, the
               default format is `hex`. Otherwise, the default is `base64`.
 
-### `Fingerprint#matches(key)`
+### `Fingerprint#matches(keyOrCertificate)`
 
-Verifies whether or not this `Fingerprint` matches a given `Key`. This function
-uses double-hashing to avoid leaking timing information. Returns a boolean.
+Verifies whether or not this `Fingerprint` matches a given `Key` or
+`Certificate`. This function uses double-hashing to avoid leaking timing
+information. Returns a boolean.
+
+Note that a `Key`-type Fingerprint will always return `false` if asked to match
+a `Certificate` and vice versa.
 
 Parameters
 
-- `key` -- a `Key` object, the key to match this fingerprint against
+- `keyOrCertificate` -- a `Key` object or `Certificate` object, the entity to
+                        match this fingerprint against
 
 ## Signatures
 
@@ -408,10 +439,10 @@
 to access basic metadata about certificates, extract public keys from them, and
 also to generate simple self-signed certificates from an existing key.
 
-Notably, there is no implementation of CA chain-of-trust verification, and no
-support for key usage restrictions (or other kinds of restrictions). Please do
-the security world a favour, and DO NOT use this code for certificate
-verification in the traditional X.509 CA chain style.
+Notably, there is no implementation of CA chain-of-trust verification, and only
+very minimal support for key usage restrictions. Please do the security world
+a favour, and DO NOT use this code for certificate verification in the
+traditional X.509 CA chain style.
 
 ### `parseCertificate(data, format)`
 
@@ -436,6 +467,7 @@
                                   certificate validity period. If given
                                   `lifetime` will be ignored
    - `serial` -- optional Buffer, the serial number of the certificate
+   - `purposes` -- optional Array of String, X.509 key usage restrictions
 
 ### `createCertificate(subject, key, issuer, issuerKey[, options])`
 
@@ -452,6 +484,7 @@
                                   certificate validity period. If given
                                   `lifetime` will be ignored
    - `serial` -- optional Buffer, the serial number of the certificate
+   - `purposes` -- optional Array of String, X.509 key usage restrictions
 
 ### `Certificate#subjects`
 
@@ -475,6 +508,41 @@
 The serial number of the certificate. As this is normally a 64-bit or wider
 integer, it is returned as a Buffer.
 
+### `Certificate#purposes`
+
+Array of Strings indicating the X.509 key usage purposes that this certificate
+is valid for. The possible strings at the moment are:
+
+ * `'signature'` -- key can be used for digital signatures
+ * `'identity'` -- key can be used to attest about the identity of the signer
+                   (X.509 calls this `nonRepudiation`)
+ * `'codeSigning'` -- key can be used to sign executable code
+ * `'keyEncryption'` -- key can be used to encrypt other keys
+ * `'encryption'` -- key can be used to encrypt data (only applies for RSA)
+ * `'keyAgreement'` -- key can be used for key exchange protocols such as
+                       Diffie-Hellman
+ * `'ca'` -- key can be used to sign other certificates (is a Certificate
+             Authority)
+ * `'crl'` -- key can be used to sign Certificate Revocation Lists (CRLs)
+
+### `Certificate#getExtension(nameOrOid)`
+
+Retrieves information about a certificate extension, if present, or returns
+`undefined` if not. The string argument `nameOrOid` should be either the OID
+(for X509 extensions) or the name (for OpenSSH extensions) of the extension
+to retrieve.
+
+The object returned will have the following properties:
+
+ * `format` -- String, set to either `'x509'` or `'openssh'`
+ * `name` or `oid` -- String, only one set based on value of `format`
+ * `data` -- Buffer, the raw data inside the extension
+
+### `Certificate#getExtensions()`
+
+Returns an Array of all present certificate extensions, in the same manner and
+format as `getExtension()`.
+
 ### `Certificate#isExpired([when])`
 
 Tests whether the Certificate is currently expired (i.e. the `validFrom` and
@@ -582,6 +650,44 @@
 
 Returns an Identity instance.
 
+### `identityFromArray(arr)`
+
+Constructs an Identity from an array of DN components (see `Identity#toArray()`
+for the format).
+
+Parameters
+
+ - `arr` -- an Array of Objects, DN components with `name` and `value`
+
+Returns an Identity instance.
+
+
+Supported attributes in DNs:
+
+| Attribute name | OID |
+| -------------- | --- |
+| `cn` | `2.5.4.3` |
+| `o` | `2.5.4.10` |
+| `ou` | `2.5.4.11` |
+| `l` | `2.5.4.7` |
+| `s` | `2.5.4.8` |
+| `c` | `2.5.4.6` |
+| `sn` | `2.5.4.4` |
+| `postalCode` | `2.5.4.17` |
+| `serialNumber` | `2.5.4.5` |
+| `street` | `2.5.4.9` |
+| `x500UniqueIdentifier` | `2.5.4.45` |
+| `role` | `2.5.4.72` |
+| `telephoneNumber` | `2.5.4.20` |
+| `description` | `2.5.4.13` |
+| `dc` | `0.9.2342.19200300.100.1.25` |
+| `uid` | `0.9.2342.19200300.100.1.1` |
+| `mail` | `0.9.2342.19200300.100.1.3` |
+| `title` | `2.5.4.12` |
+| `gn` | `2.5.4.42` |
+| `initials` | `2.5.4.43` |
+| `pseudonym` | `2.5.4.65` |
+
 ### `Identity#toString()`
 
 Returns the identity as an LDAP-style DN string.
@@ -599,7 +705,39 @@
 
 ### `Identity#cn`
 
-The value of the first `CN=` in the DN, if any.
+The value of the first `CN=` in the DN, if any. It's probably better to use
+the `#get()` method instead of this property.
+
+### `Identity#get(name[, asArray])`
+
+Returns the value of a named attribute in the Identity DN. If there is no
+attribute of the given name, returns `undefined`. If multiple components
+of the DN contain an attribute of this name, an exception is thrown unless
+the `asArray` argument is given as `true` -- then they will be returned as
+an Array in the same order they appear in the DN.
+
+Parameters
+
+ - `name` -- a String
+ - `asArray` -- an optional Boolean
+
+### `Identity#toArray()`
+
+Returns the Identity as an Array of DN component objects. This looks like:
+
+```js
+[ {
+  "name": "cn",
+  "value": "Joe Bloggs"
+},
+{
+  "name": "o",
+  "value": "Organisation Ltd"
+} ]
+```
+
+Each object has a `name` and a `value` property. The returned objects may be
+safely modified.
 
 Errors
 ------
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/bin/sshpk-conv
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/bin/sshpk-conv	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/bin/sshpk-conv	(working copy)
@@ -1,7 +1,7 @@
 #!/usr/bin/env node
 // -*- mode: js -*-
 // vim: set filetype=javascript :
-// Copyright 2015 Joyent, Inc.  All rights reserved.
+// Copyright 2018 Joyent, Inc.	All rights reserved.
 
 var dashdash = require('dashdash');
 var sshpk = require('../lib/index');
@@ -48,6 +48,21 @@
 		help: 'Print key metadata instead of converting'
 	},
 	{
+		names: ['fingerprint', 'F'],
+		type: 'bool',
+		help: 'Output key fingerprint'
+	},
+	{
+		names: ['hash', 'H'],
+		type: 'string',
+		help: 'Hash function to use for key fingeprint with -F'
+	},
+	{
+		names: ['spki', 's'],
+		type: 'bool',
+		help: 'With -F, generates an SPKI fingerprint instead of SSH'
+	},
+	{
 		names: ['comment', 'c'],
 		type: 'string',
 		help: 'Set key comment, if output format supports'
@@ -75,12 +90,18 @@
 		var help = parser.help({}).trimRight();
 		console.error('sshpk-conv: converts between SSH key formats\n');
 		console.error(help);
-		console.error('\navailable formats:');
+		console.error('\navailable key formats:');
 		console.error('  - pem, pkcs1     eg id_rsa');
 		console.error('  - ssh            eg id_rsa.pub');
 		console.error('  - pkcs8          format you want for openssl');
 		console.error('  - openssh        like output of ssh-keygen -o');
 		console.error('  - rfc4253        raw OpenSSH wire format');
+		console.error('  - dnssec         dnssec-keygen format');
+		console.error('  - putty          PuTTY ppk format');
+		console.error('\navailable fingerprint formats:');
+		console.error('  - hex            colon-separated hex for SSH');
+		console.error('                   straight hex for SPKI');
+		console.error('  - base64         SHA256:* format from OpenSSH');
 		process.exit(1);
 	}
 
@@ -110,9 +131,7 @@
 			inFile = fs.createReadStream(inFilePath);
 		}
 	} catch (e) {
-		console.error('sshpk-conv: error opening input file' +
-		     ': ' + e.name + ': ' + e.message);
-		process.exit(1);
+		ifError(e, 'error opening input file');
 	}
 
 	var outFile = process.stdout;
@@ -123,9 +142,7 @@
 			outFile = fs.createWriteStream(opts.out);
 		}
 	} catch (e) {
-		console.error('sshpk-conv: error opening output file' +
-		    ': ' + e.name + ': ' + e.message);
-		process.exit(1);
+		ifError(e, 'error opening output file');
 	}
 
 	var bufs = [];
@@ -149,20 +166,14 @@
 		} catch (e) {
 			if (e.name === 'KeyEncryptedError') {
 				getPassword(function (err, pw) {
-					if (err) {
-						console.log('sshpk-conv: ' +
-						    err.name + ': ' +
-						    err.message);
-						process.exit(1);
-					}
+					if (err)
+						ifError(err);
 					parseOpts.passphrase = pw;
 					processKey();
 				});
 				return;
 			}
-			console.error('sshpk-conv: ' +
-			    e.name + ': ' + e.message);
-			process.exit(1);
+			ifError(e);
 		}
 
 		if (opts.derive)
@@ -171,18 +182,7 @@
 		if (opts.comment)
 			key.comment = opts.comment;
 
-		if (!opts.identify) {
-			fmt = undefined;
-			if (opts.outformat)
-				fmt = opts.outformat;
-			outFile.write(key.toBuffer(fmt));
-			if (fmt === 'ssh' ||
-			    (!opts.private && fmt === undefined))
-				outFile.write('\n');
-			outFile.once('drain', function () {
-				process.exit(0);
-			});
-		} else {
+		if (opts.identify) {
 			var kind = 'public';
 			if (sshpk.PrivateKey.isPrivateKey(key))
 				kind = 'private';
@@ -192,10 +192,52 @@
 				console.log('ECDSA curve: %s', key.curve);
 			if (key.comment)
 				console.log('Comment: %s', key.comment);
-			console.log('Fingerprint:');
-			console.log('  ' + key.fingerprint().toString());
-			console.log('  ' + key.fingerprint('md5').toString());
+			console.log('SHA256 fingerprint: ' +
+			    key.fingerprint('sha256').toString());
+			console.log('MD5 fingerprint: ' +
+			    key.fingerprint('md5').toString());
+			console.log('SPKI-SHA256 fingerprint: ' +
+			    key.fingerprint('sha256', 'spki').toString());
 			process.exit(0);
+			return;
+		}
+
+		if (opts.fingerprint) {
+			var hash = opts.hash;
+			var type = opts.spki ? 'spki' : 'ssh';
+			var format = opts.outformat;
+			var fp = key.fingerprint(hash, type).toString(format);
+			outFile.write(fp);
+			outFile.write('\n');
+			outFile.once('drain', function () {
+				process.exit(0);
+			});
+			return;
 		}
+
+		fmt = undefined;
+		if (opts.outformat)
+			fmt = opts.outformat;
+		outFile.write(key.toBuffer(fmt));
+		if (fmt === 'ssh' ||
+		    (!opts.private && fmt === undefined))
+			outFile.write('\n');
+		outFile.once('drain', function () {
+			process.exit(0);
+		});
 	});
 }
+
+function ifError(e, txt) {
+	if (txt)
+		txt = txt + ': ';
+	else
+		txt = '';
+	console.error('sshpk-conv: ' + txt + e.name + ': ' + e.message);
+	if (process.env['DEBUG'] || process.env['V']) {
+		console.error(e.stack);
+		if (e.innerErr)
+			console.error(e.innerErr.stack);
+	}
+	process.exit(1);
+}
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/bin/sshpk-verify
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/bin/sshpk-verify	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/bin/sshpk-verify	(working copy)
@@ -7,6 +7,7 @@
 var sshpk = require('../lib/index');
 var fs = require('fs');
 var path = require('path');
+var Buffer = require('safer-buffer').Buffer;
 
 var options = [
 	{
@@ -93,7 +94,7 @@
 	}
 
 	var fmt = opts.format || 'asn1';
-	var sigData = new Buffer(opts.signature, 'base64');
+	var sigData = Buffer.from(opts.signature, 'base64');
 
 	var sig;
 	try {
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/algs.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/algs.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/algs.js	(working copy)
@@ -1,5 +1,7 @@
 // Copyright 2015 Joyent, Inc.
 
+var Buffer = require('safer-buffer').Buffer;
+
 var algInfo = {
 	'dsa': {
 		parts: ['p', 'q', 'g', 'y'],
@@ -14,9 +16,8 @@
 		sizePart: 'Q'
 	},
 	'ed25519': {
-		parts: ['R'],
-		normalize: false,
-		sizePart: 'R'
+		parts: ['A'],
+		sizePart: 'A'
 	}
 };
 algInfo['curve25519'] = algInfo['ed25519'];
@@ -32,8 +33,7 @@
 		parts: ['curve', 'Q', 'd']
 	},
 	'ed25519': {
-		parts: ['R', 'r'],
-		normalize: false
+		parts: ['A', 'k']
 	}
 };
 algPrivInfo['curve25519'] = algPrivInfo['ed25519'];
@@ -54,27 +54,27 @@
 	'nistp256': {
 		size: 256,
 		pkcs8oid: '1.2.840.10045.3.1.7',
-		p: new Buffer(('00' +
+		p: Buffer.from(('00' +
 		    'ffffffff 00000001 00000000 00000000' +
 		    '00000000 ffffffff ffffffff ffffffff').
 		    replace(/ /g, ''), 'hex'),
-		a: new Buffer(('00' +
+		a: Buffer.from(('00' +
 		    'FFFFFFFF 00000001 00000000 00000000' +
 		    '00000000 FFFFFFFF FFFFFFFF FFFFFFFC').
 		    replace(/ /g, ''), 'hex'),
-		b: new Buffer((
+		b: Buffer.from((
 		    '5ac635d8 aa3a93e7 b3ebbd55 769886bc' +
 		    '651d06b0 cc53b0f6 3bce3c3e 27d2604b').
 		    replace(/ /g, ''), 'hex'),
-		s: new Buffer(('00' +
+		s: Buffer.from(('00' +
 		    'c49d3608 86e70493 6a6678e1 139d26b7' +
 		    '819f7e90').
 		    replace(/ /g, ''), 'hex'),
-		n: new Buffer(('00' +
+		n: Buffer.from(('00' +
 		    'ffffffff 00000000 ffffffff ffffffff' +
 		    'bce6faad a7179e84 f3b9cac2 fc632551').
 		    replace(/ /g, ''), 'hex'),
-		G: new Buffer(('04' +
+		G: Buffer.from(('04' +
 		    '6b17d1f2 e12c4247 f8bce6e5 63a440f2' +
 		    '77037d81 2deb33a0 f4a13945 d898c296' +
 		    '4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16' +
@@ -84,31 +84,31 @@
 	'nistp384': {
 		size: 384,
 		pkcs8oid: '1.3.132.0.34',
-		p: new Buffer(('00' +
+		p: Buffer.from(('00' +
 		    'ffffffff ffffffff ffffffff ffffffff' +
 		    'ffffffff ffffffff ffffffff fffffffe' +
 		    'ffffffff 00000000 00000000 ffffffff').
 		    replace(/ /g, ''), 'hex'),
-		a: new Buffer(('00' +
+		a: Buffer.from(('00' +
 		    'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF' +
 		    'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE' +
 		    'FFFFFFFF 00000000 00000000 FFFFFFFC').
 		    replace(/ /g, ''), 'hex'),
-		b: new Buffer((
+		b: Buffer.from((
 		    'b3312fa7 e23ee7e4 988e056b e3f82d19' +
 		    '181d9c6e fe814112 0314088f 5013875a' +
 		    'c656398d 8a2ed19d 2a85c8ed d3ec2aef').
 		    replace(/ /g, ''), 'hex'),
-		s: new Buffer(('00' +
+		s: Buffer.from(('00' +
 		    'a335926a a319a27a 1d00896a 6773a482' +
 		    '7acdac73').
 		    replace(/ /g, ''), 'hex'),
-		n: new Buffer(('00' +
+		n: Buffer.from(('00' +
 		    'ffffffff ffffffff ffffffff ffffffff' +
 		    'ffffffff ffffffff c7634d81 f4372ddf' +
 		    '581a0db2 48b0a77a ecec196a ccc52973').
 		    replace(/ /g, ''), 'hex'),
-		G: new Buffer(('04' +
+		G: Buffer.from(('04' +
 		    'aa87ca22 be8b0537 8eb1c71e f320ad74' +
 		    '6e1d3b62 8ba79b98 59f741e0 82542a38' +
 		    '5502f25d bf55296c 3a545e38 72760ab7' +
@@ -120,34 +120,34 @@
 	'nistp521': {
 		size: 521,
 		pkcs8oid: '1.3.132.0.35',
-		p: new Buffer((
+		p: Buffer.from((
 		    '01ffffff ffffffff ffffffff ffffffff' +
 		    'ffffffff ffffffff ffffffff ffffffff' +
 		    'ffffffff ffffffff ffffffff ffffffff' +
 		    'ffffffff ffffffff ffffffff ffffffff' +
 		    'ffff').replace(/ /g, ''), 'hex'),
-		a: new Buffer(('01FF' +
+		a: Buffer.from(('01FF' +
 		    'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF' +
 		    'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF' +
 		    'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF' +
 		    'FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFC').
 		    replace(/ /g, ''), 'hex'),
-		b: new Buffer(('51' +
+		b: Buffer.from(('51' +
 		    '953eb961 8e1c9a1f 929a21a0 b68540ee' +
 		    'a2da725b 99b315f3 b8b48991 8ef109e1' +
 		    '56193951 ec7e937b 1652c0bd 3bb1bf07' +
 		    '3573df88 3d2c34f1 ef451fd4 6b503f00').
 		    replace(/ /g, ''), 'hex'),
-		s: new Buffer(('00' +
+		s: Buffer.from(('00' +
 		    'd09e8800 291cb853 96cc6717 393284aa' +
 		    'a0da64ba').replace(/ /g, ''), 'hex'),
-		n: new Buffer(('01ff' +
+		n: Buffer.from(('01ff' +
 		    'ffffffff ffffffff ffffffff ffffffff' +
 		    'ffffffff ffffffff ffffffff fffffffa' +
 		    '51868783 bf2f966b 7fcc0148 f709a5d0' +
 		    '3bb5c9b8 899c47ae bb6fb71e 91386409').
 		    replace(/ /g, ''), 'hex'),
-		G: new Buffer(('04' +
+		G: Buffer.from(('04' +
 		    '00c6 858e06b7 0404e9cd 9e3ecb66 2395b442' +
 		         '9c648139 053fb521 f828af60 6b4d3dba' +
 		         'a14b5e77 efe75928 fe1dc127 a2ffa8de' +
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/certificate.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/certificate.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/certificate.js	(working copy)
@@ -3,6 +3,7 @@
 module.exports = Certificate;
 
 var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
 var algs = require('./algs');
 var crypto = require('crypto');
 var Fingerprint = require('./fingerprint');
@@ -39,6 +40,8 @@
 	assert.date(opts.validFrom, 'options.validFrom');
 	assert.date(opts.validUntil, 'optons.validUntil');
 
+	assert.optionalArrayOfString(opts.purposes, 'options.purposes');
+
 	this._hashCache = {};
 
 	this.subjects = opts.subjects;
@@ -49,6 +52,7 @@
 	this.serial = opts.serial;
 	this.validFrom = opts.validFrom;
 	this.validUntil = opts.validUntil;
+	this.purposes = opts.purposes;
 }
 
 Certificate.formats = formats;
@@ -108,10 +112,45 @@
 
 	if (!this.issuer.equals(issuerCert.subjects[0]))
 		return (false);
+	if (this.issuer.purposes && this.issuer.purposes.length > 0 &&
+	    this.issuer.purposes.indexOf('ca') === -1) {
+		return (false);
+	}
 
 	return (this.isSignedByKey(issuerCert.subjectKey));
 };
 
+Certificate.prototype.getExtension = function (keyOrOid) {
+	assert.string(keyOrOid, 'keyOrOid');
+	var ext = this.getExtensions().filter(function (maybeExt) {
+		if (maybeExt.format === 'x509')
+			return (maybeExt.oid === keyOrOid);
+		if (maybeExt.format === 'openssh')
+			return (maybeExt.name === keyOrOid);
+		return (false);
+	})[0];
+	return (ext);
+};
+
+Certificate.prototype.getExtensions = function () {
+	var exts = [];
+	var x509 = this.signatures.x509;
+	if (x509 && x509.extras && x509.extras.exts) {
+		x509.extras.exts.forEach(function (ext) {
+			ext.format = 'x509';
+			exts.push(ext);
+		});
+	}
+	var openssh = this.signatures.openssh;
+	if (openssh && openssh.exts) {
+		openssh.exts.forEach(function (ext) {
+			ext.format = 'openssh';
+			exts.push(ext);
+		});
+	}
+	return (exts);
+};
+
 Certificate.prototype.isSignedByKey = function (issuerKey) {
 	utils.assertCompatible(issuerKey, Key, [1, 2], 'issuerKey');
 
@@ -178,7 +217,48 @@
 	assert.optionalBuffer(options.serial, 'options.serial');
 	var serial = options.serial;
 	if (serial === undefined)
-		serial = new Buffer('0000000000000001', 'hex');
+		serial = Buffer.from('0000000000000001', 'hex');
+
+	var purposes = options.purposes;
+	if (purposes === undefined)
+		purposes = [];
+
+	if (purposes.indexOf('signature') === -1)
+		purposes.push('signature');
+
+	/* Self-signed certs are always CAs. */
+	if (purposes.indexOf('ca') === -1)
+		purposes.push('ca');
+	if (purposes.indexOf('crl') === -1)
+		purposes.push('crl');
+
+	/*
+	 * If we weren't explicitly given any other purposes, do the sensible
+	 * thing and add some basic ones depending on the subject type.
+	 */
+	if (purposes.length <= 3) {
+		var hostSubjects = subjects.filter(function (subject) {
+			return (subject.type === 'host');
+		});
+		var userSubjects = subjects.filter(function (subject) {
+			return (subject.type === 'user');
+		});
+		if (hostSubjects.length > 0) {
+			if (purposes.indexOf('serverAuth') === -1)
+				purposes.push('serverAuth');
+		}
+		if (userSubjects.length > 0) {
+			if (purposes.indexOf('clientAuth') === -1)
+				purposes.push('clientAuth');
+		}
+		if (userSubjects.length > 0 || hostSubjects.length > 0) {
+			if (purposes.indexOf('keyAgreement') === -1)
+				purposes.push('keyAgreement');
+			if (key.type === 'rsa' &&
+			    purposes.indexOf('encryption') === -1)
+				purposes.push('encryption');
+		}
+	}
 
 	var cert = new Certificate({
 		subjects: subjects,
@@ -188,7 +268,8 @@
 		signatures: {},
 		serial: serial,
 		validFrom: validFrom,
-		validUntil: validUntil
+		validUntil: validUntil,
+		purposes: purposes
 	});
 	cert.signWith(key);
 
@@ -234,7 +315,43 @@
 	assert.optionalBuffer(options.serial, 'options.serial');
 	var serial = options.serial;
 	if (serial === undefined)
-		serial = new Buffer('0000000000000001', 'hex');
+		serial = Buffer.from('0000000000000001', 'hex');
+
+	var purposes = options.purposes;
+	if (purposes === undefined)
+		purposes = [];
+
+	if (purposes.indexOf('signature') === -1)
+		purposes.push('signature');
+
+	if (options.ca === true) {
+		if (purposes.indexOf('ca') === -1)
+			purposes.push('ca');
+		if (purposes.indexOf('crl') === -1)
+			purposes.push('crl');
+	}
+
+	var hostSubjects = subjects.filter(function (subject) {
+		return (subject.type === 'host');
+	});
+	var userSubjects = subjects.filter(function (subject) {
+		return (subject.type === 'user');
+	});
+	if (hostSubjects.length > 0) {
+		if (purposes.indexOf('serverAuth') === -1)
+			purposes.push('serverAuth');
+	}
+	if (userSubjects.length > 0) {
+		if (purposes.indexOf('clientAuth') === -1)
+			purposes.push('clientAuth');
+	}
+	if (userSubjects.length > 0 || hostSubjects.length > 0) {
+		if (purposes.indexOf('keyAgreement') === -1)
+			purposes.push('keyAgreement');
+		if (key.type === 'rsa' &&
+		    purposes.indexOf('encryption') === -1)
+			purposes.push('encryption');
+	}
 
 	var cert = new Certificate({
 		subjects: subjects,
@@ -244,7 +361,8 @@
 		signatures: {},
 		serial: serial,
 		validFrom: validFrom,
-		validUntil: validUntil
+		validUntil: validUntil,
+		purposes: purposes
 	});
 	cert.signWith(issuerKey);
 
@@ -283,8 +401,9 @@
 /*
  * API versions for Certificate:
  * [1,0] -- initial ver
+ * [1,1] -- openssh format now unpacks extensions
  */
-Certificate.prototype._sshpkApiVersion = [1, 0];
+Certificate.prototype._sshpkApiVersion = [1, 1];
 
 Certificate._oldVersionDetect = function (obj) {
 	return ([1, 0]);
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/dhe.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/dhe.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/dhe.js	(working copy)
@@ -1,19 +1,26 @@
-// Copyright 2015 Joyent, Inc.
+// Copyright 2017 Joyent, Inc.
 
-module.exports = DiffieHellman;
+module.exports = {
+	DiffieHellman: DiffieHellman,
+	generateECDSA: generateECDSA,
+	generateED25519: generateED25519
+};
 
 var assert = require('assert-plus');
 var crypto = require('crypto');
+var Buffer = require('safer-buffer').Buffer;
 var algs = require('./algs');
 var utils = require('./utils');
-var ed;
+var nacl = require('tweetnacl');
 
 var Key = require('./key');
 var PrivateKey = require('./private-key');
 
 var CRYPTO_HAVE_ECDH = (crypto.createECDH !== undefined);
 
-var ecdh, ec, jsbn;
+var ecdh = require('ecc-jsbn');
+var ec = require('ecc-jsbn/lib/ec');
+var jsbn = require('jsbn').BigInteger;
 
 function DiffieHellman(key) {
 	utils.assertCompatible(key, Key, [1, 4], 'key');
@@ -38,13 +45,6 @@
 
 	} else if (key.type === 'ecdsa') {
 		if (!CRYPTO_HAVE_ECDH) {
-			if (ecdh === undefined)
-				ecdh = require('ecc-jsbn');
-			if (ec === undefined)
-				ec = require('ecc-jsbn/lib/ec');
-			if (jsbn === undefined)
-				jsbn = require('jsbn').BigInteger;
-
 			this._ecParams = new X9ECParameters(this._curve);
 
 			if (this._isPriv) {
@@ -71,14 +71,9 @@
 		this._dh.setPublicKey(key.part.Q.data);
 
 	} else if (key.type === 'curve25519') {
-		if (ed === undefined)
-			ed = require('jodid25519');
-
 		if (this._isPriv) {
-			this._priv = key.part.r.data;
-			if (this._priv[0] === 0x00)
-				this._priv = this._priv.slice(1);
-			this._priv = this._priv.slice(0, 32);
+			utils.assertCompatible(key, PrivateKey, [1, 5], 'key');
+			this._priv = key.part.k.data;
 		}
 
 	} else {
@@ -142,7 +137,10 @@
 		}
 
 	} else if (pk.type === 'curve25519') {
-		this._priv = pk.part.r.data;
+		var k = pk.part.k;
+		if (!pk.part.k)
+			k = pk.part.r;
+		this._priv = k.data;
 		if (this._priv[0] === 0x00)
 			this._priv = this._priv.slice(1);
 		this._priv = this._priv.slice(0, 32);
@@ -174,15 +172,17 @@
 		}
 
 	} else if (this._algo === 'curve25519') {
-		pub = otherpk.part.R.data;
-		if (pub[0] === 0x00)
+		pub = otherpk.part.A.data;
+		while (pub[0] === 0x00 && pub.length > 32)
 			pub = pub.slice(1);
+		var priv = this._priv;
+		assert.strictEqual(pub.length, 32);
+		assert.strictEqual(priv.length, 32);
 
-		var secret = ed.dh.computeKey(
-		    this._priv.toString('binary'),
-		    pub.toString('binary'));
+		var secret = nacl.box.before(new Uint8Array(pub),
+		    new Uint8Array(priv));
 
-		return (new Buffer(secret, 'binary'));
+		return (Buffer.from(secret));
 	}
 
 	throw (new Error('Invalid algorithm: ' + this._algo));
@@ -211,7 +211,7 @@
 			this._dh.generateKeys();
 
 			parts.push({name: 'curve',
-			    data: new Buffer(this._curve)});
+			    data: Buffer.from(this._curve)});
 			parts.push({name: 'Q', data: this._dh.getPublicKey()});
 			parts.push({name: 'd', data: this._dh.getPrivateKey()});
 			this._key = new PrivateKey({
@@ -229,14 +229,14 @@
 			priv = r.mod(n1).add(jsbn.ONE);
 			pub = this._ecParams.getG().multiply(priv);
 
-			priv = new Buffer(priv.toByteArray());
-			pub = new Buffer(this._ecParams.getCurve().
+			priv = Buffer.from(priv.toByteArray());
+			pub = Buffer.from(this._ecParams.getCurve().
 			    encodePointHex(pub), 'hex');
 
 			this._priv = new ECPrivate(this._ecParams, priv);
 
 			parts.push({name: 'curve',
-			    data: new Buffer(this._curve)});
+			    data: Buffer.from(this._curve)});
 			parts.push({name: 'Q', data: pub});
 			parts.push({name: 'd', data: priv});
 
@@ -250,13 +250,15 @@
 		}
 
 	} else if (this._algo === 'curve25519') {
-		priv = ed.dh.generateKey();
-		pub = ed.dh.publicKey(priv);
-		this._priv = priv = new Buffer(priv, 'binary');
-		pub = new Buffer(pub, 'binary');
+		var pair = nacl.box.keyPair();
+		priv = Buffer.from(pair.secretKey);
+		pub = Buffer.from(pair.publicKey);
+		priv = Buffer.concat([priv, pub]);
+		assert.strictEqual(priv.length, 64);
+		assert.strictEqual(pub.length, 32);
 
-		parts.push({name: 'R', data: pub});
-		parts.push({name: 'r', data: Buffer.concat([priv, pub])});
+		parts.push({name: 'A', data: pub});
+		parts.push({name: 'k', data: priv});
 		this._key = new PrivateKey({
 			type: 'curve25519',
 			parts: parts
@@ -307,5 +309,89 @@
 ECPrivate.prototype.deriveSharedSecret = function (pubKey) {
 	assert.ok(pubKey instanceof ECPublic);
 	var S = pubKey._pub.multiply(this._priv);
-	return (new Buffer(S.getX().toBigInteger().toByteArray()));
+	return (Buffer.from(S.getX().toBigInteger().toByteArray()));
 };
+
+function generateED25519() {
+	var pair = nacl.sign.keyPair();
+	var priv = Buffer.from(pair.secretKey);
+	var pub = Buffer.from(pair.publicKey);
+	assert.strictEqual(priv.length, 64);
+	assert.strictEqual(pub.length, 32);
+
+	var parts = [];
+	parts.push({name: 'A', data: pub});
+	parts.push({name: 'k', data: priv.slice(0, 32)});
+	var key = new PrivateKey({
+		type: 'ed25519',
+		parts: parts
+	});
+	return (key);
+}
+
+/* Generates a new ECDSA private key on a given curve. */
+function generateECDSA(curve) {
+	var parts = [];
+	var key;
+
+	if (CRYPTO_HAVE_ECDH) {
+		/*
+		 * Node crypto doesn't expose key generation directly, but the
+		 * ECDH instances can generate keys. It turns out this just
+		 * calls into the OpenSSL generic key generator, and we can
+		 * read its output happily without doing an actual DH. So we
+		 * use that here.
+		 */
+		var osCurve = {
+			'nistp256': 'prime256v1',
+			'nistp384': 'secp384r1',
+			'nistp521': 'secp521r1'
+		}[curve];
+
+		var dh = crypto.createECDH(osCurve);
+		dh.generateKeys();
+
+		parts.push({name: 'curve',
+		    data: Buffer.from(curve)});
+		parts.push({name: 'Q', data: dh.getPublicKey()});
+		parts.push({name: 'd', data: dh.getPrivateKey()});
+
+		key = new PrivateKey({
+			type: 'ecdsa',
+			curve: curve,
+			parts: parts
+		});
+		return (key);
+	} else {
+
+		var ecParams = new X9ECParameters(curve);
+
+		/* This algorithm taken from FIPS PUB 186-4 (section B.4.1) */
+		var n = ecParams.getN();
+		/*
+		 * The crypto.randomBytes() function can only give us whole
+		 * bytes, so taking a nod from X9.62, we round up.
+		 */
+		var cByteLen = Math.ceil((n.bitLength() + 64) / 8);
+		var c = new jsbn(crypto.randomBytes(cByteLen));
+
+		var n1 = n.subtract(jsbn.ONE);
+		var priv = c.mod(n1).add(jsbn.ONE);
+		var pub = ecParams.getG().multiply(priv);
+
+		priv = Buffer.from(priv.toByteArray());
+		pub = Buffer.from(ecParams.getCurve().
+		    encodePointHex(pub), 'hex');
+
+		parts.push({name: 'curve', data: Buffer.from(curve)});
+		parts.push({name: 'Q', data: pub});
+		parts.push({name: 'd', data: priv});
+
+		key = new PrivateKey({
+			type: 'ecdsa',
+			curve: curve,
+			parts: parts
+		});
+		return (key);
+	}
+}
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/ed-compat.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/ed-compat.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/ed-compat.js	(working copy)
@@ -5,16 +5,14 @@
 	Signer: Signer
 };
 
-var nacl;
+var nacl = require('tweetnacl');
 var stream = require('stream');
 var util = require('util');
 var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
 var Signature = require('./signature');
 
 function Verifier(key, hashAlgo) {
-	if (nacl === undefined)
-		nacl = require('tweetnacl');
-
 	if (hashAlgo.toLowerCase() !== 'sha512')
 		throw (new Error('ED25519 only supports the use of ' +
 		    'SHA-512 hashes'));
@@ -33,7 +31,7 @@
 
 Verifier.prototype.update = function (chunk) {
 	if (typeof (chunk) === 'string')
-		chunk = new Buffer(chunk, 'binary');
+		chunk = Buffer.from(chunk, 'binary');
 	this.chunks.push(chunk);
 };
 
@@ -45,7 +43,7 @@
 		sig = signature.toBuffer('raw');
 
 	} else if (typeof (signature) === 'string') {
-		sig = new Buffer(signature, 'base64');
+		sig = Buffer.from(signature, 'base64');
 
 	} else if (Signature.isSignature(signature, [1, 0])) {
 		throw (new Error('signature was created by too old ' +
@@ -56,13 +54,10 @@
 	return (nacl.sign.detached.verify(
 	    new Uint8Array(Buffer.concat(this.chunks)),
 	    new Uint8Array(sig),
-	    new Uint8Array(this.key.part.R.data)));
+	    new Uint8Array(this.key.part.A.data)));
 };
 
 function Signer(key, hashAlgo) {
-	if (nacl === undefined)
-		nacl = require('tweetnacl');
-
 	if (hashAlgo.toLowerCase() !== 'sha512')
 		throw (new Error('ED25519 only supports the use of ' +
 		    'SHA-512 hashes'));
@@ -81,15 +76,16 @@
 
 Signer.prototype.update = function (chunk) {
 	if (typeof (chunk) === 'string')
-		chunk = new Buffer(chunk, 'binary');
+		chunk = Buffer.from(chunk, 'binary');
 	this.chunks.push(chunk);
 };
 
 Signer.prototype.sign = function () {
 	var sig = nacl.sign.detached(
 	    new Uint8Array(Buffer.concat(this.chunks)),
-	    new Uint8Array(this.key.part.r.data));
-	var sigBuf = new Buffer(sig);
+	    new Uint8Array(Buffer.concat([
+		this.key.part.k.data, this.key.part.A.data])));
+	var sigBuf = Buffer.from(sig);
 	var sigObj = Signature.parse(sigBuf, 'ed25519', 'raw');
 	sigObj.hashAlgorithm = 'sha512';
 	return (sigObj);
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/fingerprint.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/fingerprint.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/fingerprint.js	(working copy)
@@ -1,12 +1,14 @@
-// Copyright 2015 Joyent, Inc.
+// Copyright 2018 Joyent, Inc.
 
 module.exports = Fingerprint;
 
 var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
 var algs = require('./algs');
 var crypto = require('crypto');
 var errs = require('./errors');
 var Key = require('./key');
+var PrivateKey = require('./private-key');
 var Certificate = require('./certificate');
 var utils = require('./utils');
 
@@ -25,11 +27,12 @@
 
 	this.hash = opts.hash;
 	this.type = opts.type;
+	this.hashType = opts.hashType;
 }
 
 Fingerprint.prototype.toString = function (format) {
 	if (format === undefined) {
-		if (this.algorithm === 'md5')
+		if (this.algorithm === 'md5' || this.hashType === 'spki')
 			format = 'hex';
 		else
 			format = 'base64';
@@ -38,8 +41,12 @@
 
 	switch (format) {
 	case 'hex':
+		if (this.hashType === 'spki')
+			return (this.hash.toString('hex'));
 		return (addColons(this.hash.toString('hex')));
 	case 'base64':
+		if (this.hashType === 'spki')
+			return (this.hash.toString('base64'));
 		return (sshBase64Format(this.algorithm,
 		    this.hash.toString('base64')));
 	default:
@@ -49,14 +56,20 @@
 
 Fingerprint.prototype.matches = function (other) {
 	assert.object(other, 'key or certificate');
-	if (this.type === 'key') {
+	if (this.type === 'key' && this.hashType !== 'ssh') {
+		utils.assertCompatible(other, Key, [1, 7], 'key with spki');
+		if (PrivateKey.isPrivateKey(other)) {
+			utils.assertCompatible(other, PrivateKey, [1, 6],
+			    'privatekey with spki support');
+		}
+	} else if (this.type === 'key') {
 		utils.assertCompatible(other, Key, [1, 0], 'key');
 	} else {
 		utils.assertCompatible(other, Certificate, [1, 0],
 		    'certificate');
 	}
 
-	var theirHash = other.hash(this.algorithm);
+	var theirHash = other.hash(this.algorithm, this.hashType);
 	var theirHash2 = crypto.createHash(this.algorithm).
 	    update(theirHash).digest('base64');
 
@@ -67,6 +80,11 @@
 	return (this.hash2 === theirHash2);
 };
 
+/*JSSTYLED*/
+var base64RE = /^[A-Za-z0-9+\/=]+$/;
+/*JSSTYLED*/
+var hexRE = /^[a-fA-F0-9]+$/;
+
 Fingerprint.parse = function (fp, options) {
 	assert.string(fp, 'fingerprint');
 
@@ -80,17 +98,22 @@
 		options = {};
 	if (options.enAlgs !== undefined)
 		enAlgs = options.enAlgs;
+	if (options.algorithms !== undefined)
+		enAlgs = options.algorithms;
 	assert.optionalArrayOfString(enAlgs, 'algorithms');
 
+	var hashType = 'ssh';
+	if (options.hashType !== undefined)
+		hashType = options.hashType;
+	assert.string(hashType, 'options.hashType');
+
 	var parts = fp.split(':');
 	if (parts.length == 2) {
 		alg = parts[0].toLowerCase();
-		/*JSSTYLED*/
-		var base64RE = /^[A-Za-z0-9+\/=]+$/;
 		if (!base64RE.test(parts[1]))
 			throw (new FingerprintFormatError(fp));
 		try {
-			hash = new Buffer(parts[1], 'base64');
+			hash = Buffer.from(parts[1], 'base64');
 		} catch (e) {
 			throw (new FingerprintFormatError(fp));
 		}
@@ -98,16 +121,50 @@
 		alg = 'md5';
 		if (parts[0].toLowerCase() === 'md5')
 			parts = parts.slice(1);
+		parts = parts.map(function (p) {
+			while (p.length < 2)
+				p = '0' + p;
+			if (p.length > 2)
+				throw (new FingerprintFormatError(fp));
+			return (p);
+		});
 		parts = parts.join('');
-		/*JSSTYLED*/
-		var md5RE = /^[a-fA-F0-9]+$/;
-		if (!md5RE.test(parts))
+		if (!hexRE.test(parts) || parts.length % 2 !== 0)
 			throw (new FingerprintFormatError(fp));
 		try {
-			hash = new Buffer(parts, 'hex');
+			hash = Buffer.from(parts, 'hex');
 		} catch (e) {
 			throw (new FingerprintFormatError(fp));
 		}
+	} else {
+		if (hexRE.test(fp)) {
+			hash = Buffer.from(fp, 'hex');
+		} else if (base64RE.test(fp)) {
+			hash = Buffer.from(fp, 'base64');
+		} else {
+			throw (new FingerprintFormatError(fp));
+		}
+
+		switch (hash.length) {
+		case 32:
+			alg = 'sha256';
+			break;
+		case 16:
+			alg = 'md5';
+			break;
+		case 20:
+			alg = 'sha1';
+			break;
+		case 64:
+			alg = 'sha512';
+			break;
+		default:
+			throw (new FingerprintFormatError(fp));
+		}
+
+		/* Plain hex/base64: guess it's probably SPKI unless told. */
+		if (options.hashType === undefined)
+			hashType = 'spki';
 	}
 
 	if (alg === undefined)
@@ -125,7 +182,8 @@
 	return (new Fingerprint({
 		algorithm: alg,
 		hash: hash,
-		type: options.type || 'key'
+		type: options.type || 'key',
+		hashType: hashType
 	}));
 };
 
@@ -151,8 +209,9 @@
  * API versions for Fingerprint:
  * [1,0] -- initial ver
  * [1,1] -- first tagged ver
+ * [1,2] -- hashType and spki support
  */
-Fingerprint.prototype._sshpkApiVersion = [1, 1];
+Fingerprint.prototype._sshpkApiVersion = [1, 2];
 
 Fingerprint._oldVersionDetect = function (obj) {
 	assert.func(obj.toString);
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/auto.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/auto.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/auto.js	(working copy)
@@ -1,4 +1,4 @@
-// Copyright 2015 Joyent, Inc.
+// Copyright 2018 Joyent, Inc.
 
 module.exports = {
 	read: read,
@@ -6,6 +6,7 @@
 };
 
 var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
 var utils = require('../utils');
 var Key = require('../key');
 var PrivateKey = require('../private-key');
@@ -13,6 +14,10 @@
 var pem = require('./pem');
 var ssh = require('./ssh');
 var rfc4253 = require('./rfc4253');
+var dnssec = require('./dnssec');
+var putty = require('./putty');
+
+var DNSSEC_PRIVKEY_HEADER_PREFIX = 'Private-key-format: v1';
 
 function read(buf, options) {
 	if (typeof (buf) === 'string') {
@@ -22,19 +27,39 @@
 			return (ssh.read(buf, options));
 		if (buf.match(/^\s*ecdsa-/))
 			return (ssh.read(buf, options));
-		buf = new Buffer(buf, 'binary');
+		if (buf.match(/^putty-user-key-file-2:/i))
+			return (putty.read(buf, options));
+		if (findDNSSECHeader(buf))
+			return (dnssec.read(buf, options));
+		buf = Buffer.from(buf, 'binary');
 	} else {
 		assert.buffer(buf);
 		if (findPEMHeader(buf))
 			return (pem.read(buf, options));
 		if (findSSHHeader(buf))
 			return (ssh.read(buf, options));
+		if (findPuTTYHeader(buf))
+			return (putty.read(buf, options));
+		if (findDNSSECHeader(buf))
+			return (dnssec.read(buf, options));
 	}
 	if (buf.readUInt32BE(0) < buf.length)
 		return (rfc4253.read(buf, options));
 	throw (new Error('Failed to auto-detect format of key'));
 }
 
+function findPuTTYHeader(buf) {
+	var offset = 0;
+	while (offset < buf.length &&
+	    (buf[offset] === 32 || buf[offset] === 10 || buf[offset] === 9))
+		++offset;
+	if (offset + 22 <= buf.length &&
+	    buf.slice(offset, offset + 22).toString('ascii').toLowerCase() ===
+	    'putty-user-key-file-2:')
+		return (true);
+	return (false);
+}
+
 function findSSHHeader(buf) {
 	var offset = 0;
 	while (offset < buf.length &&
@@ -68,6 +93,32 @@
 	return (true);
 }
 
+function findDNSSECHeader(buf) {
+	// private case first
+	if (buf.length <= DNSSEC_PRIVKEY_HEADER_PREFIX.length)
+		return (false);
+	var headerCheck = buf.slice(0, DNSSEC_PRIVKEY_HEADER_PREFIX.length);
+	if (headerCheck.toString('ascii') === DNSSEC_PRIVKEY_HEADER_PREFIX)
+		return (true);
+
+	// public-key RFC3110 ?
+	// 'domain.com. IN KEY ...' or 'domain.com. IN DNSKEY ...'
+	// skip any comment-lines
+	if (typeof (buf) !== 'string') {
+		buf = buf.toString('ascii');
+	}
+	var lines = buf.split('\n');
+	var line = 0;
+	/* JSSTYLED */
+	while (lines[line].match(/^\;/))
+		line++;
+	if (lines[line].toString('ascii').match(/\. IN KEY /))
+		return (true);
+	if (lines[line].toString('ascii').match(/\. IN DNSKEY /))
+		return (true);
+	return (false);
+}
+
 function write(key, options) {
 	throw (new Error('"auto" format cannot be used for writing'));
 }
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/openssh-cert.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/openssh-cert.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/openssh-cert.js	(working copy)
@@ -1,9 +1,10 @@
-// Copyright 2016 Joyent, Inc.
+// Copyright 2017 Joyent, Inc.
 
 module.exports = {
 	read: read,
 	verify: verify,
 	sign: sign,
+	signAsync: signAsync,
 	write: write,
 
 	/* Internal private API */
@@ -14,6 +15,7 @@
 var assert = require('assert-plus');
 var SSHBuffer = require('../ssh-buffer');
 var crypto = require('crypto');
+var Buffer = require('safer-buffer').Buffer;
 var algs = require('../algs');
 var Key = require('../key');
 var PrivateKey = require('../private-key');
@@ -49,7 +51,7 @@
 	var algo = parts[0];
 	var data = parts[1];
 
-	data = new Buffer(data, 'base64');
+	data = Buffer.from(data, 'base64');
 	return (fromBuffer(data, algo));
 }
 
@@ -120,8 +122,23 @@
 	cert.validFrom = int64ToDate(sshbuf.readInt64());
 	cert.validUntil = int64ToDate(sshbuf.readInt64());
 
-	cert.signatures.openssh.critical = sshbuf.readBuffer();
-	cert.signatures.openssh.exts = sshbuf.readBuffer();
+	var exts = [];
+	var extbuf = new SSHBuffer({ buffer: sshbuf.readBuffer() });
+	var ext;
+	while (!extbuf.atEnd()) {
+		ext = { critical: true };
+		ext.name = extbuf.readString();
+		ext.data = extbuf.readBuffer();
+		exts.push(ext);
+	}
+	extbuf = new SSHBuffer({ buffer: sshbuf.readBuffer() });
+	while (!extbuf.atEnd()) {
+		ext = { critical: false };
+		ext.name = extbuf.readString();
+		ext.data = extbuf.readBuffer();
+		exts.push(ext);
+	}
+	cert.signatures.openssh.exts = exts;
 
 	/* reserved */
 	sshbuf.readBuffer();
@@ -163,7 +180,7 @@
 	var i = Math.round(date.getTime() / 1000);
 	var upper = Math.floor(i / 4294967296);
 	var lower = Math.floor(i % 4294967296);
-	var buf = new Buffer(8);
+	var buf = Buffer.alloc(8);
 	buf.writeUInt32BE(upper, 0);
 	buf.writeUInt32BE(lower, 4);
 	return (buf);
@@ -188,6 +205,38 @@
 	return (true);
 }
 
+function signAsync(cert, signer, done) {
+	if (cert.signatures.openssh === undefined)
+		cert.signatures.openssh = {};
+	try {
+		var blob = toBuffer(cert, true);
+	} catch (e) {
+		delete (cert.signatures.openssh);
+		done(e);
+		return;
+	}
+	var sig = cert.signatures.openssh;
+
+	signer(blob, function (err, signature) {
+		if (err) {
+			done(err);
+			return;
+		}
+		try {
+			/*
+			 * This will throw if the signature isn't of a
+			 * type/algo that can be used for SSH.
+			 */
+			signature.toBuffer('ssh');
+		} catch (e) {
+			done(e);
+			return;
+		}
+		sig.signature = signature;
+		done();
+	});
+}
+
 function write(cert, options) {
 	if (options === undefined)
 		options = {};
@@ -244,16 +293,30 @@
 	buf.writeInt64(dateToInt64(cert.validFrom));
 	buf.writeInt64(dateToInt64(cert.validUntil));
 
-	if (sig.critical === undefined)
-		sig.critical = new Buffer(0);
-	buf.writeBuffer(sig.critical);
-
-	if (sig.exts === undefined)
-		sig.exts = new Buffer(0);
-	buf.writeBuffer(sig.exts);
+	var exts = sig.exts;
+	if (exts === undefined)
+		exts = [];
+
+	var extbuf = new SSHBuffer({});
+	exts.forEach(function (ext) {
+		if (ext.critical !== true)
+			return;
+		extbuf.writeString(ext.name);
+		extbuf.writeBuffer(ext.data);
+	});
+	buf.writeBuffer(extbuf.toBuffer());
+
+	extbuf = new SSHBuffer({});
+	exts.forEach(function (ext) {
+		if (ext.critical === true)
+			return;
+		extbuf.writeString(ext.name);
+		extbuf.writeBuffer(ext.data);
+	});
+	buf.writeBuffer(extbuf.toBuffer());
 
 	/* reserved */
-	buf.writeBuffer(new Buffer(0));
+	buf.writeBuffer(Buffer.alloc(0));
 
 	sub = rfc4253.write(cert.issuerKey);
 	buf.writeBuffer(sub);
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/pem.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/pem.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/pem.js	(working copy)
@@ -1,4 +1,4 @@
-// Copyright 2015 Joyent, Inc.
+// Copyright 2018 Joyent, Inc.
 
 module.exports = {
 	read: read,
@@ -8,6 +8,7 @@
 var assert = require('assert-plus');
 var asn1 = require('asn1');
 var crypto = require('crypto');
+var Buffer = require('safer-buffer').Buffer;
 var algs = require('../algs');
 var utils = require('../utils');
 var Key = require('../key');
@@ -20,6 +21,29 @@
 
 var errors = require('../errors');
 
+var OID_PBES2 = '1.2.840.113549.1.5.13';
+var OID_PBKDF2 = '1.2.840.113549.1.5.12';
+
+var OID_TO_CIPHER = {
+	'1.2.840.113549.3.7': '3des-cbc',
+	'2.16.840.1.101.3.4.1.2': 'aes128-cbc',
+	'2.16.840.1.101.3.4.1.42': 'aes256-cbc'
+};
+var CIPHER_TO_OID = {};
+Object.keys(OID_TO_CIPHER).forEach(function (k) {
+	CIPHER_TO_OID[OID_TO_CIPHER[k]] = k;
+});
+
+var OID_TO_HASH = {
+	'1.2.840.113549.2.7': 'sha1',
+	'1.2.840.113549.2.9': 'sha256',
+	'1.2.840.113549.2.11': 'sha512'
+};
+var HASH_TO_OID = {};
+Object.keys(OID_TO_HASH).forEach(function (k) {
+	HASH_TO_OID[OID_TO_HASH[k]] = k;
+});
+
 /*
  * For reading we support both PKCS#1 and PKCS#8. If we find a private key,
  * we just take the public component of it and use that.
@@ -31,14 +55,22 @@
 		buf = buf.toString('ascii');
 	}
 
-	var lines = buf.trim().split('\n');
+	var lines = buf.trim().split(/[\r\n]+/g);
 
-	var m = lines[0].match(/*JSSTYLED*/
-	    /[-]+[ ]*BEGIN ([A-Z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
+	var m;
+	var si = -1;
+	while (!m && si < lines.length) {
+		m = lines[++si].match(/*JSSTYLED*/
+		    /[-]+[ ]*BEGIN ([A-Z0-9][A-Za-z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
+	}
 	assert.ok(m, 'invalid PEM header');
 
-	var m2 = lines[lines.length - 1].match(/*JSSTYLED*/
-	    /[-]+[ ]*END ([A-Z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
+	var m2;
+	var ei = lines.length;
+	while (!m2 && ei > 0) {
+		m2 = lines[--ei].match(/*JSSTYLED*/
+		    /[-]+[ ]*END ([A-Z0-9][A-Za-z0-9]+ )?(PUBLIC|PRIVATE) KEY[ ]*[-]+/);
+	}
 	assert.ok(m2, 'invalid PEM footer');
 
 	/* Begin and end banners must match key type */
@@ -52,6 +84,8 @@
 		alg = m[1].trim();
 	}
 
+	lines = lines.slice(si, ei + 1);
+
 	var headers = {};
 	while (true) {
 		lines = lines.slice(1);
@@ -62,12 +96,16 @@
 		headers[m[1].toLowerCase()] = m[2];
 	}
 
+	/* Chop off the first and last lines */
+	lines = lines.slice(0, -1).join('');
+	buf = Buffer.from(lines, 'base64');
+
 	var cipher, key, iv;
 	if (headers['proc-type']) {
 		var parts = headers['proc-type'].split(',');
 		if (parts[0] === '4' && parts[1] === 'ENCRYPTED') {
 			if (typeof (options.passphrase) === 'string') {
-				options.passphrase = new Buffer(
+				options.passphrase = Buffer.from(
 				    options.passphrase, 'utf-8');
 			}
 			if (!Buffer.isBuffer(options.passphrase)) {
@@ -77,16 +115,77 @@
 				parts = headers['dek-info'].split(',');
 				assert.ok(parts.length === 2);
 				cipher = parts[0].toLowerCase();
-				iv = new Buffer(parts[1], 'hex');
+				iv = Buffer.from(parts[1], 'hex');
 				key = utils.opensslKeyDeriv(cipher, iv,
 				    options.passphrase, 1).key;
 			}
 		}
 	}
 
-	/* Chop off the first and last lines */
-	lines = lines.slice(0, -1).join('');
-	buf = new Buffer(lines, 'base64');
+	if (alg && alg.toLowerCase() === 'encrypted') {
+		var eder = new asn1.BerReader(buf);
+		var pbesEnd;
+		eder.readSequence();
+
+		eder.readSequence();
+		pbesEnd = eder.offset + eder.length;
+
+		var method = eder.readOID();
+		if (method !== OID_PBES2) {
+			throw (new Error('Unsupported PEM/PKCS8 encryption ' +
+			    'scheme: ' + method));
+		}
+
+		eder.readSequence();	/* PBES2-params */
+
+		eder.readSequence();	/* keyDerivationFunc */
+		var kdfEnd = eder.offset + eder.length;
+		var kdfOid = eder.readOID();
+		if (kdfOid !== OID_PBKDF2)
+			throw (new Error('Unsupported PBES2 KDF: ' + kdfOid));
+		eder.readSequence();
+		var salt = eder.readString(asn1.Ber.OctetString, true);
+		var iterations = eder.readInt();
+		var hashAlg = 'sha1';
+		if (eder.offset < kdfEnd) {
+			eder.readSequence();
+			var hashAlgOid = eder.readOID();
+			hashAlg = OID_TO_HASH[hashAlgOid];
+			if (hashAlg === undefined) {
+				throw (new Error('Unsupported PBKDF2 hash: ' +
+				    hashAlgOid));
+			}
+		}
+		eder._offset = kdfEnd;
+
+		eder.readSequence();	/* encryptionScheme */
+		var cipherOid = eder.readOID();
+		cipher = OID_TO_CIPHER[cipherOid];
+		if (cipher === undefined) {
+			throw (new Error('Unsupported PBES2 cipher: ' +
+			    cipherOid));
+		}
+		iv = eder.readString(asn1.Ber.OctetString, true);
+
+		eder._offset = pbesEnd;
+		buf = eder.readString(asn1.Ber.OctetString, true);
+
+		if (typeof (options.passphrase) === 'string') {
+			options.passphrase = Buffer.from(
+			    options.passphrase, 'utf-8');
+		}
+		if (!Buffer.isBuffer(options.passphrase)) {
+			throw (new errors.KeyEncryptedError(
+			    options.filename, 'PEM'));
+		}
+
+		var cinfo = utils.opensshCipherInfo(cipher);
+
+		cipher = cinfo.opensslName;
+		key = utils.pbkdf2(hashAlg, salt, iterations, cinfo.keySize,
+		    options.passphrase);
+		alg = undefined;
+	}
 
 	if (cipher && key && iv) {
 		var cipherStream = crypto.createDecipheriv(cipher, key, iv);
@@ -135,7 +234,12 @@
 function write(key, options, type) {
 	assert.object(key);
 
-	var alg = {'ecdsa': 'EC', 'rsa': 'RSA', 'dsa': 'DSA'}[key.type];
+	var alg = {
+	    'ecdsa': 'EC',
+	    'rsa': 'RSA',
+	    'dsa': 'DSA',
+	    'ed25519': 'EdDSA'
+	}[key.type];
 	var header;
 
 	var der = new asn1.BerWriter();
@@ -169,7 +273,7 @@
 	var tmp = der.buffer.toString('base64');
 	var len = tmp.length + (tmp.length / 64) +
 	    18 + 16 + header.length*2 + 10;
-	var buf = new Buffer(len);
+	var buf = Buffer.alloc(len);
 	var o = 0;
 	o += buf.write('-----BEGIN ' + header + '-----\n', o);
 	for (var i = 0; i < tmp.length; ) {
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/pkcs1.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/pkcs1.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/pkcs1.js	(working copy)
@@ -9,6 +9,7 @@
 
 var assert = require('assert-plus');
 var asn1 = require('asn1');
+var Buffer = require('safer-buffer').Buffer;
 var algs = require('../algs');
 var utils = require('../utils');
 
@@ -55,6 +56,11 @@
 		else if (type === 'public')
 			return (readPkcs1ECDSAPublic(der));
 		throw (new Error('Unknown key type: ' + type));
+	case 'EDDSA':
+	case 'EdDSA':
+		if (type === 'private')
+			return (readPkcs1EdDSAPrivate(der));
+		throw (new Error(type + ' keys not supported with EdDSA'));
 	default:
 		throw (new Error('Unknown key algo: ' + alg));
 	}
@@ -134,6 +140,31 @@
 	return (new PrivateKey(key));
 }
 
+function readPkcs1EdDSAPrivate(der) {
+	var version = readMPInt(der, 'version');
+	assert.strictEqual(version.readUInt8(0), 1);
+
+	// private key
+	var k = der.readString(asn1.Ber.OctetString, true);
+
+	der.readSequence(0xa0);
+	var oid = der.readOID();
+	assert.strictEqual(oid, '1.3.101.112', 'the ed25519 curve identifier');
+
+	der.readSequence(0xa1);
+	var A = utils.readBitString(der);
+
+	var key = {
+		type: 'ed25519',
+		parts: [
+			{ name: 'A', data: utils.zeroPadToLength(A, 32) },
+			{ name: 'k', data: k }
+		]
+	};
+
+	return (new PrivateKey(key));
+}
+
 function readPkcs1DSAPublic(der) {
 	var y = readMPInt(der, 'y');
 	var p = readMPInt(der, 'p');
@@ -179,7 +210,7 @@
 	var key = {
 		type: 'ecdsa',
 		parts: [
-			{ name: 'curve', data: new Buffer(curve) },
+			{ name: 'curve', data: Buffer.from(curve) },
 			{ name: 'Q', data: Q }
 		]
 	};
@@ -205,7 +236,7 @@
 	var key = {
 		type: 'ecdsa',
 		parts: [
-			{ name: 'curve', data: new Buffer(curve) },
+			{ name: 'curve', data: Buffer.from(curve) },
 			{ name: 'Q', data: Q },
 			{ name: 'd', data: d }
 		]
@@ -236,6 +267,12 @@
 		else
 			writePkcs1ECDSAPublic(der, key);
 		break;
+	case 'ed25519':
+		if (PrivateKey.isPrivateKey(key))
+			writePkcs1EdDSAPrivate(der, key);
+		else
+			writePkcs1EdDSAPublic(der, key);
+		break;
 	default:
 		throw (new Error('Unknown key algo: ' + key.type));
 	}
@@ -249,8 +286,7 @@
 }
 
 function writePkcs1RSAPrivate(der, key) {
-	var ver = new Buffer(1);
-	ver[0] = 0;
+	var ver = Buffer.from([0]);
 	der.writeBuffer(ver, asn1.Ber.Integer);
 
 	der.writeBuffer(key.part.n.data, asn1.Ber.Integer);
@@ -266,8 +302,7 @@
 }
 
 function writePkcs1DSAPrivate(der, key) {
-	var ver = new Buffer(1);
-	ver[0] = 0;
+	var ver = Buffer.from([0]);
 	der.writeBuffer(ver, asn1.Ber.Integer);
 
 	der.writeBuffer(key.part.p.data, asn1.Ber.Integer);
@@ -300,8 +335,7 @@
 }
 
 function writePkcs1ECDSAPrivate(der, key) {
-	var ver = new Buffer(1);
-	ver[0] = 1;
+	var ver = Buffer.from([1]);
 	der.writeBuffer(ver, asn1.Ber.Integer);
 
 	der.writeBuffer(key.part.d.data, asn1.Ber.OctetString);
@@ -318,3 +352,22 @@
 	der.writeBuffer(Q, asn1.Ber.BitString);
 	der.endSequence();
 }
+
+function writePkcs1EdDSAPrivate(der, key) {
+	var ver = Buffer.from([1]);
+	der.writeBuffer(ver, asn1.Ber.Integer);
+
+	der.writeBuffer(key.part.k.data, asn1.Ber.OctetString);
+
+	der.startSequence(0xa0);
+	der.writeOID('1.3.101.112');
+	der.endSequence();
+
+	der.startSequence(0xa1);
+	utils.writeBitString(der, key.part.A.data);
+	der.endSequence();
+}
+
+function writePkcs1EdDSAPublic(der, key) {
+	throw (new Error('Public keys are not supported for EdDSA PKCS#1'));
+}
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/pkcs8.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/pkcs8.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/pkcs8.js	(working copy)
@@ -1,10 +1,11 @@
-// Copyright 2015 Joyent, Inc.
+// Copyright 2018 Joyent, Inc.
 
 module.exports = {
 	read: read,
 	readPkcs8: readPkcs8,
 	write: write,
 	writePkcs8: writePkcs8,
+	pkcs8ToBuffer: pkcs8ToBuffer,
 
 	readECDSACurve: readECDSACurve,
 	writeECDSACurve: writeECDSACurve
@@ -12,6 +13,7 @@
 
 var assert = require('assert-plus');
 var asn1 = require('asn1');
+var Buffer = require('safer-buffer').Buffer;
 var algs = require('../algs');
 var utils = require('../utils');
 var Key = require('../key');
@@ -62,6 +64,18 @@
 			return (readPkcs8ECDSAPublic(der));
 		else
 			return (readPkcs8ECDSAPrivate(der));
+	case '1.3.101.112':
+		if (type === 'public') {
+			return (readPkcs8EdDSAPublic(der));
+		} else {
+			return (readPkcs8EdDSAPrivate(der));
+		}
+	case '1.3.101.110':
+		if (type === 'public') {
+			return (readPkcs8X25519Public(der));
+		} else {
+			return (readPkcs8X25519Private(der));
+		}
 	default:
 		throw (new Error('Unknown key type OID ' + oid));
 	}
@@ -287,15 +301,27 @@
 	assert.equal(version[0], 1, 'unknown version of ECDSA key');
 
 	var d = der.readString(asn1.Ber.OctetString, true);
-	der.readSequence(0xa1);
+	var Q;
 
-	var Q = der.readString(asn1.Ber.BitString, true);
-	Q = utils.ecNormalize(Q);
+	if (der.peek() == 0xa0) {
+		der.readSequence(0xa0);
+		der._offset += der.length;
+	}
+	if (der.peek() == 0xa1) {
+		der.readSequence(0xa1);
+		Q = der.readString(asn1.Ber.BitString, true);
+		Q = utils.ecNormalize(Q);
+	}
+
+	if (Q === undefined) {
+		var pub = utils.publicFromPrivateECDSA(curveName, d);
+		Q = pub.part.Q.data;
+	}
 
 	var key = {
 		type: 'ecdsa',
 		parts: [
-			{ name: 'curve', data: new Buffer(curveName) },
+			{ name: 'curve', data: Buffer.from(curveName) },
 			{ name: 'Q', data: Q },
 			{ name: 'd', data: d }
 		]
@@ -314,7 +340,7 @@
 	var key = {
 		type: 'ecdsa',
 		parts: [
-			{ name: 'curve', data: new Buffer(curveName) },
+			{ name: 'curve', data: Buffer.from(curveName) },
 			{ name: 'Q', data: Q }
 		]
 	};
@@ -322,13 +348,102 @@
 	return (new Key(key));
 }
 
+function readPkcs8EdDSAPublic(der) {
+	if (der.peek() === 0x00)
+		der.readByte();
+
+	var A = utils.readBitString(der);
+
+	var key = {
+		type: 'ed25519',
+		parts: [
+			{ name: 'A', data: utils.zeroPadToLength(A, 32) }
+		]
+	};
+
+	return (new Key(key));
+}
+
+function readPkcs8X25519Public(der) {
+	var A = utils.readBitString(der);
+
+	var key = {
+		type: 'curve25519',
+		parts: [
+			{ name: 'A', data: utils.zeroPadToLength(A, 32) }
+		]
+	};
+
+	return (new Key(key));
+}
+
+function readPkcs8EdDSAPrivate(der) {
+	if (der.peek() === 0x00)
+		der.readByte();
+
+	der.readSequence(asn1.Ber.OctetString);
+	var k = der.readString(asn1.Ber.OctetString, true);
+	k = utils.zeroPadToLength(k, 32);
+
+	var A, tag;
+	while ((tag = der.peek()) !== null) {
+		if (tag === (asn1.Ber.Context | 1)) {
+			A = utils.readBitString(der, tag);
+		} else {
+			der.readSequence(tag);
+			der._offset += der.length;
+		}
+	}
+	if (A === undefined)
+		A = utils.calculateED25519Public(k);
+
+	var key = {
+		type: 'ed25519',
+		parts: [
+			{ name: 'A', data: utils.zeroPadToLength(A, 32) },
+			{ name: 'k', data: utils.zeroPadToLength(k, 32) }
+		]
+	};
+
+	return (new PrivateKey(key));
+}
+
+function readPkcs8X25519Private(der) {
+	if (der.peek() === 0x00)
+		der.readByte();
+
+	der.readSequence(asn1.Ber.OctetString);
+	var k = der.readString(asn1.Ber.OctetString, true);
+	k = utils.zeroPadToLength(k, 32);
+
+	var A = utils.calculateX25519Public(k);
+
+	var key = {
+		type: 'curve25519',
+		parts: [
+			{ name: 'A', data: utils.zeroPadToLength(A, 32) },
+			{ name: 'k', data: utils.zeroPadToLength(k, 32) }
+		]
+	};
+
+	return (new PrivateKey(key));
+}
+
+function pkcs8ToBuffer(key) {
+	var der = new asn1.BerWriter();
+	writePkcs8(der, key);
+	return (der.buffer);
+}
+
 function writePkcs8(der, key) {
 	der.startSequence();
 
 	if (PrivateKey.isPrivateKey(key)) {
-		var sillyInt = new Buffer(1);
-		sillyInt[0] = 0x0;
-		der.writeBuffer(sillyInt, asn1.Ber.Integer);
+		var version = 0;
+		if (key.type === 'ed25519')
+			version = 1;
+		var vbuf = Buffer.from([version]);
+		der.writeBuffer(vbuf, asn1.Ber.Integer);
 	}
 
 	der.startSequence();
@@ -354,6 +469,13 @@
 		else
 			writePkcs8ECDSAPublic(key, der);
 		break;
+	case 'ed25519':
+		der.writeOID('1.3.101.112');
+		if (PrivateKey.isPrivateKey(key))
+			writePkcs8EdDSAPrivate(key, der);
+		else
+			writePkcs8EdDSAPublic(key, der);
+		break;
 	default:
 		throw (new Error('Unsupported key type: ' + key.type));
 	}
@@ -368,8 +490,7 @@
 	der.startSequence(asn1.Ber.OctetString);
 	der.startSequence();
 
-	var version = new Buffer(1);
-	version[0] = 0;
+	var version = Buffer.from([0]);
 	der.writeBuffer(version, asn1.Ber.Integer);
 
 	der.writeBuffer(key.part.n.data, asn1.Ber.Integer);
@@ -440,8 +561,7 @@
 		// ECParameters sequence
 		der.startSequence();
 
-		var version = new Buffer(1);
-		version.writeUInt8(1, 0);
+		var version = Buffer.from([1]);
 		der.writeBuffer(version, asn1.Ber.Integer);
 
 		// FieldID sequence
@@ -464,8 +584,7 @@
 		der.writeBuffer(curve.n, asn1.Ber.Integer);
 		var h = curve.h;
 		if (!h) {
-			h = new Buffer(1);
-			h[0] = 1;
+			h = Buffer.from([1]);
 		}
 		der.writeBuffer(h, asn1.Ber.Integer);
 
@@ -489,8 +608,7 @@
 	der.startSequence(asn1.Ber.OctetString);
 	der.startSequence();
 
-	var version = new Buffer(1);
-	version[0] = 1;
+	var version = Buffer.from([1]);
 	der.writeBuffer(version, asn1.Ber.Integer);
 
 	der.writeBuffer(key.part.d.data, asn1.Ber.OctetString);
@@ -503,3 +621,23 @@
 	der.endSequence();
 	der.endSequence();
 }
+
+function writePkcs8EdDSAPublic(key, der) {
+	der.endSequence();
+
+	utils.writeBitString(der, key.part.A.data);
+}
+
+function writePkcs8EdDSAPrivate(key, der) {
+	der.endSequence();
+
+	der.startSequence(asn1.Ber.OctetString);
+	var k = utils.mpNormalize(key.part.k.data);
+	/* RFCs call for storing exactly 32 bytes, so strip any leading zeros */
+	while (k.length > 32 && k[0] === 0x00)
+		k = k.slice(1);
+	der.writeBuffer(k, asn1.Ber.OctetString);
+	der.endSequence();
+
+	utils.writeBitString(der, key.part.A.data, asn1.Ber.Context | 1);
+}
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/rfc4253.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/rfc4253.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/rfc4253.js	(working copy)
@@ -14,6 +14,7 @@
 };
 
 var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
 var algs = require('../algs');
 var utils = require('../utils');
 var Key = require('../key');
@@ -54,7 +55,7 @@
 
 function read(partial, type, buf, options) {
 	if (typeof (buf) === 'string')
-		buf = new Buffer(buf);
+		buf = Buffer.from(buf);
 	assert.buffer(buf, 'buf');
 
 	var key = {};
@@ -97,12 +98,25 @@
 
 	var normalized = true;
 	for (var i = 0; i < algInfo.parts.length; ++i) {
-		parts[i].name = algInfo.parts[i];
-		if (parts[i].name !== 'curve' &&
-		    algInfo.normalize !== false) {
-			var p = parts[i];
-			var nd = utils.mpNormalize(p.data);
-			if (nd !== p.data) {
+		var p = parts[i];
+		p.name = algInfo.parts[i];
+		/*
+		 * OpenSSH stores ed25519 "private" keys as seed + public key
+		 * concat'd together (k followed by A). We want to keep them
+		 * separate for other formats that don't do this.
+		 */
+		if (key.type === 'ed25519' && p.name === 'k')
+			p.data = p.data.slice(0, 32);
+
+		if (p.name !== 'curve' && algInfo.normalize !== false) {
+			var nd;
+			if (key.type === 'ed25519') {
+				nd = utils.zeroPadToLength(p.data, 32);
+			} else {
+				nd = utils.mpNormalize(p.data);
+			}
+			if (nd.toString('binary') !==
+			    p.data.toString('binary')) {
 				p.data = nd;
 				normalized = false;
 			}
@@ -137,8 +151,14 @@
 
 	for (i = 0; i < parts.length; ++i) {
 		var data = key.part[parts[i]].data;
-		if (algInfo.normalize !== false)
-			data = utils.mpNormalize(data);
+		if (algInfo.normalize !== false) {
+			if (key.type === 'ed25519')
+				data = utils.zeroPadToLength(data, 32);
+			else
+				data = utils.mpNormalize(data);
+		}
+		if (key.type === 'ed25519' && parts[i] === 'k')
+			data = Buffer.concat([data, key.part.A.data]);
 		buf.writeBuffer(data);
 	}
 
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/ssh-private.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/ssh-private.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/ssh-private.js	(working copy)
@@ -8,6 +8,7 @@
 
 var assert = require('assert-plus');
 var asn1 = require('asn1');
+var Buffer = require('safer-buffer').Buffer;
 var algs = require('../algs');
 var utils = require('../utils');
 var crypto = require('crypto');
@@ -70,7 +71,7 @@
 		}
 
 		if (typeof (options.passphrase) === 'string') {
-			options.passphrase = new Buffer(options.passphrase,
+			options.passphrase = Buffer.from(options.passphrase,
 			    'utf-8');
 		}
 		if (!Buffer.isBuffer(options.passphrase)) {
@@ -88,7 +89,7 @@
 			throw (new Error('bcrypt_pbkdf function returned ' +
 			    'failure, parameters invalid'));
 		}
-		out = new Buffer(out);
+		out = Buffer.from(out);
 		var ckey = out.slice(0, cinf.keySize);
 		var iv = out.slice(cinf.keySize, cinf.keySize + cinf.blockSize);
 		var cipherStream = crypto.createDecipheriv(cinf.opensslName,
@@ -142,13 +143,13 @@
 
 	var cipher = 'none';
 	var kdf = 'none';
-	var kdfopts = new Buffer(0);
+	var kdfopts = Buffer.alloc(0);
 	var cinf = { blockSize: 8 };
 	var passphrase;
 	if (options !== undefined) {
 		passphrase = options.passphrase;
 		if (typeof (passphrase) === 'string')
-			passphrase = new Buffer(passphrase, 'utf-8');
+			passphrase = Buffer.from(passphrase, 'utf-8');
 		if (passphrase !== undefined) {
 			assert.buffer(passphrase, 'options.passphrase');
 			assert.optionalString(options.cipher, 'options.cipher');
@@ -199,7 +200,7 @@
 			throw (new Error('bcrypt_pbkdf function returned ' +
 			    'failure, parameters invalid'));
 		}
-		out = new Buffer(out);
+		out = Buffer.from(out);
 		var ckey = out.slice(0, cinf.keySize);
 		var iv = out.slice(cinf.keySize, cinf.keySize + cinf.blockSize);
 
@@ -244,7 +245,7 @@
 	var tmp = buf.toString('base64');
 	var len = tmp.length + (tmp.length / 70) +
 	    18 + 16 + header.length*2 + 10;
-	buf = new Buffer(len);
+	buf = Buffer.alloc(len);
 	var o = 0;
 	o += buf.write('-----BEGIN ' + header + '-----\n', o);
 	for (var i = 0; i < tmp.length; ) {
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/ssh.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/ssh.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/ssh.js	(working copy)
@@ -6,6 +6,7 @@
 };
 
 var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
 var rfc4253 = require('./rfc4253');
 var utils = require('../utils');
 var Key = require('../key');
@@ -14,9 +15,9 @@
 var sshpriv = require('./ssh-private');
 
 /*JSSTYLED*/
-var SSHKEY_RE = /^([a-z0-9-]+)[ \t]+([a-zA-Z0-9+\/]+[=]*)([\n \t]+([^\n]+))?$/;
+var SSHKEY_RE = /^([a-z0-9-]+)[ \t]+([a-zA-Z0-9+\/]+[=]*)([ \t]+([^ \t][^\n]*[\n]*)?)?$/;
 /*JSSTYLED*/
-var SSHKEY_RE2 = /^([a-z0-9-]+)[ \t]+([a-zA-Z0-9+\/ \t\n]+[=]*)(.*)$/;
+var SSHKEY_RE2 = /^([a-z0-9-]+)[ \t\n]+([a-zA-Z0-9+\/][a-zA-Z0-9+\/ \t\n=]*)([^a-zA-Z0-9+\/ \t\n=].*)?$/;
 
 function read(buf, options) {
 	if (typeof (buf) !== 'string') {
@@ -31,7 +32,7 @@
 	assert.ok(m, 'key must match regex');
 
 	var type = rfc4253.algToKeyType(m[1]);
-	var kbuf = new Buffer(m[2], 'base64');
+	var kbuf = Buffer.from(m[2], 'base64');
 
 	/*
 	 * This is a bit tricky. If we managed to parse the key and locate the
@@ -50,7 +51,7 @@
 		} catch (e) {
 			m = trimmed.match(SSHKEY_RE2);
 			assert.ok(m, 'key must match regex');
-			kbuf = new Buffer(m[2], 'base64');
+			kbuf = Buffer.from(m[2], 'base64');
 			key = rfc4253.readInternal(ret, 'public', kbuf);
 		}
 	} else {
@@ -71,7 +72,7 @@
 		 * chars from the beginning up to this point in the the string.
 		 * Then offset in this and try to make up for missing = chars.
 		 */
-		var data = m[2] + m[3];
+		var data = m[2] + (m[3] ? m[3] : '');
 		var realOffset = Math.ceil(ret.consumed / 3) * 4;
 		data = data.slice(0, realOffset - 2). /*JSSTYLED*/
 		    replace(/[^a-zA-Z0-9+\/=]/g, '') +
@@ -110,5 +111,5 @@
 	if (key.comment)
 		parts.push(key.comment);
 
-	return (new Buffer(parts.join(' ')));
+	return (Buffer.from(parts.join(' ')));
 }
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/x509-pem.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/x509-pem.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/x509-pem.js	(working copy)
@@ -11,6 +11,7 @@
 
 var assert = require('assert-plus');
 var asn1 = require('asn1');
+var Buffer = require('safer-buffer').Buffer;
 var algs = require('../algs');
 var utils = require('../utils');
 var Key = require('../key');
@@ -28,14 +29,24 @@
 
 	var lines = buf.trim().split(/[\r\n]+/g);
 
-	var m = lines[0].match(/*JSSTYLED*/
-	    /[-]+[ ]*BEGIN CERTIFICATE[ ]*[-]+/);
+	var m;
+	var si = -1;
+	while (!m && si < lines.length) {
+		m = lines[++si].match(/*JSSTYLED*/
+		    /[-]+[ ]*BEGIN CERTIFICATE[ ]*[-]+/);
+	}
 	assert.ok(m, 'invalid PEM header');
 
-	var m2 = lines[lines.length - 1].match(/*JSSTYLED*/
-	    /[-]+[ ]*END CERTIFICATE[ ]*[-]+/);
+	var m2;
+	var ei = lines.length;
+	while (!m2 && ei > 0) {
+		m2 = lines[--ei].match(/*JSSTYLED*/
+		    /[-]+[ ]*END CERTIFICATE[ ]*[-]+/);
+	}
 	assert.ok(m2, 'invalid PEM footer');
 
+	lines = lines.slice(si, ei + 1);
+
 	var headers = {};
 	while (true) {
 		lines = lines.slice(1);
@@ -48,7 +59,7 @@
 
 	/* Chop off the first and last lines */
 	lines = lines.slice(0, -1).join('');
-	buf = new Buffer(lines, 'base64');
+	buf = Buffer.from(lines, 'base64');
 
 	return (x509.read(buf, options));
 }
@@ -60,7 +71,7 @@
 	var tmp = dbuf.toString('base64');
 	var len = tmp.length + (tmp.length / 64) +
 	    18 + 16 + header.length*2 + 10;
-	var buf = new Buffer(len);
+	var buf = Buffer.alloc(len);
 	var o = 0;
 	o += buf.write('-----BEGIN ' + header + '-----\n', o);
 	for (var i = 0; i < tmp.length; ) {
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/x509.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/x509.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/formats/x509.js	(working copy)
@@ -1,14 +1,16 @@
-// Copyright 2016 Joyent, Inc.
+// Copyright 2017 Joyent, Inc.
 
 module.exports = {
 	read: read,
 	verify: verify,
 	sign: sign,
+	signAsync: signAsync,
 	write: write
 };
 
 var assert = require('assert-plus');
 var asn1 = require('asn1');
+var Buffer = require('safer-buffer').Buffer;
 var algs = require('../algs');
 var utils = require('../utils');
 var Key = require('../key');
@@ -69,7 +71,8 @@
 	'ecdsa-sha1': '1.2.840.10045.4.1',
 	'ecdsa-sha256': '1.2.840.10045.4.3.2',
 	'ecdsa-sha384': '1.2.840.10045.4.3.3',
-	'ecdsa-sha512': '1.2.840.10045.4.3.4'
+	'ecdsa-sha512': '1.2.840.10045.4.3.4',
+	'ed25519-sha512': '1.3.101.112'
 };
 Object.keys(SIGN_ALGS).forEach(function (k) {
 	SIGN_ALGS[SIGN_ALGS[k]] = k;
@@ -79,12 +82,15 @@
 
 var EXTS = {
 	'issuerKeyId': '2.5.29.35',
-	'altName': '2.5.29.17'
+	'altName': '2.5.29.17',
+	'basicConstraints': '2.5.29.19',
+	'keyUsage': '2.5.29.15',
+	'extKeyUsage': '2.5.29.37'
 };
 
 function read(buf, options) {
 	if (typeof (buf) === 'string') {
-		buf = new Buffer(buf, 'binary');
+		buf = Buffer.from(buf, 'binary');
 	}
 	assert.buffer(buf, 'buf');
 
@@ -197,6 +203,14 @@
 	}
 }
 
+function writeDate(der, date) {
+	if (date.getUTCFullYear() >= 2050 || date.getUTCFullYear() < 1950) {
+		der.writeString(dateToGTime(date), asn1.Ber.GeneralizedTime);
+	} else {
+		der.writeString(dateToUTCTime(date), asn1.Ber.UTCTime);
+	}
+}
+
 /* RFC5280, section 4.2.1.6 (GeneralName type) */
 var ALTNAME = {
 	OtherName: Local(0),
@@ -210,19 +224,115 @@
 	OID: Context(8)
 };
 
+/* RFC5280, section 4.2.1.12 (KeyPurposeId) */
+var EXTPURPOSE = {
+	'serverAuth': '1.3.6.1.5.5.7.3.1',
+	'clientAuth': '1.3.6.1.5.5.7.3.2',
+	'codeSigning': '1.3.6.1.5.5.7.3.3',
+
+	/* See https://github.com/joyent/oid-docs/blob/master/root.md */
+	'joyentDocker': '1.3.6.1.4.1.38678.1.4.1',
+	'joyentCmon': '1.3.6.1.4.1.38678.1.4.2'
+};
+var EXTPURPOSE_REV = {};
+Object.keys(EXTPURPOSE).forEach(function (k) {
+	EXTPURPOSE_REV[EXTPURPOSE[k]] = k;
+});
+
+var KEYUSEBITS = [
+	'signature', 'identity', 'keyEncryption',
+	'encryption', 'keyAgreement', 'ca', 'crl'
+];
+
 function readExtension(cert, buf, der) {
 	der.readSequence();
 	var after = der.offset + der.length;
 	var extId = der.readOID();
 	var id;
 	var sig = cert.signatures.x509;
-	sig.extras.exts = [];
+	if (!sig.extras.exts)
+		sig.extras.exts = [];
 
 	var critical;
 	if (der.peek() === asn1.Ber.Boolean)
 		critical = der.readBoolean();
 
 	switch (extId) {
+	case (EXTS.basicConstraints):
+		der.readSequence(asn1.Ber.OctetString);
+		der.readSequence();
+		var bcEnd = der.offset + der.length;
+		var ca = false;
+		if (der.peek() === asn1.Ber.Boolean)
+			ca = der.readBoolean();
+		if (cert.purposes === undefined)
+			cert.purposes = [];
+		if (ca === true)
+			cert.purposes.push('ca');
+		var bc = { oid: extId, critical: critical };
+		if (der.offset < bcEnd && der.peek() === asn1.Ber.Integer)
+			bc.pathLen = der.readInt();
+		sig.extras.exts.push(bc);
+		break;
+	case (EXTS.extKeyUsage):
+		der.readSequence(asn1.Ber.OctetString);
+		der.readSequence();
+		if (cert.purposes === undefined)
+			cert.purposes = [];
+		var ekEnd = der.offset + der.length;
+		while (der.offset < ekEnd) {
+			var oid = der.readOID();
+			cert.purposes.push(EXTPURPOSE_REV[oid] || oid);
+		}
+		/*
+		 * This is a bit of a hack: in the case where we have a cert
+		 * that's only allowed to do serverAuth or clientAuth (and not
+		 * the other), we want to make sure all our Subjects are of
+		 * the right type. But we already parsed our Subjects and
+		 * decided if they were hosts or users earlier (since it appears
+		 * first in the cert).
+		 *
+		 * So we go through and mutate them into the right kind here if
+		 * it doesn't match. This might not be hugely beneficial, as it
+		 * seems that single-purpose certs are not often seen in the
+		 * wild.
+		 */
+		if (cert.purposes.indexOf('serverAuth') !== -1 &&
+		    cert.purposes.indexOf('clientAuth') === -1) {
+			cert.subjects.forEach(function (ide) {
+				if (ide.type !== 'host') {
+					ide.type = 'host';
+					ide.hostname = ide.uid ||
+					    ide.email ||
+					    ide.components[0].value;
+				}
+			});
+		} else if (cert.purposes.indexOf('clientAuth') !== -1 &&
+		    cert.purposes.indexOf('serverAuth') === -1) {
+			cert.subjects.forEach(function (ide) {
+				if (ide.type !== 'user') {
+					ide.type = 'user';
+					ide.uid = ide.hostname ||
+					    ide.email ||
+					    ide.components[0].value;
+				}
+			});
+		}
+		sig.extras.exts.push({ oid: extId, critical: critical });
+		break;
+	case (EXTS.keyUsage):
+		der.readSequence(asn1.Ber.OctetString);
+		var bits = der.readString(asn1.Ber.BitString, true);
+		var setBits = readBitField(bits, KEYUSEBITS);
+		setBits.forEach(function (bit) {
+			if (cert.purposes === undefined)
+				cert.purposes = [];
+			if (cert.purposes.indexOf(bit) === -1)
+				cert.purposes.push(bit);
+		});
+		sig.extras.exts.push({ oid: extId, critical: critical,
+		    bits: bits });
+		break;
 	case (EXTS.altName):
 		der.readSequence(asn1.Ber.OctetString);
 		der.readSequence();
@@ -313,9 +423,11 @@
 	return (d);
 }
 
-function zeroPad(n) {
+function zeroPad(n, m) {
+	if (m === undefined)
+		m = 2;
 	var s = '' + n;
-	while (s.length < 2)
+	while (s.length < m)
 		s = '0' + s;
 	return (s);
 }
@@ -332,6 +444,18 @@
 	return (s);
 }
 
+function dateToGTime(d) {
+	var s = '';
+	s += zeroPad(d.getUTCFullYear(), 4);
+	s += zeroPad(d.getUTCMonth() + 1);
+	s += zeroPad(d.getUTCDate());
+	s += zeroPad(d.getUTCHours());
+	s += zeroPad(d.getUTCMinutes());
+	s += zeroPad(d.getUTCSeconds());
+	s += 'Z';
+	return (s);
+}
+
 function sign(cert, key) {
 	if (cert.signatures.x509 === undefined)
 		cert.signatures.x509 = {};
@@ -353,6 +477,32 @@
 	return (true);
 }
 
+function signAsync(cert, signer, done) {
+	if (cert.signatures.x509 === undefined)
+		cert.signatures.x509 = {};
+	var sig = cert.signatures.x509;
+
+	var der = new asn1.BerWriter();
+	writeTBSCert(cert, der);
+	var blob = der.buffer;
+	sig.cache = blob;
+
+	signer(blob, function (err, signature) {
+		if (err) {
+			done(err);
+			return;
+		}
+		sig.algo = signature.type + '-' + signature.hashAlgorithm;
+		if (SIGN_ALGS[sig.algo] === undefined) {
+			done(new Error('Invalid signing algorithm "' +
+			    sig.algo + '"'));
+			return;
+		}
+		sig.signature = signature;
+		done();
+	});
+}
+
 function write(cert, options) {
 	var sig = cert.signatures.x509;
 	assert.object(sig, 'x509 signature');
@@ -374,7 +524,7 @@
 	der.endSequence();
 
 	var sigData = sig.signature.toBuffer('asn1');
-	var data = new Buffer(sigData.length + 1);
+	var data = Buffer.alloc(sigData.length + 1);
 	data[0] = 0;
 	sigData.copy(data, 1);
 	der.writeBuffer(data, asn1.Ber.BitString);
@@ -397,13 +547,15 @@
 
 	der.startSequence();
 	der.writeOID(SIGN_ALGS[sig.algo]);
+	if (sig.algo.match(/^rsa-/))
+		der.writeNull();
 	der.endSequence();
 
 	cert.issuer.toAsn1(der);
 
 	der.startSequence();
-	der.writeString(dateToUTCTime(cert.validFrom), asn1.Ber.UTCTime);
-	der.writeString(dateToUTCTime(cert.validUntil), asn1.Ber.UTCTime);
+	writeDate(der, cert.validFrom);
+	writeDate(der, cert.validUntil);
 	der.endSequence();
 
 	var subject = cert.subjects[0];
@@ -421,13 +573,27 @@
 	}
 
 	if (altNames.length > 0 || subject.type === 'host' ||
+	    (cert.purposes !== undefined && cert.purposes.length > 0) ||
 	    (sig.extras && sig.extras.exts)) {
 		der.startSequence(Local(3));
 		der.startSequence();
 
-		var exts = [
-			{ oid: EXTS.altName }
-		];
+		var exts = [];
+		if (cert.purposes !== undefined && cert.purposes.length > 0) {
+			exts.push({
+				oid: EXTS.basicConstraints,
+				critical: true
+			});
+			exts.push({
+				oid: EXTS.keyUsage,
+				critical: true
+			});
+			exts.push({
+				oid: EXTS.extKeyUsage,
+				critical: true
+			});
+		}
+		exts.push({ oid: EXTS.altName });
 		if (sig.extras && sig.extras.exts)
 			exts = sig.extras.exts;
 
@@ -468,6 +634,54 @@
 				}
 				der.endSequence();
 				der.endSequence();
+			} else if (exts[i].oid === EXTS.basicConstraints) {
+				der.startSequence(asn1.Ber.OctetString);
+				der.startSequence();
+				var ca = (cert.purposes.indexOf('ca') !== -1);
+				var pathLen = exts[i].pathLen;
+				der.writeBoolean(ca);
+				if (pathLen !== undefined)
+					der.writeInt(pathLen);
+				der.endSequence();
+				der.endSequence();
+			} else if (exts[i].oid === EXTS.extKeyUsage) {
+				der.startSequence(asn1.Ber.OctetString);
+				der.startSequence();
+				cert.purposes.forEach(function (purpose) {
+					if (purpose === 'ca')
+						return;
+					if (KEYUSEBITS.indexOf(purpose) !== -1)
+						return;
+					var oid = purpose;
+					if (EXTPURPOSE[purpose] !== undefined)
+						oid = EXTPURPOSE[purpose];
+					der.writeOID(oid);
+				});
+				der.endSequence();
+				der.endSequence();
+			} else if (exts[i].oid === EXTS.keyUsage) {
+				der.startSequence(asn1.Ber.OctetString);
+				/*
+				 * If we parsed this certificate from a byte
+				 * stream (i.e. we didn't generate it in sshpk)
+				 * then we'll have a ".bits" property on the
+				 * ext with the original raw byte contents.
+				 *
+				 * If we have this, use it here instead of
+				 * regenerating it. This guarantees we output
+				 * the same data we parsed, so signatures still
+				 * validate.
+				 */
+				if (exts[i].bits !== undefined) {
+					der.writeBuffer(exts[i].bits,
+					    asn1.Ber.BitString);
+				} else {
+					var bits = writeBitField(cert.purposes,
+					    KEYUSEBITS);
+					der.writeBuffer(bits,
+					    asn1.Ber.BitString);
+				}
+				der.endSequence();
 			} else {
 				der.writeBuffer(exts[i].data,
 				    asn1.Ber.OctetString);
@@ -482,3 +696,57 @@
 
 	der.endSequence();
 }
+
+/*
+ * Reads an ASN.1 BER bitfield out of the Buffer produced by doing
+ * `BerReader#readString(asn1.Ber.BitString)`. That function gives us the raw
+ * contents of the BitString tag, which is a count of unused bits followed by
+ * the bits as a right-padded byte string.
+ *
+ * `bits` is the Buffer, `bitIndex` should contain an array of string names
+ * for the bits in the string, ordered starting with bit #0 in the ASN.1 spec.
+ *
+ * Returns an array of Strings, the names of the bits that were set to 1.
+ */
+function readBitField(bits, bitIndex) {
+	var bitLen = 8 * (bits.length - 1) - bits[0];
+	var setBits = {};
+	for (var i = 0; i < bitLen; ++i) {
+		var byteN = 1 + Math.floor(i / 8);
+		var bit = 7 - (i % 8);
+		var mask = 1 << bit;
+		var bitVal = ((bits[byteN] & mask) !== 0);
+		var name = bitIndex[i];
+		if (bitVal && typeof (name) === 'string') {
+			setBits[name] = true;
+		}
+	}
+	return (Object.keys(setBits));
+}
+
+/*
+ * `setBits` is an array of strings, containing the names for each bit that
+ * sould be set to 1. `bitIndex` is same as in `readBitField()`.
+ *
+ * Returns a Buffer, ready to be written out with `BerWriter#writeString()`.
+ */
+function writeBitField(setBits, bitIndex) {
+	var bitLen = bitIndex.length;
+	var blen = Math.ceil(bitLen / 8);
+	var unused = blen * 8 - bitLen;
+	var bits = Buffer.alloc(1 + blen); // zero-filled
+	bits[0] = unused;
+	for (var i = 0; i < bitLen; ++i) {
+		var byteN = 1 + Math.floor(i / 8);
+		var bit = 7 - (i % 8);
+		var mask = 1 << bit;
+		var name = bitIndex[i];
+		if (name === undefined)
+			continue;
+		var bitVal = (setBits.indexOf(name) !== -1);
+		if (bitVal) {
+			bits[byteN] |= mask;
+		}
+	}
+	return (bits);
+}
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/identity.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/identity.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/identity.js	(working copy)
@@ -1,4 +1,4 @@
-// Copyright 2016 Joyent, Inc.
+// Copyright 2017 Joyent, Inc.
 
 module.exports = Identity;
 
@@ -11,6 +11,7 @@
 var util = require('util');
 var utils = require('./utils');
 var asn1 = require('asn1');
+var Buffer = require('safer-buffer').Buffer;
 
 /*JSSTYLED*/
 var DNS_NAME_RE = /^([*]|[a-z0-9][a-z0-9\-]{0,62})(?:\.([*]|[a-z0-9][a-z0-9\-]{0,62}))*$/i;
@@ -23,9 +24,21 @@
 oids.s = '2.5.4.8';
 oids.c = '2.5.4.6';
 oids.sn = '2.5.4.4';
+oids.postalCode = '2.5.4.17';
+oids.serialNumber = '2.5.4.5';
+oids.street = '2.5.4.9';
+oids.x500UniqueIdentifier = '2.5.4.45';
+oids.role = '2.5.4.72';
+oids.telephoneNumber = '2.5.4.20';
+oids.description = '2.5.4.13';
 oids.dc = '0.9.2342.19200300.100.1.25';
 oids.uid = '0.9.2342.19200300.100.1.1';
 oids.mail = '0.9.2342.19200300.100.1.3';
+oids.title = '2.5.4.12';
+oids.gn = '2.5.4.42';
+oids.initials = '2.5.4.43';
+oids.pseudonym = '2.5.4.65';
+oids.emailAddress = '1.2.840.113549.1.9.1';
 
 var unoids = {};
 Object.keys(oids).forEach(function (k) {
@@ -112,17 +125,79 @@
 
 Identity.prototype.toString = function () {
 	return (this.components.map(function (c) {
-		return (c.name.toUpperCase() + '=' + c.value);
+		var n = c.name.toUpperCase();
+		/*JSSTYLED*/
+		n = n.replace(/=/g, '\\=');
+		var v = c.value;
+		/*JSSTYLED*/
+		v = v.replace(/,/g, '\\,');
+		return (n + '=' + v);
 	}).join(', '));
 };
 
+Identity.prototype.get = function (name, asArray) {
+	assert.string(name, 'name');
+	var arr = this.componentLookup[name];
+	if (arr === undefined || arr.length === 0)
+		return (undefined);
+	if (!asArray && arr.length > 1)
+		throw (new Error('Multiple values for attribute ' + name));
+	if (!asArray)
+		return (arr[0].value);
+	return (arr.map(function (c) {
+		return (c.value);
+	}));
+};
+
+Identity.prototype.toArray = function (idx) {
+	return (this.components.map(function (c) {
+		return ({
+			name: c.name,
+			value: c.value
+		});
+	}));
+};
+
+/*
+ * These are from X.680 -- PrintableString allowed chars are in section 37.4
+ * table 8. Spec for IA5Strings is "1,6 + SPACE + DEL" where 1 refers to
+ * ISO IR #001 (standard ASCII control characters) and 6 refers to ISO IR #006
+ * (the basic ASCII character set).
+ */
+/* JSSTYLED */
+var NOT_PRINTABLE = /[^a-zA-Z0-9 '(),+.\/:=?-]/;
+/* JSSTYLED */
+var NOT_IA5 = /[^\x00-\x7f]/;
+
 Identity.prototype.toAsn1 = function (der, tag) {
 	der.startSequence(tag);
 	this.components.forEach(function (c) {
 		der.startSequence(asn1.Ber.Constructor | asn1.Ber.Set);
 		der.startSequence();
 		der.writeOID(c.oid);
-		der.writeString(c.value, asn1.Ber.PrintableString);
+		/*
+		 * If we fit in a PrintableString, use that. Otherwise use an
+		 * IA5String or UTF8String.
+		 *
+		 * If this identity was parsed from a DN, use the ASN.1 types
+		 * from the original representation (otherwise this might not
+		 * be a full match for the original in some validators).
+		 */
+		if (c.asn1type === asn1.Ber.Utf8String ||
+		    c.value.match(NOT_IA5)) {
+			var v = Buffer.from(c.value, 'utf8');
+			der.writeBuffer(v, asn1.Ber.Utf8String);
+
+		} else if (c.asn1type === asn1.Ber.IA5String ||
+		    c.value.match(NOT_PRINTABLE)) {
+			der.writeString(c.value, asn1.Ber.IA5String);
+
+		} else {
+			var type = asn1.Ber.PrintableString;
+			if (c.asn1type !== undefined)
+				type = c.asn1type;
+			der.writeString(c.value, type);
+		}
 		der.endSequence();
 		der.endSequence();
 	});
@@ -190,17 +265,60 @@
 
 Identity.parseDN = function (dn) {
 	assert.string(dn, 'dn');
-	var parts = dn.split(',');
+	var parts = [''];
+	var idx = 0;
+	var rem = dn;
+	while (rem.length > 0) {
+		var m;
+		/*JSSTYLED*/
+		if ((m = /^,/.exec(rem)) !== null) {
+			parts[++idx] = '';
+			rem = rem.slice(m[0].length);
+		/*JSSTYLED*/
+		} else if ((m = /^\\,/.exec(rem)) !== null) {
+			parts[idx] += ',';
+			rem = rem.slice(m[0].length);
+		/*JSSTYLED*/
+		} else if ((m = /^\\./.exec(rem)) !== null) {
+			parts[idx] += m[0];
+			rem = rem.slice(m[0].length);
+		/*JSSTYLED*/
+		} else if ((m = /^[^\\,]+/.exec(rem)) !== null) {
+			parts[idx] += m[0];
+			rem = rem.slice(m[0].length);
+		} else {
+			throw (new Error('Failed to parse DN'));
+		}
+	}
 	var cmps = parts.map(function (c) {
 		c = c.trim();
 		var eqPos = c.indexOf('=');
-		var name = c.slice(0, eqPos).toLowerCase();
+		while (eqPos > 0 && c.charAt(eqPos - 1) === '\\')
+			eqPos = c.indexOf('=', eqPos + 1);
+		if (eqPos === -1) {
+			throw (new Error('Failed to parse DN'));
+		}
+		/*JSSTYLED*/
+		var name = c.slice(0, eqPos).toLowerCase().replace(/\\=/g, '=');
 		var value = c.slice(eqPos + 1);
 		return ({ name: name, value: value });
 	});
 	return (new Identity({ components: cmps }));
 };
 
+Identity.fromArray = function (components) {
+	assert.arrayOfObject(components, 'components');
+	components.forEach(function (cmp) {
+		assert.object(cmp, 'component');
+		assert.string(cmp.name, 'component.name');
+		if (!Buffer.isBuffer(cmp.value) &&
+		    !(typeof (cmp.value) === 'string')) {
+			throw (new Error('Invalid component value'));
+		}
+	});
+	return (new Identity({ components: components }));
+};
+
 Identity.parseAsn1 = function (der, top) {
 	var components = [];
 	der.readSequence(top);
@@ -231,7 +349,7 @@
 		default:
 			throw (new Error('Unknown asn1 type ' + type));
 		}
-		components.push({ oid: oid, value: value });
+		components.push({ oid: oid, asn1type: type, value: value });
 		der._offset = after;
 	}
 	der._offset = end;
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/index.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/index.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/index.js	(working copy)
@@ -18,6 +18,7 @@
 	parseSignature: Signature.parse,
 	PrivateKey: PrivateKey,
 	parsePrivateKey: PrivateKey.parse,
+	generatePrivateKey: PrivateKey.generate,
 	Certificate: Certificate,
 	parseCertificate: Certificate.parse,
 	createSelfSignedCertificate: Certificate.createSelfSigned,
@@ -27,6 +28,7 @@
 	identityForHost: Identity.forHost,
 	identityForUser: Identity.forUser,
 	identityForEmail: Identity.forEmail,
+	identityFromArray: Identity.fromArray,
 
 	/* errors */
 	FingerprintFormatError: errs.FingerprintFormatError,
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/key.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/key.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/key.js	(working copy)
@@ -1,4 +1,4 @@
-// Copyright 2015 Joyent, Inc.
+// Copyright 2018 Joyent, Inc.
 
 module.exports = Key;
 
@@ -7,7 +7,7 @@
 var crypto = require('crypto');
 var Fingerprint = require('./fingerprint');
 var Signature = require('./signature');
-var DiffieHellman = require('./dhe');
+var DiffieHellman = require('./dhe').DiffieHellman;
 var errs = require('./errors');
 var utils = require('./utils');
 var PrivateKey = require('./private-key');
@@ -31,6 +31,9 @@
 formats['ssh'] = require('./formats/ssh');
 formats['ssh-private'] = require('./formats/ssh-private');
 formats['openssh'] = formats['ssh-private'];
+formats['dnssec'] = require('./formats/dnssec');
+formats['putty'] = require('./formats/putty');
+formats['ppk'] = formats['putty'];
 
 function Key(opts) {
 	assert.object(opts, 'options');
@@ -64,7 +67,7 @@
 		var curve = this.part.curve.data.toString();
 		this.curve = curve;
 		sz = algs.curves[curve].size;
-	} else if (this.type === 'ed25519') {
+	} else if (this.type === 'ed25519' || this.type === 'curve25519') {
 		sz = 256;
 		this.curve = 'curve25519';
 	} else {
@@ -97,29 +100,44 @@
 	return (this.toBuffer(format, options).toString());
 };
 
-Key.prototype.hash = function (algo) {
+Key.prototype.hash = function (algo, type) {
 	assert.string(algo, 'algorithm');
+	assert.optionalString(type, 'type');
+	if (type === undefined)
+		type = 'ssh';
 	algo = algo.toLowerCase();
 	if (algs.hashAlgs[algo] === undefined)
 		throw (new InvalidAlgorithmError(algo));
 
-	if (this._hashCache[algo])
-		return (this._hashCache[algo]);
-
-	var hash = crypto.createHash(algo).
-	    update(this.toBuffer('rfc4253')).digest();
-	this._hashCache[algo] = hash;
+	var cacheKey = algo + '||' + type;
+	if (this._hashCache[cacheKey])
+		return (this._hashCache[cacheKey]);
+
+	var buf;
+	if (type === 'ssh') {
+		buf = this.toBuffer('rfc4253');
+	} else if (type === 'spki') {
+		buf = formats.pkcs8.pkcs8ToBuffer(this);
+	} else {
+		throw (new Error('Hash type ' + type + ' not supported'));
+	}
+	var hash = crypto.createHash(algo).update(buf).digest();
+	this._hashCache[cacheKey] = hash;
 	return (hash);
 };
 
-Key.prototype.fingerprint = function (algo) {
+Key.prototype.fingerprint = function (algo, type) {
 	if (algo === undefined)
 		algo = 'sha256';
+	if (type === undefined)
+		type = 'ssh';
 	assert.string(algo, 'algorithm');
+	assert.string(type, 'type');
 	var opts = {
 		type: 'key',
-		hash: this.hash(algo),
-		algorithm: algo
+		hash: this.hash(algo, type),
+		algorithm: algo,
+		hashType: type
 	};
 	return (new Fingerprint(opts));
 };
@@ -171,6 +189,7 @@
 	assert.ok(v, 'failed to create verifier');
 	var oldVerify = v.verify.bind(v);
 	var key = this.toBuffer('pkcs8');
+	var curve = this.curve;
 	var self = this;
 	v.verify = function (signature, fmt) {
 		if (Signature.isSignature(signature, [2, 0])) {
@@ -179,6 +198,9 @@
 			if (signature.hashAlgorithm &&
 			    signature.hashAlgorithm !== hashAlgo)
 				return (false);
+			if (signature.curve && self.type === 'ecdsa' &&
+			    signature.curve !== curve)
+				return (false);
 			return (oldVerify(key, signature.toBuffer('asn1')));
 
 		} else if (typeof (signature) === 'string' ||
@@ -252,8 +274,10 @@
  * [1,3] -- added defaultHashAlgorithm
  * [1,4] -- added ed support, createDH
  * [1,5] -- first explicitly tagged version
+ * [1,6] -- changed ed25519 part names
+ * [1,7] -- spki hash types
  */
-Key.prototype._sshpkApiVersion = [1, 5];
+Key.prototype._sshpkApiVersion = [1, 7];
 
 Key._oldVersionDetect = function (obj) {
 	assert.func(obj.toBuffer);
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/private-key.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/private-key.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/private-key.js	(working copy)
@@ -1,8 +1,9 @@
-// Copyright 2015 Joyent, Inc.
+// Copyright 2017 Joyent, Inc.
 
 module.exports = PrivateKey;
 
 var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
 var algs = require('./algs');
 var crypto = require('crypto');
 var Fingerprint = require('./fingerprint');
@@ -10,14 +11,11 @@
 var errs = require('./errors');
 var util = require('util');
 var utils = require('./utils');
-var edCompat;
-var ed;
-
-try {
-	edCompat = require('./ed-compat');
-} catch (e) {
-	/* Just continue through, and bail out if we try to use it. */
-}
+var dhe = require('./dhe');
+var generateECDSA = dhe.generateECDSA;
+var generateED25519 = dhe.generateED25519;
+var edCompat = require('./ed-compat');
+var nacl = require('tweetnacl');
 
 var Key = require('./key');
 
@@ -34,6 +32,8 @@
 formats['ssh-private'] = require('./formats/ssh-private');
 formats['openssh'] = formats['ssh-private'];
 formats['ssh'] = formats['ssh-private'];
+formats['dnssec'] = require('./formats/dnssec');
+formats['putty'] = require('./formats/putty');
 
 function PrivateKey(opts) {
 	assert.object(opts, 'options');
@@ -55,8 +55,12 @@
 	return (formats[format].write(this, options));
 };
 
-PrivateKey.prototype.hash = function (algo) {
-	return (this.toPublic().hash(algo));
+PrivateKey.prototype.hash = function (algo, type) {
+	return (this.toPublic().hash(algo, type));
+};
+
+PrivateKey.prototype.fingerprint = function (algo, type) {
+	return (this.toPublic().fingerprint(algo, type));
 };
 
 PrivateKey.prototype.toPublic = function () {
@@ -80,49 +84,38 @@
 	return (this._pubCache);
 };
 
-PrivateKey.prototype.derive = function (newType, newSize) {
+PrivateKey.prototype.derive = function (newType) {
 	assert.string(newType, 'type');
-	assert.optionalNumber(newSize, 'size');
-	var priv, pub;
+	var priv, pub, pair;
 
 	if (this.type === 'ed25519' && newType === 'curve25519') {
-		if (ed === undefined)
-			ed = require('jodid25519');
-
-		priv = this.part.r.data;
+		priv = this.part.k.data;
 		if (priv[0] === 0x00)
 			priv = priv.slice(1);
-		priv = priv.slice(0, 32);
 
-		pub = ed.dh.publicKey(priv);
-		priv = utils.mpNormalize(Buffer.concat([priv, pub]));
+		pair = nacl.box.keyPair.fromSecretKey(new Uint8Array(priv));
+		pub = Buffer.from(pair.publicKey);
 
 		return (new PrivateKey({
 			type: 'curve25519',
 			parts: [
-				{ name: 'R', data: utils.mpNormalize(pub) },
-				{ name: 'r', data: priv }
+				{ name: 'A', data: utils.mpNormalize(pub) },
+				{ name: 'k', data: utils.mpNormalize(priv) }
 			]
 		}));
 	} else if (this.type === 'curve25519' && newType === 'ed25519') {
-		if (ed === undefined)
-			ed = require('jodid25519');
-
-		priv = this.part.r.data;
+		priv = this.part.k.data;
 		if (priv[0] === 0x00)
 			priv = priv.slice(1);
-		priv = priv.slice(0, 32);
-
-		pub = ed.eddsa.publicKey(priv.toString('binary'));
-		pub = new Buffer(pub, 'binary');
 
-		priv = utils.mpNormalize(Buffer.concat([priv, pub]));
+		pair = nacl.sign.keyPair.fromSeed(new Uint8Array(priv));
+		pub = Buffer.from(pair.publicKey);
 
 		return (new PrivateKey({
 			type: 'ed25519',
 			parts: [
-				{ name: 'R', data: utils.mpNormalize(pub) },
-				{ name: 'r', data: priv }
+				{ name: 'A', data: utils.mpNormalize(pub) },
+				{ name: 'k', data: utils.mpNormalize(priv) }
 			]
 		}));
 	}
@@ -163,12 +156,14 @@
 	var oldSign = v.sign.bind(v);
 	var key = this.toBuffer('pkcs1');
 	var type = this.type;
+	var curve = this.curve;
 	v.sign = function () {
 		var sig = oldSign(key);
 		if (typeof (sig) === 'string')
-			sig = new Buffer(sig, 'binary');
+			sig = Buffer.from(sig, 'binary');
 		sig = Signature.parse(sig, type, 'asn1');
 		sig.hashAlgorithm = hashAlgo;
+		sig.curve = curve;
 		return (sig);
 	};
 	return (v);
@@ -208,6 +203,25 @@
 	return (utils.isCompatible(obj, PrivateKey, ver));
 };
 
+PrivateKey.generate = function (type, options) {
+	if (options === undefined)
+		options = {};
+	assert.object(options, 'options');
+
+	switch (type) {
+	case 'ecdsa':
+		if (options.curve === undefined)
+			options.curve = 'nistp256';
+		assert.string(options.curve, 'options.curve');
+		return (generateECDSA(options.curve));
+	case 'ed25519':
+		return (generateED25519());
+	default:
+		throw (new Error('Key generation not supported with key ' +
+		    'type "' + type + '"'));
+	}
+};
+
 /*
  * API versions for PrivateKey:
  * [1,0] -- initial ver
@@ -215,8 +229,10 @@
  * [1,2] -- added defaultHashAlgorithm
  * [1,3] -- added derive, ed, createDH
  * [1,4] -- first tagged version
+ * [1,5] -- changed ed25519 part names and format
+ * [1,6] -- type arguments for hash() and fingerprint()
  */
-PrivateKey.prototype._sshpkApiVersion = [1, 4];
+PrivateKey.prototype._sshpkApiVersion = [1, 6];
 
 PrivateKey._oldVersionDetect = function (obj) {
 	assert.func(obj.toPublic);
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/signature.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/signature.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/signature.js	(working copy)
@@ -3,6 +3,7 @@
 module.exports = Signature;
 
 var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
 var algs = require('./algs');
 var crypto = require('crypto');
 var errs = require('./errors');
@@ -26,6 +27,7 @@
 
 	this.type = opts.type;
 	this.hashAlgorithm = opts.hashAlgo;
+	this.curve = opts.curve;
 	this.parts = opts.parts;
 	this.part = partLookup;
 }
@@ -36,18 +38,45 @@
 	assert.string(format, 'format');
 
 	var buf;
+	var stype = 'ssh-' + this.type;
 
 	switch (this.type) {
 	case 'rsa':
+		switch (this.hashAlgorithm) {
+		case 'sha256':
+			stype = 'rsa-sha2-256';
+			break;
+		case 'sha512':
+			stype = 'rsa-sha2-512';
+			break;
+		case 'sha1':
+		case undefined:
+			break;
+		default:
+			throw (new Error('SSH signature ' +
+			    'format does not support hash ' +
+			    'algorithm ' + this.hashAlgorithm));
+		}
+		if (format === 'ssh') {
+			buf = new SSHBuffer({});
+			buf.writeString(stype);
+			buf.writePart(this.part.sig);
+			return (buf.toBuffer());
+		} else {
+			return (this.part.sig.data);
+		}
+		break;
+
 	case 'ed25519':
 		if (format === 'ssh') {
 			buf = new SSHBuffer({});
-			buf.writeString('ssh-' + this.type);
+			buf.writeString(stype);
 			buf.writePart(this.part.sig);
 			return (buf.toBuffer());
 		} else {
 			return (this.part.sig.data);
 		}
+		break;
 
 	case 'dsa':
 	case 'ecdsa':
@@ -113,7 +142,7 @@
 
 Signature.parse = function (data, type, format) {
 	if (typeof (data) === 'string')
-		data = new Buffer(data, 'base64');
+		data = Buffer.from(data, 'base64');
 	assert.buffer(data, 'data');
 	assert.string(format, 'format');
 	assert.string(type, 'type');
@@ -126,11 +155,9 @@
 		assert.ok(data.length > 0, 'signature must not be empty');
 		switch (opts.type) {
 		case 'rsa':
-			return (parseOneNum(data, type, format, opts,
-			    'ssh-rsa'));
+			return (parseOneNum(data, type, format, opts));
 		case 'ed25519':
-			return (parseOneNum(data, type, format, opts,
-			    'ssh-ed25519'));
+			return (parseOneNum(data, type, format, opts));
 
 		case 'dsa':
 		case 'ecdsa':
@@ -152,7 +179,7 @@
 	}
 };
 
-function parseOneNum(data, type, format, opts, headType) {
+function parseOneNum(data, type, format, opts) {
 	if (format === 'ssh') {
 		try {
 			var buf = new SSHBuffer({buffer: data});
@@ -160,7 +187,30 @@
 		} catch (e) {
 			/* fall through */
 		}
-		if (head === headType) {
+		if (buf !== undefined) {
+			var msg = 'SSH signature does not match expected ' +
+			    'type (expected ' + type + ', got ' + head + ')';
+			switch (head) {
+			case 'ssh-rsa':
+				assert.strictEqual(type, 'rsa', msg);
+				opts.hashAlgo = 'sha1';
+				break;
+			case 'rsa-sha2-256':
+				assert.strictEqual(type, 'rsa', msg);
+				opts.hashAlgo = 'sha256';
+				break;
+			case 'rsa-sha2-512':
+				assert.strictEqual(type, 'rsa', msg);
+				opts.hashAlgo = 'sha512';
+				break;
+			case 'ssh-ed25519':
+				assert.strictEqual(type, 'ed25519', msg);
+				opts.hashAlgo = 'sha512';
+				break;
+			default:
+				throw (new Error('Unknown SSH signature ' +
+				    'type: ' + head));
+			}
 			var sig = buf.readPart();
 			assert.ok(buf.atEnd(), 'extra trailing bytes');
 			sig.name = 'sig';
@@ -204,7 +254,26 @@
 
 	var r, s;
 	var inner = buf.readBuffer();
-	if (inner.toString('ascii').match(/^ecdsa-/)) {
+	var stype = inner.toString('ascii');
+	if (stype.slice(0, 6) === 'ecdsa-') {
+		var parts = stype.split('-');
+		assert.strictEqual(parts[0], 'ecdsa');
+		assert.strictEqual(parts[1], 'sha2');
+		opts.curve = parts[2];
+		switch (opts.curve) {
+		case 'nistp256':
+			opts.hashAlgo = 'sha256';
+			break;
+		case 'nistp384':
+			opts.hashAlgo = 'sha384';
+			break;
+		case 'nistp521':
+			opts.hashAlgo = 'sha512';
+			break;
+		default:
+			throw (new Error('Unsupported ECDSA curve: ' +
+			    opts.curve));
+		}
 		inner = buf.readBuffer();
 		assert.ok(buf.atEnd(), 'extra trailing bytes on outer');
 		buf = new SSHBuffer({buffer: inner});
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/ssh-buffer.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/ssh-buffer.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/ssh-buffer.js	(working copy)
@@ -3,6 +3,7 @@
 module.exports = SSHBuffer;
 
 var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
 
 function SSHBuffer(opts) {
 	assert.object(opts, 'options');
@@ -10,7 +11,7 @@
 		assert.buffer(opts.buffer, 'options.buffer');
 
 	this._size = opts.buffer ? opts.buffer.length : 1024;
-	this._buffer = opts.buffer || (new Buffer(this._size));
+	this._buffer = opts.buffer || Buffer.alloc(this._size);
 	this._offset = 0;
 }
 
@@ -32,7 +33,7 @@
 
 SSHBuffer.prototype.expand = function () {
 	this._size *= 2;
-	var buf = new Buffer(this._size);
+	var buf = Buffer.alloc(this._size);
 	this._buffer.copy(buf, 0);
 	this._buffer = buf;
 };
@@ -96,7 +97,7 @@
 };
 
 SSHBuffer.prototype.writeString = function (str) {
-	this.writeBuffer(new Buffer(str, 'utf8'));
+	this.writeBuffer(Buffer.from(str, 'utf8'));
 };
 
 SSHBuffer.prototype.writeCString = function (str) {
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/utils.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/utils.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/lib/utils.js	(working copy)
@@ -4,18 +4,34 @@
 	bufferSplit: bufferSplit,
 	addRSAMissing: addRSAMissing,
 	calculateDSAPublic: calculateDSAPublic,
+	calculateED25519Public: calculateED25519Public,
+	calculateX25519Public: calculateX25519Public,
 	mpNormalize: mpNormalize,
+	mpDenormalize: mpDenormalize,
 	ecNormalize: ecNormalize,
 	countZeros: countZeros,
 	assertCompatible: assertCompatible,
 	isCompatible: isCompatible,
 	opensslKeyDeriv: opensslKeyDeriv,
-	opensshCipherInfo: opensshCipherInfo
+	opensshCipherInfo: opensshCipherInfo,
+	publicFromPrivateECDSA: publicFromPrivateECDSA,
+	zeroPadToLength: zeroPadToLength,
+	writeBitString: writeBitString,
+	readBitString: readBitString,
+	pbkdf2: pbkdf2
 };
 
 var assert = require('assert-plus');
+var Buffer = require('safer-buffer').Buffer;
 var PrivateKey = require('./private-key');
+var Key = require('./key');
 var crypto = require('crypto');
+var algs = require('./algs');
+var asn1 = require('asn1');
+
+var ec = require('ecc-jsbn/lib/ec');
+var jsbn = require('jsbn').BigInteger;
+var nacl = require('tweetnacl');
 
 var MAX_CLASS_DEPTH = 3;
 
@@ -72,8 +88,9 @@
 }
 
 var CIPHER_LEN = {
-	'des-ede3-cbc': { key: 7, iv: 8 },
-	'aes-128-cbc': { key: 16, iv: 16 }
+	'des-ede3-cbc': { key: 24, iv: 8 },
+	'aes-128-cbc': { key: 16, iv: 16 },
+	'aes-256-cbc': { key: 32, iv: 16 }
 };
 var PKCS5_SALT_LEN = 8;
 
@@ -88,7 +105,7 @@
 	salt = salt.slice(0, PKCS5_SALT_LEN);
 
 	var D, D_prev, bufs;
-	var material = new Buffer(0);
+	var material = Buffer.alloc(0);
 	while (material.length < clen.key + clen.iv) {
 		bufs = [];
 		if (D_prev)
@@ -108,6 +125,40 @@
 	});
 }
 
+/* See: RFC2898 */
+function pbkdf2(hashAlg, salt, iterations, size, passphrase) {
+	var hkey = Buffer.alloc(salt.length + 4);
+	salt.copy(hkey);
+
+	var gen = 0, ts = [];
+	var i = 1;
+	while (gen < size) {
+		var t = T(i++);
+		gen += t.length;
+		ts.push(t);
+	}
+	return (Buffer.concat(ts).slice(0, size));
+
+	function T(I) {
+		hkey.writeUInt32BE(I, hkey.length - 4);
+
+		var hmac = crypto.createHmac(hashAlg, passphrase);
+		hmac.update(hkey);
+
+		var Ti = hmac.digest();
+		var Uc = Ti;
+		var c = 1;
+		while (c++ < iterations) {
+			hmac = crypto.createHmac(hashAlg, passphrase);
+			hmac.update(Uc);
+			Uc = hmac.digest();
+			for (var x = 0; x < Ti.length; ++x)
+				Ti[x] ^= Uc[x];
+		}
+		return (Ti);
+	}
+}
+
 /* Count leading zero bits on a buffer */
 function countZeros(buf) {
 	var o = 0, obit = 8;
@@ -172,18 +223,59 @@
 		if (!addZero)
 			return (buf);
 	}
-	var b = new Buffer(buf.length + 1);
+	var b = Buffer.alloc(buf.length + 1);
 	b[0] = 0x0;
 	buf.copy(b, 1);
 	return (b);
 }
 
+function readBitString(der, tag) {
+	if (tag === undefined)
+		tag = asn1.Ber.BitString;
+	var buf = der.readString(tag, true);
+	assert.strictEqual(buf[0], 0x00, 'bit strings with unused bits are ' +
+	    'not supported (0x' + buf[0].toString(16) + ')');
+	return (buf.slice(1));
+}
+
+function writeBitString(der, buf, tag) {
+	if (tag === undefined)
+		tag = asn1.Ber.BitString;
+	var b = Buffer.alloc(buf.length + 1);
+	b[0] = 0x00;
+	buf.copy(b, 1);
+	der.writeBuffer(b, tag);
+}
+
 function mpNormalize(buf) {
 	assert.buffer(buf);
 	while (buf.length > 1 && buf[0] === 0x00 && (buf[1] & 0x80) === 0x00)
 		buf = buf.slice(1);
 	if ((buf[0] & 0x80) === 0x80) {
-		var b = new Buffer(buf.length + 1);
+		var b = Buffer.alloc(buf.length + 1);
+		b[0] = 0x00;
+		buf.copy(b, 1);
+		buf = b;
+	}
+	return (buf);
+}
+
+function mpDenormalize(buf) {
+	assert.buffer(buf);
+	while (buf.length > 1 && buf[0] === 0x00)
+		buf = buf.slice(1);
+	return (buf);
+}
+
+function zeroPadToLength(buf, len) {
+	assert.buffer(buf);
+	assert.number(len);
+	while (buf.length > len) {
+		assert.equal(buf[0], 0x00);
+		buf = buf.slice(1);
+	}
+	while (buf.length < len) {
+		var b = Buffer.alloc(buf.length + 1);
 		b[0] = 0x00;
 		buf.copy(b, 1);
 		buf = b;
@@ -192,7 +284,7 @@
 }
 
 function bigintToMpBuf(bigint) {
-	var buf = new Buffer(bigint.toByteArray());
+	var buf = Buffer.from(bigint.toByteArray());
 	buf = mpNormalize(buf);
 	return (buf);
 }
@@ -201,35 +293,37 @@
 	assert.buffer(g);
 	assert.buffer(p);
 	assert.buffer(x);
-	try {
-		var bigInt = require('jsbn').BigInteger;
-	} catch (e) {
-		throw (new Error('To load a PKCS#8 format DSA private key, ' +
-		    'the node jsbn library is required.'));
-	}
-	g = new bigInt(g);
-	p = new bigInt(p);
-	x = new bigInt(x);
+	g = new jsbn(g);
+	p = new jsbn(p);
+	x = new jsbn(x);
 	var y = g.modPow(x, p);
 	var ybuf = bigintToMpBuf(y);
 	return (ybuf);
 }
 
+function calculateED25519Public(k) {
+	assert.buffer(k);
+
+	var kp = nacl.sign.keyPair.fromSeed(new Uint8Array(k));
+	return (Buffer.from(kp.publicKey));
+}
+
+function calculateX25519Public(k) {
+	assert.buffer(k);
+
+	var kp = nacl.box.keyPair.fromSeed(new Uint8Array(k));
+	return (Buffer.from(kp.publicKey));
+}
+
 function addRSAMissing(key) {
 	assert.object(key);
 	assertCompatible(key, PrivateKey, [1, 1]);
-	try {
-		var bigInt = require('jsbn').BigInteger;
-	} catch (e) {
-		throw (new Error('To write a PEM private key from ' +
-		    'this source, the node jsbn lib is required.'));
-	}
 
-	var d = new bigInt(key.part.d.data);
+	var d = new jsbn(key.part.d.data);
 	var buf;
 
 	if (!key.part.dmodp) {
-		var p = new bigInt(key.part.p.data);
+		var p = new jsbn(key.part.p.data);
 		var dmodp = d.mod(p.subtract(1));
 
 		buf = bigintToMpBuf(dmodp);
@@ -237,7 +331,7 @@
 		key.parts.push(key.part.dmodp);
 	}
 	if (!key.part.dmodq) {
-		var q = new bigInt(key.part.q.data);
+		var q = new jsbn(key.part.q.data);
 		var dmodq = d.mod(q.subtract(1));
 
 		buf = bigintToMpBuf(dmodq);
@@ -246,6 +340,28 @@
 	}
 }
 
+function publicFromPrivateECDSA(curveName, priv) {
+	assert.string(curveName, 'curveName');
+	assert.buffer(priv);
+	var params = algs.curves[curveName];
+	var p = new jsbn(params.p);
+	var a = new jsbn(params.a);
+	var b = new jsbn(params.b);
+	var curve = new ec.ECCurveFp(p, a, b);
+	var G = curve.decodePointHex(params.G.toString('hex'));
+
+	var d = new jsbn(mpNormalize(priv));
+	var pub = G.multiply(d);
+	pub = Buffer.from(curve.encodePointHex(pub), 'hex');
+
+	var parts = [];
+	parts.push({name: 'curve', data: Buffer.from(curveName)});
+	parts.push({name: 'Q', data: pub});
+
+	var key = new Key({type: 'ecdsa', curve: curve, parts: parts});
+	return (key);
+}
+
 function opensshCipherInfo(cipher) {
 	var inf = {};
 	switch (cipher) {
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/package.json
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/package.json	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/http-signature/node_modules/sshpk/package.json	(working copy)
@@ -1,6 +1,6 @@
 {
   "name": "sshpk",
-  "version": "1.10.1",
+  "version": "1.18.0",
   "description": "A library for finding and using SSH public keys",
   "main": "lib/index.js",
   "scripts": {
@@ -8,11 +8,9 @@
   },
   "repository": {
     "type": "git",
-    "url": "git+https://github.com/arekinath/node-sshpk.git"
-  },
-  "author": {
-    "name": "Joyent, Inc"
+    "url": "git+https://github.com/joyent/node-sshpk.git"
   },
+  "author": "Joyent, Inc",
   "contributors": [
     {
       "name": "Dave Eddy",
@@ -45,41 +43,17 @@
     "assert-plus": "^1.0.0",
     "dashdash": "^1.12.0",
     "getpass": "^0.1.1",
+    "safer-buffer": "^2.0.2",
     "jsbn": "~0.1.0",
     "tweetnacl": "~0.14.0",
-    "jodid25519": "^1.0.0",
-    "ecc-jsbn": "~0.1.1",
-    "bcrypt-pbkdf": "^1.0.0"
-  },
-  "optionalDependencies": {
-    "jsbn": "~0.1.0",
-    "tweetnacl": "~0.14.0",
-    "jodid25519": "^1.0.0",
     "ecc-jsbn": "~0.1.1",
     "bcrypt-pbkdf": "^1.0.0"
   },
+  "optionalDependencies": {},
   "devDependencies": {
     "tape": "^3.5.0",
     "benchmark": "^1.0.0",
     "sinon": "^1.17.2",
     "temp": "^0.8.2"
-  },
-  "man": [
-    "/home/netboy/.npm/sshpk/1.10.1/package/man/man1/sshpk-conv.1",
-    "/home/netboy/.npm/sshpk/1.10.1/package/man/man1/sshpk-sign.1",
-    "/home/netboy/.npm/sshpk/1.10.1/package/man/man1/sshpk-verify.1"
-  ],
-  "bin": {
-    "sshpk-conv": "bin/sshpk-conv",
-    "sshpk-sign": "bin/sshpk-sign",
-    "sshpk-verify": "bin/sshpk-verify"
-  },
-  "readme": "sshpk\n=========\n\nParse, convert, fingerprint and use SSH keys (both public and private) in pure\nnode -- no `ssh-keygen` or other external dependencies.\n\nSupports RSA, DSA, ECDSA (nistp-\\*) and ED25519 key types, in PEM (PKCS#1, \nPKCS#8) and OpenSSH formats.\n\nThis library has been extracted from\n[`node-http-signature`](https://github.com/joyent/node-http-signature)\n(work by [Mark Cavage](https://github.com/mcavage) and\n[Dave Eddy](https://github.com/bahamas10)) and\n[`node-ssh-fingerprint`](https://github.com/bahamas10/node-ssh-fingerprint)\n(work by Dave Eddy), with additions (including ECDSA support) by\n[Alex Wilson](https://github.com/arekinath).\n\nInstall\n-------\n\n```\nnpm install sshpk\n```\n\nExamples\n--------\n\n```js\nvar sshpk = require('sshpk');\n\nvar fs = require('fs');\n\n/* Read in an OpenSSH-format public key */\nvar keyPub = fs.readFileSync('id_rsa.pub');\nvar key = sshpk.parseKey(keyPub, 'ssh');\n\n/* Get metadata about the key */\nconsole.log('type => %s', key.type);\nconsole.log('size => %d bits', key.size);\nconsole.log('comment => %s', key.comment);\n\n/* Compute key fingerprints, in new OpenSSH (>6.7) format, and old MD5 */\nconsole.log('fingerprint => %s', key.fingerprint().toString());\nconsole.log('old-style fingerprint => %s', key.fingerprint('md5').toString());\n```\n\nExample output:\n\n```\ntype => rsa\nsize => 2048 bits\ncomment => foo@foo.com\nfingerprint => SHA256:PYC9kPVC6J873CSIbfp0LwYeczP/W4ffObNCuDJ1u5w\nold-style fingerprint => a0:c8:ad:6c:32:9a:32:fa:59:cc:a9:8c:0a:0d:6e:bd\n```\n\nMore examples: converting between formats:\n\n```js\n/* Read in a PEM public key */\nvar keyPem = fs.readFileSync('id_rsa.pem');\nvar key = sshpk.parseKey(keyPem, 'pem');\n\n/* Convert to PEM PKCS#8 public key format */\nvar pemBuf = key.toBuffer('pkcs8');\n\n/* Convert to SSH public key format (and return as a string) */\nvar sshKey = key.toString('ssh');\n```\n\nSigning and verifying:\n\n```js\n/* Read in an OpenSSH/PEM *private* key */\nvar keyPriv = fs.readFileSync('id_ecdsa');\nvar key = sshpk.parsePrivateKey(keyPriv, 'pem');\n\nvar data = 'some data';\n\n/* Sign some data with the key */\nvar s = key.createSign('sha1');\ns.update(data);\nvar signature = s.sign();\n\n/* Now load the public key (could also use just key.toPublic()) */\nvar keyPub = fs.readFileSync('id_ecdsa.pub');\nkey = sshpk.parseKey(keyPub, 'ssh');\n\n/* Make a crypto.Verifier with this key */\nvar v = key.createVerify('sha1');\nv.update(data);\nvar valid = v.verify(signature);\n/* => true! */\n```\n\nMatching fingerprints with keys:\n\n```js\nvar fp = sshpk.parseFingerprint('SHA256:PYC9kPVC6J873CSIbfp0LwYeczP/W4ffObNCuDJ1u5w');\n\nvar keys = [sshpk.parseKey(...), sshpk.parseKey(...), ...];\n\nkeys.forEach(function (key) {\n\tif (fp.matches(key))\n\t\tconsole.log('found it!');\n});\n```\n\nUsage\n-----\n\n## Public keys\n\n### `parseKey(data[, format = 'auto'[, options]])`\n\nParses a key from a given data format and returns a new `Key` object.\n\nParameters\n\n- `data` -- Either a Buffer or String, containing the key\n- `format` -- String name of format to use, valid options are:\n  - `auto`: choose automatically from all below\n  - `pem`: supports both PKCS#1 and PKCS#8\n  - `ssh`: standard OpenSSH format,\n  - `pkcs1`, `pkcs8`: variants of `pem`\n  - `rfc4253`: raw OpenSSH wire format\n  - `openssh`: new post-OpenSSH 6.5 internal format, produced by \n               `ssh-keygen -o`\n- `options` -- Optional Object, extra options, with keys:\n  - `filename` -- Optional String, name for the key being parsed \n                  (eg. the filename that was opened). Used to generate\n                  Error messages\n  - `passphrase` -- Optional String, encryption passphrase used to decrypt an\n                    encrypted PEM file\n\n### `Key.isKey(obj)`\n\nReturns `true` if the given object is a valid `Key` object created by a version\nof `sshpk` compatible with this one.\n\nParameters\n\n- `obj` -- Object to identify\n\n### `Key#type`\n\nString, the type of key. Valid options are `rsa`, `dsa`, `ecdsa`.\n\n### `Key#size`\n\nInteger, \"size\" of the key in bits. For RSA/DSA this is the size of the modulus;\nfor ECDSA this is the bit size of the curve in use.\n\n### `Key#comment`\n\nOptional string, a key comment used by some formats (eg the `ssh` format).\n\n### `Key#curve`\n\nOnly present if `this.type === 'ecdsa'`, string containing the name of the\nnamed curve used with this key. Possible values include `nistp256`, `nistp384`\nand `nistp521`.\n\n### `Key#toBuffer([format = 'ssh'])`\n\nConvert the key into a given data format and return the serialized key as\na Buffer.\n\nParameters\n\n- `format` -- String name of format to use, for valid options see `parseKey()`\n\n### `Key#toString([format = 'ssh])`\n\nSame as `this.toBuffer(format).toString()`.\n\n### `Key#fingerprint([algorithm = 'sha256'])`\n\nCreates a new `Fingerprint` object representing this Key's fingerprint.\n\nParameters\n\n- `algorithm` -- String name of hash algorithm to use, valid options are `md5`,\n                 `sha1`, `sha256`, `sha384`, `sha512`\n\n### `Key#createVerify([hashAlgorithm])`\n\nCreates a `crypto.Verifier` specialized to use this Key (and the correct public\nkey algorithm to match it). The returned Verifier has the same API as a regular\none, except that the `verify()` function takes only the target signature as an\nargument.\n\nParameters\n\n- `hashAlgorithm` -- optional String name of hash algorithm to use, any\n                     supported by OpenSSL are valid, usually including\n                     `sha1`, `sha256`.\n\n`v.verify(signature[, format])` Parameters\n\n- `signature` -- either a Signature object, or a Buffer or String\n- `format` -- optional String, name of format to interpret given String with.\n              Not valid if `signature` is a Signature or Buffer.\n\n### `Key#createDiffieHellman()`\n### `Key#createDH()`\n\nCreates a Diffie-Hellman key exchange object initialized with this key and all\nnecessary parameters. This has the same API as a `crypto.DiffieHellman`\ninstance, except that functions take `Key` and `PrivateKey` objects as\narguments, and return them where indicated for.\n\nThis is only valid for keys belonging to a cryptosystem that supports DHE\nor a close analogue (i.e. `dsa`, `ecdsa` and `curve25519` keys). An attempt\nto call this function on other keys will yield an `Error`.\n\n## Private keys\n\n### `parsePrivateKey(data[, format = 'auto'[, options]])`\n\nParses a private key from a given data format and returns a new\n`PrivateKey` object.\n\nParameters\n\n- `data` -- Either a Buffer or String, containing the key\n- `format` -- String name of format to use, valid options are:\n  - `auto`: choose automatically from all below\n  - `pem`: supports both PKCS#1 and PKCS#8\n  - `ssh`, `openssh`: new post-OpenSSH 6.5 internal format, produced by \n                      `ssh-keygen -o`\n  - `pkcs1`, `pkcs8`: variants of `pem`\n  - `rfc4253`: raw OpenSSH wire format\n- `options` -- Optional Object, extra options, with keys:\n  - `filename` -- Optional String, name for the key being parsed \n                  (eg. the filename that was opened). Used to generate\n                  Error messages\n  - `passphrase` -- Optional String, encryption passphrase used to decrypt an\n                    encrypted PEM file\n\n### `PrivateKey.isPrivateKey(obj)`\n\nReturns `true` if the given object is a valid `PrivateKey` object created by a\nversion of `sshpk` compatible with this one.\n\nParameters\n\n- `obj` -- Object to identify\n\n### `PrivateKey#type`\n\nString, the type of key. Valid options are `rsa`, `dsa`, `ecdsa`.\n\n### `PrivateKey#size`\n\nInteger, \"size\" of the key in bits. For RSA/DSA this is the size of the modulus;\nfor ECDSA this is the bit size of the curve in use.\n\n### `PrivateKey#curve`\n\nOnly present if `this.type === 'ecdsa'`, string containing the name of the\nnamed curve used with this key. Possible values include `nistp256`, `nistp384`\nand `nistp521`.\n\n### `PrivateKey#toBuffer([format = 'pkcs1'])`\n\nConvert the key into a given data format and return the serialized key as\na Buffer.\n\nParameters\n\n- `format` -- String name of format to use, valid options are listed under \n              `parsePrivateKey`. Note that ED25519 keys default to `openssh`\n              format instead (as they have no `pkcs1` representation).\n\n### `PrivateKey#toString([format = 'pkcs1'])`\n\nSame as `this.toBuffer(format).toString()`.\n\n### `PrivateKey#toPublic()`\n\nExtract just the public part of this private key, and return it as a `Key`\nobject.\n\n### `PrivateKey#fingerprint([algorithm = 'sha256'])`\n\nSame as `this.toPublic().fingerprint()`.\n\n### `PrivateKey#createVerify([hashAlgorithm])`\n\nSame as `this.toPublic().createVerify()`.\n\n### `PrivateKey#createSign([hashAlgorithm])`\n\nCreates a `crypto.Sign` specialized to use this PrivateKey (and the correct\nkey algorithm to match it). The returned Signer has the same API as a regular\none, except that the `sign()` function takes no arguments, and returns a\n`Signature` object.\n\nParameters\n\n- `hashAlgorithm` -- optional String name of hash algorithm to use, any\n                     supported by OpenSSL are valid, usually including\n                     `sha1`, `sha256`.\n\n`v.sign()` Parameters\n\n- none\n\n### `PrivateKey#derive(newType)`\n\nDerives a related key of type `newType` from this key. Currently this is\nonly supported to change between `ed25519` and `curve25519` keys which are\nstored with the same private key (but usually distinct public keys in order\nto avoid degenerate keys that lead to a weak Diffie-Hellman exchange).\n\nParameters\n\n- `newType` -- String, type of key to derive, either `ed25519` or `curve25519`\n\n## Fingerprints\n\n### `parseFingerprint(fingerprint[, algorithms])`\n\nPre-parses a fingerprint, creating a `Fingerprint` object that can be used to\nquickly locate a key by using the `Fingerprint#matches` function.\n\nParameters\n\n- `fingerprint` -- String, the fingerprint value, in any supported format\n- `algorithms` -- Optional list of strings, names of hash algorithms to limit\n                  support to. If `fingerprint` uses a hash algorithm not on\n                  this list, throws `InvalidAlgorithmError`.\n\n### `Fingerprint.isFingerprint(obj)`\n\nReturns `true` if the given object is a valid `Fingerprint` object created by a\nversion of `sshpk` compatible with this one.\n\nParameters\n\n- `obj` -- Object to identify\n\n### `Fingerprint#toString([format])`\n\nReturns a fingerprint as a string, in the given format.\n\nParameters\n\n- `format` -- Optional String, format to use, valid options are `hex` and\n              `base64`. If this `Fingerprint` uses the `md5` algorithm, the\n              default format is `hex`. Otherwise, the default is `base64`.\n\n### `Fingerprint#matches(key)`\n\nVerifies whether or not this `Fingerprint` matches a given `Key`. This function\nuses double-hashing to avoid leaking timing information. Returns a boolean.\n\nParameters\n\n- `key` -- a `Key` object, the key to match this fingerprint against\n\n## Signatures\n\n### `parseSignature(signature, algorithm, format)`\n\nParses a signature in a given format, creating a `Signature` object. Useful\nfor converting between the SSH and ASN.1 (PKCS/OpenSSL) signature formats, and\nalso returned as output from `PrivateKey#createSign().sign()`.\n\nA Signature object can also be passed to a verifier produced by\n`Key#createVerify()` and it will automatically be converted internally into the\ncorrect format for verification.\n\nParameters\n\n- `signature` -- a Buffer (binary) or String (base64), data of the actual\n                 signature in the given format\n- `algorithm` -- a String, name of the algorithm to be used, possible values\n                 are `rsa`, `dsa`, `ecdsa`\n- `format` -- a String, either `asn1` or `ssh`\n\n### `Signature.isSignature(obj)`\n\nReturns `true` if the given object is a valid `Signature` object created by a\nversion of `sshpk` compatible with this one.\n\nParameters\n\n- `obj` -- Object to identify\n\n### `Signature#toBuffer([format = 'asn1'])`\n\nConverts a Signature to the given format and returns it as a Buffer.\n\nParameters\n\n- `format` -- a String, either `asn1` or `ssh`\n\n### `Signature#toString([format = 'asn1'])`\n\nSame as `this.toBuffer(format).toString('base64')`.\n\n## Certificates\n\n`sshpk` includes basic support for parsing certificates in X.509 (PEM) format\nand the OpenSSH certificate format. This feature is intended to be used mainly\nto access basic metadata about certificates, extract public keys from them, and\nalso to generate simple self-signed certificates from an existing key.\n\nNotably, there is no implementation of CA chain-of-trust verification, and no\nsupport for key usage restrictions (or other kinds of restrictions). Please do\nthe security world a favour, and DO NOT use this code for certificate\nverification in the traditional X.509 CA chain style.\n\n### `parseCertificate(data, format)`\n\nParameters\n\n - `data` -- a Buffer or String\n - `format` -- a String, format to use, one of `'openssh'`, `'pem'` (X.509 in a\n               PEM wrapper), or `'x509'` (raw DER encoded)\n\n### `createSelfSignedCertificate(subject, privateKey[, options])`\n\nParameters\n\n - `subject` -- an Identity, the subject of the certificate\n - `privateKey` -- a PrivateKey, the key of the subject: will be used both to be\n                   placed in the certificate and also to sign it (since this is\n                   a self-signed certificate)\n - `options` -- optional Object, with keys:\n   - `lifetime` -- optional Number, lifetime of the certificate from now in\n                   seconds\n   - `validFrom`, `validUntil` -- optional Dates, beginning and end of\n                                  certificate validity period. If given\n                                  `lifetime` will be ignored\n   - `serial` -- optional Buffer, the serial number of the certificate\n\n### `createCertificate(subject, key, issuer, issuerKey[, options])`\n\nParameters\n\n - `subject` -- an Identity, the subject of the certificate\n - `key` -- a Key, the public key of the subject\n - `issuer` -- an Identity, the issuer of the certificate who will sign it\n - `issuerKey` -- a PrivateKey, the issuer's private key for signing\n - `options` -- optional Object, with keys:\n   - `lifetime` -- optional Number, lifetime of the certificate from now in\n                   seconds\n   - `validFrom`, `validUntil` -- optional Dates, beginning and end of\n                                  certificate validity period. If given\n                                  `lifetime` will be ignored\n   - `serial` -- optional Buffer, the serial number of the certificate\n\n### `Certificate#subjects`\n\nArray of `Identity` instances describing the subject of this certificate.\n\n### `Certificate#issuer`\n\nThe `Identity` of the Certificate's issuer (signer).\n\n### `Certificate#subjectKey`\n\nThe public key of the subject of the certificate, as a `Key` instance.\n\n### `Certificate#issuerKey`\n\nThe public key of the signing issuer of this certificate, as a `Key` instance.\nMay be `undefined` if the issuer's key is unknown (e.g. on an X509 certificate).\n\n### `Certificate#serial`\n\nThe serial number of the certificate. As this is normally a 64-bit or wider\ninteger, it is returned as a Buffer.\n\n### `Certificate#isExpired([when])`\n\nTests whether the Certificate is currently expired (i.e. the `validFrom` and\n`validUntil` dates specify a range of time that does not include the current\ntime).\n\nParameters\n\n - `when` -- optional Date, if specified, tests whether the Certificate was or\n             will be expired at the specified time instead of now\n\nReturns a Boolean.\n\n### `Certificate#isSignedByKey(key)`\n\nTests whether the Certificate was validly signed by the given (public) Key.\n\nParameters\n\n - `key` -- a Key instance\n\nReturns a Boolean.\n\n### `Certificate#isSignedBy(certificate)`\n\nTests whether this Certificate was validly signed by the subject of the given\ncertificate. Also tests that the issuer Identity of this Certificate and the\nsubject Identity of the other Certificate are equivalent.\n\nParameters\n\n - `certificate` -- another Certificate instance\n\nReturns a Boolean.\n\n### `Certificate#fingerprint([hashAlgo])`\n\nReturns the X509-style fingerprint of the entire certificate (as a Fingerprint\ninstance). This matches what a web-browser or similar would display as the\ncertificate fingerprint and should not be confused with the fingerprint of the\nsubject's public key.\n\nParameters\n\n - `hashAlgo` -- an optional String, any hash function name\n\n### `Certificate#toBuffer([format])`\n\nSerializes the Certificate to a Buffer and returns it.\n\nParameters\n\n - `format` -- an optional String, output format, one of `'openssh'`, `'pem'` or\n               `'x509'`. Defaults to `'x509'`.\n\nReturns a Buffer.\n\n### `Certificate#toString([format])`\n\n - `format` -- an optional String, output format, one of `'openssh'`, `'pem'` or\n               `'x509'`. Defaults to `'pem'`.\n\nReturns a String.\n\n## Certificate identities\n\n### `identityForHost(hostname)`\n\nConstructs a host-type Identity for a given hostname.\n\nParameters\n\n - `hostname` -- the fully qualified DNS name of the host\n\nReturns an Identity instance.\n\n### `identityForUser(uid)`\n\nConstructs a user-type Identity for a given UID.\n\nParameters\n\n - `uid` -- a String, user identifier (login name)\n\nReturns an Identity instance.\n\n### `identityForEmail(email)`\n\nConstructs an email-type Identity for a given email address.\n\nParameters\n\n - `email` -- a String, email address\n\nReturns an Identity instance.\n\n### `identityFromDN(dn)`\n\nParses an LDAP-style DN string (e.g. `'CN=foo, C=US'`) and turns it into an\nIdentity instance.\n\nParameters\n\n - `dn` -- a String\n\nReturns an Identity instance.\n\n### `Identity#toString()`\n\nReturns the identity as an LDAP-style DN string.\ne.g. `'CN=foo, O=bar corp, C=us'`\n\n### `Identity#type`\n\nThe type of identity. One of `'host'`, `'user'`, `'email'` or `'unknown'`\n\n### `Identity#hostname`\n### `Identity#uid`\n### `Identity#email`\n\nSet when `type` is `'host'`, `'user'`, or `'email'`, respectively. Strings.\n\n### `Identity#cn`\n\nThe value of the first `CN=` in the DN, if any.\n\nErrors\n------\n\n### `InvalidAlgorithmError`\n\nThe specified algorithm is not valid, either because it is not supported, or\nbecause it was not included on a list of allowed algorithms.\n\nThrown by `Fingerprint.parse`, `Key#fingerprint`.\n\nProperties\n\n- `algorithm` -- the algorithm that could not be validated\n\n### `FingerprintFormatError`\n\nThe fingerprint string given could not be parsed as a supported fingerprint\nformat, or the specified fingerprint format is invalid.\n\nThrown by `Fingerprint.parse`, `Fingerprint#toString`.\n\nProperties\n\n- `fingerprint` -- if caused by a fingerprint, the string value given\n- `format` -- if caused by an invalid format specification, the string value given\n\n### `KeyParseError`\n\nThe key data given could not be parsed as a valid key.\n\nProperties\n\n- `keyName` -- `filename` that was given to `parseKey`\n- `format` -- the `format` that was trying to parse the key (see `parseKey`)\n- `innerErr` -- the inner Error thrown by the format parser\n\n### `KeyEncryptedError`\n\nThe key is encrypted with a symmetric key (ie, it is password protected). The\nparsing operation would succeed if it was given the `passphrase` option.\n\nProperties\n\n- `keyName` -- `filename` that was given to `parseKey`\n- `format` -- the `format` that was trying to parse the key (currently can only\n              be `\"pem\"`)\n\n### `CertificateParseError`\n\nThe certificate data given could not be parsed as a valid certificate.\n\nProperties\n\n- `certName` -- `filename` that was given to `parseCertificate`\n- `format` -- the `format` that was trying to parse the key\n              (see `parseCertificate`)\n- `innerErr` -- the inner Error thrown by the format parser\n\nFriends of sshpk\n----------------\n\n * [`sshpk-agent`](https://github.com/arekinath/node-sshpk-agent) is a library\n   for speaking the `ssh-agent` protocol from node.js, which uses `sshpk`\n",
-  "readmeFilename": "README.md",
-  "_id": "sshpk@1.10.1",
-  "dist": {
-    "shasum": "102e71a6fbf1b38266c1a10a58a0d5c7778476ee"
-  },
-  "_from": "sshpk@^1.7.0",
-  "_resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.10.1.tgz"
+  }
 }
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/tunnel-agent/index.js
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/tunnel-agent/index.js	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/tunnel-agent/index.js	(working copy)
@@ -7,6 +7,7 @@
   , events = require('events')
   , assert = require('assert')
   , util = require('util')
+  , Buffer = require('safe-buffer').Buffer
   ;
 
 exports.httpOverHttp = httpOverHttp
@@ -118,7 +119,7 @@
   var placeholder = {}
   self.sockets.push(placeholder)
 
-  var connectOptions = mergeOptions({}, self.proxyOptions, 
+  var connectOptions = mergeOptions({}, self.proxyOptions,
     { method: 'CONNECT'
     , path: options.host + ':' + options.port
     , agent: false
@@ -127,7 +128,7 @@
   if (connectOptions.proxyAuth) {
     connectOptions.headers = connectOptions.headers || {}
     connectOptions.headers['Proxy-Authorization'] = 'Basic ' +
-        new Buffer(connectOptions.proxyAuth).toString('base64')
+        Buffer.from(connectOptions.proxyAuth).toString('base64')
   }
 
   debug('making CONNECT request')
@@ -183,7 +184,7 @@
 TunnelingAgent.prototype.removeSocket = function removeSocket(socket) {
   var pos = this.sockets.indexOf(socket)
   if (pos === -1) return
-  
+
   this.sockets.splice(pos, 1)
 
   var pending = this.requests.shift()
@@ -198,7 +199,7 @@
   var self = this
   TunnelingAgent.prototype.createSocket.call(self, options, function(socket) {
     // 0 is dummy port for v0.6
-    var secureSocket = tls.connect(0, mergeOptions({}, self.options, 
+    var secureSocket = tls.connect(0, mergeOptions({}, self.options,
       { servername: options.host
       , socket: socket
       }
Index: /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/tunnel-agent/package.json
===================================================================
--- /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/tunnel-agent/package.json	(revision 20239)
+++ /branches/rel_ag_9_4_0_493_SBOM/restfulapi/proxy/media/node_modules/less/node_modules/request/node_modules/tunnel-agent/package.json	(working copy)
@@ -1,13 +1,9 @@
 {
-  "author": {
-    "name": "Mikeal Rogers",
-    "email": "mikeal.rogers@gmail.com",
-    "url": "http://www.futurealoof.com"
-  },
+  "author": "Mikeal Rogers <mikeal.rogers@gmail.com> (http://www.futurealoof.com)",
   "name": "tunnel-agent",
   "license": "Apache-2.0",
   "description": "HTTP proxy tunneling agent. Formerly part of mikeal/request, now a standalone module.",
-  "version": "0.4.3",
+  "version": "0.6.0",
   "repository": {
     "url": "https://github.com/mikeal/tunnel-agent"
   },
@@ -15,21 +11,12 @@
   "files": [
     "index.js"
   ],
-  "dependencies": {},
+  "dependencies": {
+    "safe-buffer": "^5.0.1"
+  },
   "devDependencies": {},
   "optionalDependencies": {},
   "engines": {
     "node": "*"
-  },
-  "readme": "tunnel-agent\n============\n\nHTTP proxy tunneling agent. Formerly part of mikeal/request, now a standalone module.\n",
-  "readmeFilename": "README.md",
-  "bugs": {
-    "url": "https://github.com/mikeal/tunnel-agent/issues"
-  },
-  "_id": "tunnel-agent@0.4.3",
-  "dist": {
-    "shasum": "55d2d80609d1296ed51e5a09e419bb81fb7ac4f5"
-  },
-  "_from": "tunnel-agent@~0.4.1",
-  "_resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz"
+  }
 }
