diff --git a/server/router/index.js b/server/router/index.js index 9bdeaf1..789e0bc 100644 --- a/server/router/index.js +++ b/server/router/index.js @@ -19,6 +19,14 @@ module.exports = function (options) { }) }); + router.route('/bsides') + .get(function(request, response, next) { + response.render("bsides", { + user: request.user, + pageTitle: "HDAuth - Bsides 2019" + }) + }); + // TODO: load child routers automatically var accountRouter = require('./account/index.js')(options); var xpubAuth = require('./xpub-auth/index.js')(options); diff --git a/server/static/css/jquery.json-viewer.css b/server/static/css/jquery.json-viewer.css new file mode 100644 index 0000000..57aa450 --- /dev/null +++ b/server/static/css/jquery.json-viewer.css @@ -0,0 +1,57 @@ +/* Root element */ +.json-document { + padding: 1em 2em; +} + +/* Syntax highlighting for JSON objects */ +ul.json-dict, ol.json-array { + list-style-type: none; + margin: 0 0 0 1px; + border-left: 1px dotted #ccc; + padding-left: 2em; +} +.json-string { + color: #0B7500; +} +.json-literal { + color: #1A01CC; + font-weight: bold; +} + +/* Toggle button */ +a.json-toggle { + position: relative; + color: inherit; + text-decoration: none; +} +a.json-toggle:focus { + outline: none; +} +a.json-toggle:before { + font-size: 1.1em; + color: #c0c0c0; + content: "\25BC"; /* down arrow */ + position: absolute; + display: inline-block; + width: 1em; + text-align: center; + line-height: 1em; + left: -1.2em; +} +a.json-toggle:hover:before { + color: #aaa; +} +a.json-toggle.collapsed:before { + /* Use rotated down arrow, prevents right arrow appearing smaller than down arrow in some browsers */ + transform: rotate(-90deg); +} + +/* Collapsable placeholder links */ +a.json-placeholder { + color: #aaa; + padding: 0 1em; + text-decoration: none; +} +a.json-placeholder:hover { + text-decoration: underline; +} diff --git a/server/static/hd-auth.json b/server/static/hd-auth.json new file mode 100644 index 0000000..2809862 --- /dev/null +++ b/server/static/hd-auth.json @@ -0,0 +1,90 @@ +{ + "who?": { + "name": "Kgothatso", + "surname": "Ngako", + "twitter": "@440UrPp" + }, + "what?": { + "title": "Hierarchically Deterministic Authentication", + "background": [ + { + "cryptography": [ + "https://people.xiph.org/~greg/gmaxwell_sfbitcoin_2015_04_20.pdf#page=28" + ], + "defintion": [ + "Cryptography is information bending." + ] + }, + "Symmetric Cryptography", + "Asymmetric Cryptography", + "Bitcoin", + "Bitcoin Improvement Proposals", + "BIP 39", + "BIP 32", + "https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch05.asciidoc", + "Signatures" + ] + }, + "how?": { + "service": { + "setup": [ + "create a wallet using a random mnemonic seed", + "generate a hardened xpub to use as service 'identity'.", + "generate server xpubs derived from service xpub derivation path", + "keep mnemonic seed secure" + ], + "server": [ + "gets a hardened xpriv from the service.", + "signs all messages it produces on behalf of the service using it's assigned xpriv", + "verifies that all signed client requests were signed with the clients xpub", + "keep xpriv secure" + ] + }, + "user": [ + "creates a wallet using mnemonic seed", + "generates an xpub using a random derivation path on the master key from seed", + "registers with a service using the xpub as their ID", + "keep wallet secure" + ] + }, + "where?": [ + "hd-auth-wallet", + "auth.sigidli.com" + ], + "why?": { + "1": [ + "Service Access Keys but decentralized." + ], + "2": { + "Crypto stands for cryptography": [ + "because cryptocurrencies are in your face" + ] + }, + "3": [ + "Mutual Authentication" + ], + "4": [ + "Phone + Wallet + Keys" + ], + "5": [ + "Have you been pawned?" + ], + "6": [ + "explorerzydxu5ecjrkwceayqybizmpjjznk5izmitf2modhcusuqlid.onion" + ], + "7": [ + "Oauth? Federation?" + ], + "8": [ + "Deep fakes", + "photoshop social media posts" + ] + }, + "when?": [ + "When do you find out that a site has been storing passwords insecurely", + "When will you know when a cryptographic operation becomes insecure?" + ], + "but_really_how?": [ + "https://code.sigidli.com/hd-auth" + ] +} \ No newline at end of file diff --git a/server/static/img/bsides.png b/server/static/img/bsides.png new file mode 100644 index 0000000..3fcf802 Binary files /dev/null and b/server/static/img/bsides.png differ diff --git a/server/static/js/jquery.json-viewer.js b/server/static/js/jquery.json-viewer.js new file mode 100644 index 0000000..611411b --- /dev/null +++ b/server/static/js/jquery.json-viewer.js @@ -0,0 +1,158 @@ +/** + * jQuery json-viewer + * @author: Alexandre Bodelot + * @link: https://github.com/abodelot/jquery.json-viewer + */ +(function($) { + + /** + * Check if arg is either an array with at least 1 element, or a dict with at least 1 key + * @return boolean + */ + function isCollapsable(arg) { + return arg instanceof Object && Object.keys(arg).length > 0; + } + + /** + * Check if a string represents a valid url + * @return boolean + */ + function isUrl(string) { + var urlRegexp = /^(https?:\/\/|ftps?:\/\/)?([a-z0-9%-]+\.){1,}([a-z0-9-]+)?(:(\d{1,5}))?(\/([a-z0-9\-._~:/?#[\]@!$&'()*+,;=%]+)?)?$/i; + return urlRegexp.test(string); + } + + /** + * Transform a json object into html representation + * @return string + */ + function json2html(json, options) { + var html = ''; + if (typeof json === 'string') { + // Escape tags and quotes + json = json + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/'/g, ''') + .replace(/"/g, '"'); + + if (options.withLinks && isUrl(json)) { + html += '' + json + ''; + } else { + // Escape double quotes in the rendered non-URL string. + json = json.replace(/"/g, '\\"'); + html += '"' + json + '"'; + } + } else if (typeof json === 'number') { + html += '' + json + ''; + } else if (typeof json === 'boolean') { + html += '' + json + ''; + } else if (json === null) { + html += 'null'; + } else if (json instanceof Array) { + if (json.length > 0) { + html += '[
    '; + for (var i = 0; i < json.length; ++i) { + html += '
  1. '; + // Add toggle button if item is collapsable + if (isCollapsable(json[i])) { + html += ''; + } + html += json2html(json[i], options); + // Add comma if item is not last + if (i < json.length - 1) { + html += ','; + } + html += '
  2. '; + } + html += '
]'; + } else { + html += '[]'; + } + } else if (typeof json === 'object') { + var keyCount = Object.keys(json).length; + if (keyCount > 0) { + html += '{}'; + } else { + html += '{}'; + } + } + return html; + } + + /** + * jQuery plugin method + * @param json: a javascript object + * @param options: an optional options hash + */ + $.fn.jsonViewer = function(json, options) { + // Merge user options with default options + options = Object.assign({}, { + collapsed: false, + rootCollapsable: true, + withQuotes: false, + withLinks: true + }, options); + + // jQuery chaining + return this.each(function() { + + // Transform to HTML + var html = json2html(json, options); + if (options.rootCollapsable && isCollapsable(json)) { + html = '' + html; + } + + // Insert HTML in target DOM element + $(this).html(html); + $(this).addClass('json-document'); + + // Bind click on toggle buttons + $(this).off('click'); + $(this).on('click', 'a.json-toggle', function() { + var target = $(this).toggleClass('collapsed').siblings('ul.json-dict, ol.json-array'); + target.toggle(); + if (target.is(':visible')) { + target.siblings('.json-placeholder').remove(); + } else { + var count = target.children('li').length; + var placeholder = count + (count > 1 ? ' items' : ' item'); + target.after('' + placeholder + ''); + } + return false; + }); + + // Simulate click on toggle button when placeholder is clicked + $(this).on('click', 'a.json-placeholder', function() { + $(this).siblings('a.json-toggle').click(); + return false; + }); + + if (options.collapsed == true) { + // Trigger click to collapse all nodes + $(this).find('a.json-toggle').click(); + } + }); + }; +})(jQuery); diff --git a/server/views/bsides.pug b/server/views/bsides.pug new file mode 100644 index 0000000..772d745 --- /dev/null +++ b/server/views/bsides.pug @@ -0,0 +1,24 @@ +extend templates/layout.pug + +block content + .container + .center + figure + img.response-img(src="static/img/bsides.png", alt="bsides cpt 2019") + figcaption as seen at b-sides Cape Town 2019 + .row + .col.s12 + pre#json-renderer + .col.s12 + .center + p.flow-text view annoted raw json + a(href="static/hd-auth.json") here + + +block additionalScripts + script(src="static/js/jquery.json-viewer.js") + script + include ./js/bsides.js + +block additionalStyle + link(rel="stylesheet", href="static/css/jquery.json-viewer.css") \ No newline at end of file diff --git a/server/views/home.pug b/server/views/home.pug index ee8306c..22c7109 100644 --- a/server/views/home.pug +++ b/server/views/home.pug @@ -8,4 +8,8 @@ block content p.flow-text Hello #{user.displayName} h3 Hierarchically Deterministic Authentication p.flow-text Using digital signatures for a challenge response authentication mechanism. - \ No newline at end of file + + a.btn.blue(href="/bsides") Learn More + + .row + .col.s12 \ No newline at end of file diff --git a/server/views/js/bsides.js b/server/views/js/bsides.js new file mode 100644 index 0000000..f94b259 --- /dev/null +++ b/server/views/js/bsides.js @@ -0,0 +1,94 @@ +$(document).ready(function (){ + console.log("########"); + + $("#json-renderer").jsonViewer({ + "who?": { + "name": "Kgothatso", + "surname": "Ngako", + "twitter": "@440UrPp" + }, + "what?": { + "title": "Hierarchically Deterministic Authentication", + "background": [ + { + "cryptography": [ + "https://people.xiph.org/~greg/gmaxwell_sfbitcoin_2015_04_20.pdf#page=28" + ], + "defintion": [ + "Cryptography is information bending." + ] + }, + "Symmetric Cryptography", + "Asymmetric Cryptography", + "Bitcoin", + "Bitcoin Improvement Proposals", + "BIP 39", + "BIP 32", + "https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch05.asciidoc", + "Signatures" + ] + }, + "where?": [ + "https://auth.sigidli.com", + "https://code.sigidli.com/hd-auth/hd-auth-wallet" + ], + "how?": { + "service": { + "setup": [ + "create a wallet using a random mnemonic seed", + "generate a hardened xpub to use as service 'identity'.", + "generate server xpubs derived from service xpub derivation path", + "keep mnemonic seed secure" + ], + "server": [ + "gets a hardened xpriv from the service.", + "signs all messages it produces on behalf of the service using it's assigned xpriv", + "verifies that all signed client requests were signed with the clients xpub", + "keep xpriv secure" + ] + }, + "user": [ + "creates a wallet using mnemonic seed", + "generates an xpub using a random derivation path on the master key from seed", + "registers with a service using the xpub as their ID", + "keep wallet secure" + ] + }, + "why?": { + "1": [ + "Service Access Keys but decentralized." + ], + "2": { + "Crypto stands for cryptography": [ + "because cryptocurrencies are in your face" + ] + }, + "3": [ + "Mutual Authentication" + ], + "4": [ + "Phone + Wallet + Keys" + ], + "5": [ + "Have you been pawned?" + ], + "6": [ + "explorerzydxu5ecjrkwceayqybizmpjjznk5izmitf2modhcusuqlid.onion" + ], + "7": [ + "Oauth? Federation?" + ], + "8": [ + "Deep fakes", + "photoshop social media posts" + ] + }, + "when?": [ + "When do you find out that a site has been storing passwords insecurely", + "When will you know when a cryptographic operation becomes insecure?" + ], + "but_really_how?": [ + "https://code.sigidli.com/hd-auth" + ] + }, {rootCollapsable: false, collapsed: true, withLinks: true}) +}) \ No newline at end of file diff --git a/server/views/templates/layout.pug b/server/views/templates/layout.pug index 259e608..0a7d3e7 100644 --- a/server/views/templates/layout.pug +++ b/server/views/templates/layout.pug @@ -44,7 +44,7 @@ html(lang="en" dir="ltr") header(role="banner") block navigation - nav + nav.blue.darken-4 .nav-wrapper a.brand-logo.center HD-Auth ul.left @@ -63,18 +63,20 @@ html(lang="en" dir="ltr") block footer - footer.brand-colour.page-footer(role="footer") + footer.blue.darken-4.page-footer(role="footer") .container .row .col.s12 - p Links + p.flow-text Links ul li - a.grey-text.text-lighten-3(href="https://code.sigidli.com/hd-auth/") Code + a.white-text(href="bsides") b-sides Capetown 2019 li - a.grey-text.text-lighten-3(href="bitcoin:1GShZrpSK6LJZRDCSNcZhEiHcLV916afoX") Donate to 1GShZrpSK6LJZRDCSNcZhEiHcLV916afoX + a.white-text(href="https://code.sigidli.com/hd-auth/") Code li - a.grey-text.text-lighten-3(href="http://xpub6CmUNwicBT2i7voSgpZJrJmr4nU77SsFd5UiKoMxiqpzWTtebwukbziMDsD3FNozPmS2Qb7sRSGzW2VgTkHYwnqAod16w81X44H145ovt5Y.onion") onion v4? + a.white-text(href="bitcoin:1GShZrpSK6LJZRDCSNcZhEiHcLV916afoX") Donate to 1GShZrpSK6LJZRDCSNcZhEiHcLV916afoX + li + a.white-text(href="http://xpub6CmUNwicBT2i7voSgpZJrJmr4nU77SsFd5UiKoMxiqpzWTtebwukbziMDsD3FNozPmS2Qb7sRSGzW2VgTkHYwnqAod16w81X44H145ovt5Y.onion") onion v4? .footer-copyright .container