Created
March 10, 2016 13:30
-
-
Save almet/f4fec4d259f320e52a64 to your computer and use it in GitHub Desktop.
Kinto signature validation in Firefox chrome.
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
Cu.import("resource://services-common/canonical-json.js"); | |
function mergeChanges(localRecords, changes) { | |
const records = {}; | |
localRecords.data.forEach(function(record) { | |
records[record.id] = record; | |
}); | |
// Apply remote changes in the "records" variable. | |
// All records that exists already are replaced by the version from the | |
// server. | |
changes.forEach(function(record) { | |
records[record.id] = record; | |
}); | |
// Filter out protected properties of the records. | |
return Object.keys(records).map(function(recordID){ | |
const newRecord = {}; | |
Object.keys(records[recordID]).forEach(function(key) { | |
if (key.indexOf("_") !== 0) { | |
newRecord[key] = records[recordID][key]; | |
} | |
}); | |
return newRecord; | |
}) | |
// Remove all deleted records. | |
.filter(function(record) { | |
return !(record.hasOwnProperty("deleted") && | |
record.deleted === true); | |
}); | |
} | |
function sortByID(a, b) { | |
return a.id - b.id; | |
if (a.id < b.id) | |
return -1; | |
if (a.id > b.id) | |
return 1; | |
return 0; | |
}; | |
function signatureVerifierFactory(collection) { | |
return function validateCollectionSignature(payload, collection) { | |
console.log("validate collection signature called"); | |
return collection.list() | |
.then(function(localRecords) { | |
// XXX payload.changes.changes? | |
var records = mergeChanges(localRecords, payload.changes.changes); | |
console.log("merged records", records); | |
return getCanonicalJSON(records, sortByID); | |
}) | |
.then(function(canonicalJSON) { | |
console.log("CanonicalJSON", canonicalJSON); | |
const collectionURL = collection.api.endpoints().collection( | |
collection._bucket, | |
collection.name | |
); | |
return fetch(collectionURL).then(function(resp) { | |
return resp.json(); | |
}) | |
.then(function(json) { | |
console.log("json", json); | |
return json.data; | |
}) | |
.then(function(data) { | |
// XXX Use the NSS exposed code to do the verification. | |
return verifySignature(data.publicKey, data.signature, canonicalJSON); | |
}); | |
}).then(function(validated) { | |
console.log("verified", validated); | |
// In case the hash is valid, we don't want to alter the payload, | |
// so just return the same payload we've got in the input. | |
return payload; | |
}); | |
} | |
} | |
function kintoStuff() { | |
Cu.import("resource://services-common/moz-kinto-client.js"); | |
Cu.import("resource://gre/modules/Task.jsm"); | |
let Kinto = loadKinto(); | |
let FirefoxAdapter = Kinto.adapters.FirefoxAdapter; | |
let certList = Cc["@mozilla.org/security/certblocklist;1"] | |
.getService(Ci.nsICertBlocklist); | |
// Future blocklist clients can extract the sync-if-stale logic. For | |
// now, since this is currently the only client, we'll do this here. | |
let config = { | |
remote: "https://firefox.settings.services.mozilla.com/v1", | |
bucket: "blocklists", | |
adapter: FirefoxAdapter, | |
}; | |
let db = new Kinto(config); | |
let collectionName = "certificates"; | |
let blocklist = db.collection(collectionName, { | |
"hooks": { | |
"incoming-changes": [signatureVerifierFactory(collectionName)] | |
} | |
}); | |
return Task.spawn(function* () { | |
try { | |
yield blocklist.db.open(); | |
// do your kinto operations here | |
yield blocklist.sync(); | |
} finally { | |
} | |
}); | |
} | |
kintoStuff().then(() => { | |
console.log("done!") | |
dump("all done!"); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment