-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
convert to pure esm module and es6 everywhere. add changelog. update …
…tap. fixes #65
- Loading branch information
1 parent
b534932
commit ba33cff
Showing
14 changed files
with
551 additions
and
535 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,5 @@ node_modules | |
|
||
# Don't checkin package-lock.json for libraries | ||
package-lock.json | ||
|
||
.nyc_output |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
engine-strict=true | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# 3.0.0 | ||
* BREAKING: publish as a pure ES module | ||
* BREAKING: only support node >= 12.17 | ||
* BREAKING: switch to es6 everywhere | ||
* update tap dependency |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,39 @@ | ||
'use strict' | ||
import https from 'https' | ||
|
||
var https = require('https') | ||
|
||
const globalCache = { } // default in-memory cache for downloaded certificates | ||
|
||
var globalCache = {} // default in-memory cache for downloaded certificates | ||
|
||
module.exports = function fetchCert (options, callback) { | ||
var url = options.url | ||
var cache = options.cache || globalCache | ||
var cachedResponse = cache[url.href] | ||
var servedFromCache = false | ||
if (cachedResponse) { | ||
servedFromCache = true | ||
process.nextTick(callback, undefined, cachedResponse, servedFromCache) | ||
return | ||
} | ||
export default function fetchCert (options, callback) { | ||
const url = options.url | ||
const cache = options.cache || globalCache | ||
const cachedResponse = cache[url.href] | ||
let servedFromCache = false | ||
if (cachedResponse) { | ||
servedFromCache = true | ||
process.nextTick(callback, undefined, cachedResponse, servedFromCache) | ||
return | ||
} | ||
|
||
var body = '' | ||
let body = '' | ||
|
||
https.get(url.href, function (response) { | ||
var statusCode | ||
https.get(url.href, function (response) { | ||
if (!response || 200 !== response.statusCode) { | ||
const statusCode = response ? response.statusCode : 0 | ||
return callback('Failed to download certificate at: ' + url.href + '. Response code: ' + statusCode) | ||
} | ||
|
||
if (!response || 200 !== response.statusCode) { | ||
statusCode = response ? response.statusCode : 0 | ||
return callback('Failed to download certificate at: ' + url.href + '. Response code: ' + statusCode) | ||
} | ||
response.setEncoding('utf8') | ||
response.on('data', function (chunk) { | ||
body += chunk | ||
}) | ||
|
||
response.setEncoding('utf8') | ||
response.on('data', function (chunk) { | ||
body += chunk | ||
response.on('end', function () { | ||
cache[url.href] = body | ||
callback(undefined, body, servedFromCache) | ||
}) | ||
}) | ||
response.on('end', function () { | ||
cache[url.href] = body | ||
callback(undefined, body, servedFromCache) | ||
.on('error', function (er) { | ||
callback('Failed to download certificate at: ' + url.href +'. Error: ' + er) | ||
}) | ||
}) | ||
.on('error', function(er) { | ||
callback('Failed to download certificate at: ' + url.href +'. Error: ' + er) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,108 +1,107 @@ | ||
'use strict' | ||
import crypto from 'crypto' | ||
import fetchCert from './fetch-cert.js' | ||
import url from 'url' | ||
import validateCert from './validate-cert.js' | ||
import validateCertUri from './validate-cert-uri.js' | ||
import validator from 'validator' | ||
|
||
var crypto = require('crypto') | ||
var fetchCert = require('./fetch-cert') | ||
var url = require('url') | ||
var validateCert = require('./validate-cert') | ||
var validateCertUri = require('./validate-cert-uri') | ||
var validator = require('validator') | ||
|
||
const TIMESTAMP_TOLERANCE = 150 | ||
const SIGNATURE_FORMAT = 'base64' | ||
|
||
// constants | ||
var TIMESTAMP_TOLERANCE = 150 | ||
var SIGNATURE_FORMAT = 'base64' | ||
|
||
function getCert (cert_url, callback) { | ||
var options = { url: url.parse(cert_url) } | ||
var result = validateCertUri(options.url) | ||
if (result !== true) | ||
return process.nextTick(callback, result) | ||
const options = { url: url.parse(cert_url) } | ||
const result = validateCertUri(options.url) | ||
if (result !== true) | ||
return process.nextTick(callback, result) | ||
|
||
fetchCert(options, function (er, pem_cert) { | ||
if (er) | ||
return callback(er) | ||
fetchCert(options, function (er, pem_cert) { | ||
if (er) | ||
return callback(er) | ||
|
||
er = validateCert(pem_cert) | ||
if (er) | ||
return callback(er) | ||
er = validateCert(pem_cert) | ||
if (er) | ||
return callback(er) | ||
|
||
callback(er, pem_cert) | ||
}) | ||
callback(er, pem_cert) | ||
}) | ||
} | ||
|
||
|
||
// returns true if the signature for the request body is valid, false otherwise | ||
function isValidSignature (pem_cert, signature, requestBody) { | ||
var verifier = crypto.createVerify('RSA-SHA1') | ||
verifier.update(requestBody, 'utf8') | ||
return verifier.verify(pem_cert, signature, SIGNATURE_FORMAT) | ||
const verifier = crypto.createVerify('RSA-SHA1') | ||
verifier.update(requestBody, 'utf8') | ||
return verifier.verify(pem_cert, signature, SIGNATURE_FORMAT) | ||
} | ||
|
||
|
||
// determine if a timestamp is valid for a given request with a tolerance of | ||
// TIMESTAMP_TOLERANCE seconds | ||
// returns undefined if valid, or an error string otherwise | ||
function validateTimestamp (requestBody) { | ||
var d, e, error, now, oldestTime, request_json | ||
try { | ||
request_json = JSON.parse(requestBody) | ||
} catch (error) { | ||
e = error | ||
return 'request body invalid json' | ||
} | ||
if (!(request_json.request && request_json.request.timestamp)) | ||
return 'Timestamp field not present in request' | ||
|
||
d = new Date(request_json.request.timestamp) | ||
now = new Date() | ||
oldestTime = now.getTime() - (TIMESTAMP_TOLERANCE * 1000) | ||
if (d.getTime() < oldestTime) | ||
return 'Request is from more than ' + TIMESTAMP_TOLERANCE + ' seconds ago' | ||
} | ||
let e, error, request_json | ||
|
||
try { | ||
request_json = JSON.parse(requestBody) | ||
} catch (error) { | ||
e = error | ||
return 'request body invalid json' | ||
} | ||
|
||
function verifier (cert_url, signature, requestBody, callback) { | ||
var er | ||
if (!(request_json.request && request_json.request.timestamp)) | ||
return 'Timestamp field not present in request' | ||
|
||
if(!cert_url) | ||
return process.nextTick(callback, 'missing certificate url') | ||
const d = new Date(request_json.request.timestamp) | ||
const now = new Date() | ||
const oldestTime = now.getTime() - (TIMESTAMP_TOLERANCE * 1000) | ||
|
||
if (!signature) | ||
return process.nextTick(callback, 'missing signature') | ||
if (d.getTime() < oldestTime) | ||
return 'Request is from more than ' + TIMESTAMP_TOLERANCE + ' seconds ago' | ||
} | ||
|
||
if (!requestBody) | ||
return process.nextTick(callback, 'missing request (certificate) body') | ||
|
||
if (!validator.isBase64(signature)) | ||
return process.nextTick(callback, 'invalid signature (not base64 encoded)') | ||
function verifier (cert_url, signature, requestBody, callback) { | ||
if (!cert_url) | ||
return process.nextTick(callback, 'missing certificate url') | ||
|
||
if (!signature) | ||
return process.nextTick(callback, 'missing signature') | ||
|
||
if (!requestBody) | ||
return process.nextTick(callback, 'missing request (certificate) body') | ||
|
||
er = validateTimestamp(requestBody) | ||
if (!validator.isBase64(signature)) | ||
return process.nextTick(callback, 'invalid signature (not base64 encoded)') | ||
|
||
if (er) | ||
return process.nextTick(callback, er) | ||
const er = validateTimestamp(requestBody) | ||
|
||
getCert(cert_url, function (er, pem_cert) { | ||
if (er) | ||
return callback(er) | ||
return process.nextTick(callback, er) | ||
|
||
if (!isValidSignature(pem_cert, signature, requestBody)) | ||
return callback('invalid signature') | ||
getCert(cert_url, function (er, pem_cert) { | ||
if (er) | ||
return callback(er) | ||
|
||
callback() | ||
}) | ||
if (!isValidSignature(pem_cert, signature, requestBody)) | ||
return callback('invalid signature') | ||
|
||
callback() | ||
}) | ||
} | ||
|
||
|
||
// certificate validator for amazon echo | ||
module.exports = function (cert_url, signature, requestBody, cb) { | ||
if(cb) | ||
return verifier(cert_url, signature, requestBody, cb) | ||
|
||
return new Promise(function( resolve, reject) { | ||
verifier(cert_url, signature, requestBody, function(er) { | ||
if(er) | ||
return reject(er) | ||
resolve() | ||
}) | ||
export default function alexaVerifier (cert_url, signature, requestBody, cb) { | ||
if (cb) | ||
return verifier(cert_url, signature, requestBody, cb) | ||
|
||
return new Promise(function (resolve, reject) { | ||
verifier(cert_url, signature, requestBody, function (er) { | ||
if (er) | ||
return reject(er) | ||
resolve() | ||
}) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.