From ebb36c954e18d72cbd99afa95d5de1d7dbe290df Mon Sep 17 00:00:00 2001 From: Kgothatso Date: Sat, 7 Dec 2019 21:22:38 +0200 Subject: [PATCH] Adding bsides slides --- server/router/index.js | 8 ++ server/static/css/jquery.json-viewer.css | 57 ++++++++ server/static/hd-auth.json | 90 +++++++++++++ server/static/img/bsides.png | Bin 0 -> 46759 bytes server/static/js/jquery.json-viewer.js | 158 +++++++++++++++++++++++ server/views/bsides.pug | 24 ++++ server/views/home.pug | 6 +- server/views/js/bsides.js | 94 ++++++++++++++ server/views/templates/layout.pug | 14 +- 9 files changed, 444 insertions(+), 7 deletions(-) create mode 100644 server/static/css/jquery.json-viewer.css create mode 100644 server/static/hd-auth.json create mode 100644 server/static/img/bsides.png create mode 100644 server/static/js/jquery.json-viewer.js create mode 100644 server/views/bsides.pug create mode 100644 server/views/js/bsides.js 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 0000000000000000000000000000000000000000..3fcf8022adedd2281637a2604d609062277ec0d4 GIT binary patch literal 46759 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 jXwymE zA{(ACslfFfb+X53W8o0AJLb-J*3JMO6~0S?-fe-$IT+;|_8oU4#?~zoyiYid@b>X{oMIkp;Peux! zT}%J6Jjo$zY+Z7$0b$Gi3WDz?Fatyq6N9|1;mKBn9$#AOnh+pmm`8d z(-PKw0yY;GJ2@*-Uz0C37E=3sgaW~Nn+nDq$?&GKZ_t_zw6fZ|M@?d5^E#5v*QD}p zk`Oz-m6wKKfVH~NhF;0a`@GBjW;^|75lj3w<4z#~-$GpsrJ}{S!9T&xj3!7=R&Gyz zJJveta6Q@jV<^~mG=*a%RwOoBoWGuTJ?^dUyE|Y7g&Q1IhwR6hI2nU$5RT!;c})(X z%IN_1{qV;V);;1B`U>9yId=#B`te$bR^qFcQ({LA^@zcTpFgQrT@=2MXhZ*k7p`34 zdcH(TT)SIWxVumdI^kh)Qj9Zj(0z^+CVuC z$-Vf^ArkgG_H5aBc_}Abaa#LzP$)Zb=;pLuu-&8hJBP@MtK~6W$UlrQ^GgDXBX@V3 z^_Ns^1h_7OnW(z7k6>+v^wHD8PZZAU6@CLHpiujw<}N$`@PYCY&>cdd(0m+ zZTP-QI{3neP=?&)vXhoWx><8)CF&s_j{I28mZx6pud~y1L*cWyus&npO&4<{K=QgP zl-tg4f8BU^u}+sFgr52f-D$|SwG)*da5dBQC$3NsjZ}Ag?e%fCCflZQu3<-9RBoKT1qQ6CrvccmvV*Aks?YgvU7x&G00>uE;07MDYcM> zQlOQJmFW7WjzS+_oPhaZvW8Wk#s#;O7GeBgu=lsB*IINbA9wxXZ^}#XJ4yvxzrmuM*PEeKnnPik&TYv?mF$7!oUaS5n2VAvo39PIp-ic;Yb}|Kz z_jP~%9#CW2VnSDgxa73c$x#<*E>5?_(4I7?Y?vsyZ9O$JS3i}^`)07Gr~9Y31$R;9 zQpvDeqrJD~@!#mM9sN|L5t=KZI{2rB8Yl{;8$I6HY-P_F77IuXYkLLjvzcG4DNQya z-*~1=j@t-8?g!j;?Cee24fpwP<>inY+*6{f0FlCc7`xy$`QDV8yVUS4jce??O;PW0 z@9?1}sh?uzpI*}Ix-5_B+cG?*lKbz*-6vY79X#i z1}R*c>7TkPdl<2VI6afZ+x|GM-kvl+XGPMdyRpZyQ=hzv_J?faY$kR}tWkzQp@v^O zfjX#@HNtu;B$n}nY7QU4XisaOqMLezn(3&srE{0vTsI;tx*w|ZgHp__7Jd^Qa0GKr zR29nTR;g;$t=AYVm9%JGjhPP3_gyZ8#G###pv0V!S=z9s;;gGYO%eUDQ(sKUwACYO zd>!Ys@Y?2lHn229n$}6W#JkIrw1enkTHGbm!x zzWZ6E$mIlG{mc=p(j0#}tWmj6v^|n5pqebSYF1~c(o*EYzv z&cj7D(8vRIKP!Wyl>y0&-N<=b1Z=UUpvOUeHfc;P$=vRI@wuGi zo%vV4QINNia^aAc@=ja1HvurkOB8ORbZ?TXD~)|irvLGybgG8PjcE<)$AD74TBdl&tO3zcp#kA zIu8)GHZNJD8yLr9a*hiBT}(Tz>qH0)7yb>YfTp_K! zIEDy1Q^V)x6VY{eBio3m6u_L%{t!=~4f9E9{~ibt>Sz|DrNoZ>EU-$S&M!jpPd_5{ z=$pXbuxe-gV=g#7NL*H=)p(rc5ExiNIOAn2U-8VaQ z(bL1ba;Ao&YU@td(we+KzJIHe%bkZI9LkWs%h0&5D5XKgSryoZsO`ckDmxSvak_PY zuUMS^*SA`!K)R-9tbIP<{R=|zi1yZQx{rDk=V_ii9n z{$ZV4HqT$-SWCshu$!`J9u43#)h-m+c24U8B3s%~qU{LFfzRB)MX|;DGh;aFIhdyP z1l~D@-=^h8P$(e29V~A$Z5~H(Fu@`M0(H&PkUbU#w@apn!pfN5x`JUqutJ!k?C@Li$~YJo;w+<}C`q)RIkCdIXTx1V_b`2==6`|q7Y zIrU4ZnVIs*mmH3<6m@MLAT!$hs<0q%p9zv@d*Uo# zu=DZ!b3?d_Q5j*3*9i5TX*Nwa1p^m#=B#x5gK0&%=86DGw(X=K(BE@?s{|BL{dKWpyQ#zkF}$(sEEy8>2Fx>s z1%8W`%v}*^UEyz92t_E5LOxUPdkB?A5fCWP&$E+lyVB#V`6a2&y(wdQidz@uKpE)XH*JxcACE8AIx_fx+ z*iJ3g2AKZ3V5=RWa3sTjoIIq}=~d&?>DS_EYm|mJ0=OoFQ&o>AJBqUI9ckCo%$Wl9 zYV>s^HYB1^c6>#+a}B?_C5LjwuwrXpxm6GwN;5y-Km;h7#d9IuI+i^W{sevIxA$s$ z*VgI7E!p>unvs=iU!Rp?-;U0ik49Lbk+L(R6YoREJ1-6NI+Li-aNR-X0tR2kbtyYu z3_IS^-%kb!k)$d+Dbg#?){N59;#tJ$>6LcSCJwk+}%vFYP3>LvveRob?KnNLp^jx@JC%0;0kd zX{7}~H`-bJt;&$kn0}+sB_#i1VR4%rEuZoX-}Bs=L%51^0vO|AxC~2$Zwh>SfeK2= zqS1>}$MzB)0)FCAxxm5}UOBl}TfZZ7LKmD!wx6Ljl9giHg7j`j_^M1)y6OvtBVn=5 z(T3@wT+gyp_YGIqH)sc9QILP`i3-o2H=rY@?+c*`)UFMnY~+K5gF1HpfxU0?XU~t_ zw|>dEZNQGk#JU&9?c5L*ws})b_-7lIhHc^BxWC=?&eE_iHb#YQ+!P!B>B@1v5`Sdx z$Fmej9{H^skr=m%zd@}Cg!eo^p)lNVj~$%x3B#%@p_6j~8x&))f?Uja$%t-2CCeSV z$XIAGuu)~j(LZe8mb=>d`v+ zhGuNQGN?^vTa;iszk6oL;?{vY6RLU(LTSLSTlzdyoM=B^O93Ge<{53dl)v1uY0Evs zheALY>#-6A=mHCE?{>s_yp~o=U7#3Tg$_?LA#dk&0l_$ES$ru9i#D#HzHz;80Pm~vly4Pu=2?DnrE`~L4%zcWvu6Ln z#rO7}ZGDf<84&}E@(ML|Jr4Ky8wx7jwA2e(@31m|%d%AW4c7`_KcfqlzfY$)Xidx< z)v-lOWVF`xe>2h7VKtZ$nFkw8dn1EyXdryG<148~0ig>4PPgNfM_$>nsr^+bx48p4 zv~+fBeG4py1tqDDgJ?vTG83(b$?!8`EMFQM8iB@{2SM?7?wHGgRdi4e{;93i)qB^_ zaQEfD8u=@{_dXe#x^H+#8)W0m3}|r)qkE|J5>;9cY|zLH^Wh_7WMFz=)~eI1aBG4# z+X_rRFV1#;-LxPz8Nk=ff-uC%vr%3wO|a4J>FTUs0aRQS1O}O7?wZJ7aJ+(=Gz9TF zf`U0C!J3&JYdu$*VAmKpKp{b4TD;70;K|`#WP5qKNFb7H%Ot=U+xVS*V5|l4ZOB?? z-^hilDqTQr%SPG++m%~53bhGO-lM|8a$uNl&yBc7%SXmgQta#Xywy1VfTtoH_&a^x z$fXbtSKX8pUXAVih5@X-O9x&IFF%&-DE|EJ;j*1R@>?S>sYEO!G8JfRT>TpG6@qb^ z-B;jq`p>FlB3~1!M%BlRxib!9^8-$wOMRdp_FnZ3eUWp7z2QmxqET^Nt02L4^60#g z>S$BbHl@cYY1uTAKo`BGz{_1 zpc@E+>Zl=o#8sqAW@Q09w}n=NS$&n!GNQoI@2O|5tF$vH6NdW={9b|2Xr*Ms%Kc0B za{Fh9zkuzR?U?sz|U+&>!7M z#557qH0J{J^U;*&k(&{~b7oAxE zw7h2Nef!0S#@(C0!trTAvi(S2oR!n#*np&C!D6^fZ6BR=k5~XNM}9~_p?7jx2-n!* zj5LB^Ver{;))POp_mi#95pZ>k()V3QKVPn7)yE%L8DyW}qzJ!a>O;Kg6WMSONB!MZai-g@%Xa%c9lA>G1S`1#V+ z^3L}WX2r$#c$;X5~i+?6P%+0Aq*PK6u-$-#T};J zb%V+qA(oT)-J!hb_vprCyQ{Vym_D(tU}fd5cK(6slk~7XBRsCl;En*W3?E_s$o!E( zX=CohwucAOKKIWGomCKLyTs|SS(?E4ss#j5Rokuvq)!$S!>YVguyE88$q@2Voif%K z#K@@KH6+MzYi|P8OzaRUe1d;BL}4+ELBM<*2Dq##?g`zG6NKirGl|VF6sDC2$}* zqNq)PUk8R+6_e!N1iZd(>D#Vknf-_!r_q9_l)rjFW?3QqMt5CRFqW+mGA6*qiTPk+ znMteLpp;=jM*F=zV*o55j<{|#G`$yEPF-Da-Y?8ve1m3C>vHp_HxH3Icp;S zCv%y7qpSdq<9Qp_lZHmE)*f7?n?O3AAuPjh7Z^7?SkW@ap;sb$2k`813J9jZDq+Hg@8Df7Go)e21lVJj6-)*@K7iU2)e_V=L+s1rj_FlV4j!P-xU&E6;6OA2yF^IGIWEcO+liMVO`>T+T;hv-yk&T(j?y;h04v2nl|^;90&DQviBxAg+Mt}1Qk8%}@(BDEkiJL;PWKNW$_wuUt~vxv!>9@T7GYk^j%E_ZBsI=CzAnPZam;c>Ml z)u^~>6eTgWlJNjF=K8=1@Vo}j-DMp0$rLNt_&ujnQq$)`q7a}rAdEsMzFTc)F(LI$ zGZUsx6ZTg3`}#8q6IvNV0iF^4wAp(Eo^jz^7r;e`kan@ejSfG)ILTh3U0gK+3L z`(}mSlbLMaE{p<=4$rD<*nBRtd@_=4TQU-?M+@Surwdm&HWn-xH3iz|;|Oy{TAVc- z;h$%tX5;2}=%6(DD==ge&|)diLdSnKqBrZAd8n~&XfDL7EMwl*yC9Mj^foIpUh9&wQCo0Hz z0M~J73*d55U$P(&-<(H!G=`{!agp^z3xw{V98T?B?)WbS3BRR}5FwE-0SpKS?so$bh;5(KX z1%j-u#^2>dan^F~HeDERy~=Xc`xJ$Rx=P*iTfUFqHG=Qr+pAd+W(CXayPpZ}Dwc9} zR#Ib;Xdj?PJAq9PpN*51Ra;U8!f*QkcU2L`bHF%2ZLP~jQJeVqt}tpK$Se*|f$zBw zJU8ANVe*XWR2`X?16#1o8G%7CH zCj)0k024lwmtZUU*OZ}2A59(-@sBA(?fc>_+jCPL8;TZ=?w>n<>CRjdanz=ZQdEoErNcWctvo2ol*hxl>u*p=Uqk}nd zeZxL77Ga3g#N({TM7w=8@&hs`yeo`_-*OCQ=gbhb6J~V+Ldtqmbl3)&HN|lcjTws7 zLcv6aCR(qqCG$C+nOYeXPUyIDHGs3Kc)iL&<@9)299KZWM+*tx8HKK5I1)DVFBY9a zJ9h&GH_PZ6>lRl52djByc^qFnI(BOBwk%s;PUB&I-ANyRka8+oIO={ayzBX6IJ_cn zOq(V&SSKm=?GzXk3@jsB3L-SX{4?S#C467cyD&r@TDe49E{MgNY}=kii)5wa?^!Dx z|Hw?SZ%U7`oWMI5U`3whcmNqJzh&L(VN?q!Q9KvF{F5c)^mcfCb3G#=+tTJHbZ^~L z1Qha!?}gE`40Ncnt`;mK{oC?_c-tlP)e;E2f?Z3)^7qAA_U=!#Y}g+ikw@zcD9w+z zox*#UwTTg0yT$hsryf7URds5NM;072t%WJ}!%qiykxl$iho(ZXu}KMtN$$+7A%Jjs zxIU>anNtj#Qz++|g>MGDt9C`Kl5tc)d|%RO7H(aE;J9-rH2}J;cxVm}7NSN+-;DT= z|2B2#?L`T;b7&anxk6O5HE7Pz_IC>d(-??iS```;!A3;}!p57MU@Q6O)S=IPe)sU8 zzurE?wW(f9f8T%>{=Ti=kL=%e`}E-M|C&0q*Qa+3bL>asCNn_%m-sy!GMNXMo17J{ z!bjs4>w!CKu8HW)JjjW3TIki2zM5G&E51LVYhM)@r!Y%xw##X1soAOa^uFL#jGC)#s+JFCCRcaFS+C_oa1|ukv%x_BP1j!5a{DKliM9i}=1j}Tm0t-T z`4a6s*|tZIQw`di)w8-s7o)g0zN|V43*f>sr0FQr zMW(OCt1%=pYUWcWAY6~vl_r)4wAzc@crYiymJ0@UpkSF}SALQ`Cm+fNa6-SH1cN*c zd0ME1Jcal9bcmAk}IrB#@&0jDoA!q)m8K2xS?796h5ovkxw&R6~^8NKN%yB{n z>QfvilE?JqVLTjPG0itf+9#~=+p}X~sc3z~*zQ!h(qiSbZP}AdezVTBHYY%NU*IZy z{4W06?L(g2Ju{@os<2+IQRdCt1p0H9reART=FQhl3+e#$`_COiEwFOqAvALG;;j%C z)+=l$>_b#k5T_CpgextqTe`uDlI@v~59>0R>2K;+W&RqSls0>Z8FQ;I5UxvG)~}ut zE0*5`n1x#t@ST-`fIMPgIx#-J-{1%BBTSB4%mNky+L3|KzR_(dB>c9X(@pJG4IT?{{~{pM{j^4=jY$-zIMRMIX<)w&O=aO##{DuYY`yA59u(iV{};NPdZl7 zO6OAMytn73*jQ`SQAVY>RFXbb(*fM z2?4XE;z2THB#MFF(xc6o{3IJU8{D6>+W7~rhsj+N`Ev-gPcjm1hxRTFFHDEP$cnMD z+*SQZT&OS6pefu7mOD0)L4vt=+;CS=_w{!LbpyHrU37HTue`@+J%Ro}KfK@V(>sTC z+BQA7E0mOuy;}wbbZ!>V>d&_g>9li3NLM`ThIjZ~mG}hj?4L8D^Rpq{Of3fz88)wj z+B9vQn`+;b6RVXK^TB*c|I!B4#gaokZ5CloHyZ>z6%@9I1G7WN0`2zB3R#-J%)Wc+ z$nKo1A_S!ijgJk`$Cp?474EG9{QP^i2yFAW$wT^WpAj6tH!7kqC(e2Xf>>q&qL0Z{ zFK4~3Bg!c(pB&zWlVijR_QXnW3}U1z;_sR+ZK#Hl3D{y^RuG8bB4!tMj{=R%mmjf(6F?lH>lnh~9&a%pEZfjO=Mz zKw??E97%@!ewMz9oplL_RUz?e77YdCS;e^YXXhz!aFyw%!q~L*bFmm*ie;tC92xfx z>>%x3%~moJ%3nMMbNY9=s3qbxUC9Zl85Jv;E|eQmGW8}LRq=$3yO>{(nfgPmOLedDST&K=avJ~ zV=X74m0!b^lL+WSyrKryk-q}He7Rs$+^PVDINgmXbL)xpIBP-a;?WPMj_uikLI6)6b{DcVP8^z$HY>5&;{IgWO5I6Ge3{|xwC(fpq+Ukv>TO4 zu?P`pgO`n`q#|x=#?0yqgqx@Z?{Z^#N-S7Xq*=JN0m5JdW{2^lkok^OtXWtM0ffx~ zZ8WCqV-LTaI50E~=KhfwOKFa_!uIERZ;byDx5uDXg9e;~4q7S=RyTLipfq1P8af2Z zIcoiT;v%-U50uUqfCgNNNmNDbph$~YGyEHZ!f(ll?p@R7jd%(j>KM)4-1nw ze-=X69_K%PbdMg{^G60BO|gAO2A>^kJmVa!=oOJj0j*!i;H4S)ooBGd>CxeyhMq2N|)}(t|OUOfI%$ z8V<|~eF2*DJpdQejRY1RO|f&15pYxLQ&-rgnc$-_$pv?17M`|XTDj%7l zRI<{!NkTe$r3<g!b4#k z!z2X+dKgb*kxFnIGiFv_Alxu5c&(y5B$cL?W?|MA2uCy>P)&`A#OLy!Sy&APgfH7u zBeH;1%hZu$b5x-JsrK*~kng4y=DXb*Q+x7<^UC8VQwjzGLrq zPjRYaKUaR|#9FRU;OS<)f_t2W&=0>ZQVD1*0YR#*dr1{uXR|Qt0zEu-nwlCkpR4#EGz+UCfUsr5HIQ`VKi)Rz zDef!8fh%-Q7ju%vOB0vVJh|OKvTYaVtLOh<;u;8zH>pWx;n~q>%Xzw{{&4GHnGk?V zC6i*^D$T4`L=zeX!E%uD>fgF)`)(})Wbc=OZJO4p(V}zs{PEU7%}?GpW=wj5^&s*| zMo148sYEoUfT)eMWnn8!Hw&{aKv+zJ3b#7qbJdaS zJoZr&pwMx;Zj+{dzWzUP_HUk-Y(JuJnV}l2bb2(*^VF(2V8)Hzw1I1w#fi3~Iu6ml z&B4vARQuYDc_U~1$k9(`NRgWP`>_>Do>9@{670=2m4S;yS2i#O}8H_8(NV z%&|8u#=r47)^qAG%Az`ywp{^t4*nSxme4R=p;csdk$=Ceuxp_8OH zW8R26crZ^%iam28g zmCnug>!&gX8dg>#UST@Z`m`Iw2?G2^cQF~m(Bjgr>KVbf1pI~q`o!wU_0xK{6(Lm1 z%Nlr#%L>tD4L7^-gswQKGl1lvq*)}oI#HmL-)HDhG;g&uZo#vfFA8gxtq z;mJx%kP5#lV#ToY^V%q<%n@i;{TLZ%KybE3QIfsbWZI{8%9|z#c(D9#UeSmvXxVt@ zj6TEWSWcYvRBn>}@b7LJ^uRx-4h{L`#DT5aH03 z60IBC1j@-;uCU!n7mPk1P8#G_x+-!l%J&LSG2FQ%tY~j^L{?6`Hf@%1P(X<_#xVh| z9;UlXAF$K~MEU;Mh{GM4`ibyG*mWukMc^nRV4ex?*1mAT=;tyx01O7q_;6K>S&fls z%nI+Y4D`PV#kl1+-9~6fd2$U@j`;Ds(v$CCRoQCV3 zk0@s-F6%@nqYvuu$@V7)qax1iO0ax}e%m){WOucLF{h!@t;@b8);khgDG$|7mS*NFP)UX*?9HmiaBV{0P!sYh4Hp?Jh3l7(VqLqTL;B{FmYg0#N!LW z;bI!iU|gUR1+YPLMh5pRQr1R8l2JhXa>9W5GJ{FWYXt_S3qx*Gz7?JLAUiO%J$6(I z4X*4>Pp}?F-p+qKWr!NYtJ1_*O#B^3zd>M}MQISgi03kA;AnHvB@LpTi$KuEKx8#H zHOd3CLqiYF4s~$9A1;bIm|)r3F3?Xb(fSIAW}0>{ZSnN|V;4iS)s9=$>za8N<^-l? zEF%NT_)MUGLxx|HV7qefKy4fX0>ahrP|xxk7Q}2WF2nm37Rh-4zAH!0^6%64jlEX_ zZqlTA3qN0uzpxE87Q~IkEmNwhYcpco<`n`WI2*zN7Q|Hu;sVsM8t1B%N45o&`)08w zID=4|MJThy_zv?AL36Dr-gb@Cybjv^aqm$jvdn0WzM>YeG!dX?&CkzHtIzb4uEu$?J*JC zxMel+s>WKBpsOJ4jL-!~8uyjr@sfop_Jb%hZm&WzO&=Kv-3@lYWMh({Sd7?jbqD}8X|T|o<|1-pe+6|Tp{u@F5S z`Ek}OiwAd|MOvsgKht=flN`7CR>{Xd-k zi}rL8ZKxdW`C4I;y|5(JaVR^*w&Rbt4PN?cL~nI8sF9#pX#I;u7u%?Q|Ar@3$@iEs zv-&^}x3(kxs^G?&g;^Kq;W3{zRf-Z0rVHh8KL+67Xgh#Mrq)SVKtRYWCK8xkcQmjf zHw%K=BM6r)q&xV8S?v#6x$ZAtDwN38;jacDYTy*QQ>JEy#1fZ0keJ@ z**^r9hRa+Av7G#LS4h1YGCBfvBbKS(<`>3g!?Gz#PZTr1f~yQ*zL=2*WvIC5KqAcCiSg+I!e>iV*lsdTe5;j-9-aXzUd1%&aySX$oJp4h1cWtz!Km*4 zy<=D>SP-W1)rIKp<8?y!)*TBMj7nx*=?qM@0rgwlAclMH5LXnnTU|hi`$q|gK$Zl` zVd20IfhSf+e(E;Xe&*~y>sJ#82K~g@pVNUAK}Kks?%`Um{`FOm((osmF|+yrVR||^Y$Ro-HP{Jn zdU(_*YD$MNGG5KXQNVL9Vxf@WyYx%<2Y7%B{lBx#zA*x=gWqxt!gu3c!`l@l*$ZS0 zf{plkgKZE{`{Rabxi2~Y51o8VTCC+5;wqzGoeYKZ=ZliHV=|k#jwb{T+CYkE$$bl8)a3p z@$TVjiw)CsQ7GZ!^K3}hzzoDip#TP|7_ACZ#VNlLzS^IOg7r&i@7#=zXC7y874{d? zgIl!MR;SmdEmunjNYY=hVALek%_gpW$$M@5d$b&p4kff)b!mXg2O;+i0z$T)Py&K} zabEB4({4y%vYp}beO123FslQ1UZo4Jgp2EnUXJ`r@oVFM#dZtpO!nrYWk_whIKh4i zxLglt-!sfa`>~=FM;hZfy~3HXXiz7aHV-*nqvc`{5CgNI`9naIWyD%eP%tnbneno= zi0&rU=Tv!65Kwt>FMC&c@jD6%TA8wzg~!Ee@5>Rqbn~)2N>Da*ZNK7%1!;G2L2MAM^ii2vbPyYUB*?s2V){~ zP-e|21av`QN{CeAJ#+uqDM#b2nR*9yg$Gn9SH_39kD=_etrq~+2hVLj6curDQja#W z2_)k5q#b!m{0}FsOj#^lMe^{^*?VYQiVOtjG5I32s2g-x>n;5B-QcjeFUf; z4m)*Ch0i#N2HS@TVZ{U7gNc4&8RNlK7I+Es#D)8}e0Jxshf5M|=h2YVMq+jC!15g$ zKYi%?$!sVXz-S8f=h_}boUxH)+sgr9FrO?kPvA;gR76=?jOEzT1nU7<7H9WIg&&U_ z)jjs7&VDj82E;N{3Pp{?JSryss|f=V3gc}O2jkPzQwd0)b^r|o2hv#}E&*5p>}1Ch zY~@FitXoiU;Cto*LXT7G`n|~hLy8uTPR>lVua#L!$TKxRhAVN!Sxbch>)T1-9?MTO zN~RH=`dVSU^$IMjE&iOIiumd~KXl?M~3`>uTI;D(O0bY(Uf`psI_3-1Hs;sfMer1v}(ANDK!U6vJVJqrt>h~pp` zT!WKflZ`4VERLr-Gk!T?z>8}ldXFF3p@q13Rejw^qzb#EJA-Qo=wa8!f*`SSRk|ja zh3g6MEze$HIG$*I>Yc7;Vbv7~FIo#$h>OkG$R%$S5Y!wd_iEc>e{@7XwN+iiQ&0`n z*jPOV8tYl{w`$DK6ZaK6rF2?qJWLOn%83+5!MbTdNiT)Y|eYkmU1HlLVfc5>hA*6GZU;w>DrM!l9Fus^9FQ~U0n@Y zwg`$p-Zppvw+N@DQ7MkvgJHOsq5+(FS2+(R;CpDB+_Bhw^?Zf*m|o`p%0pqa%1Qpl zH6GOw8iAC-lR;euXHc+e;i+_+#%BU~k4g)tUyH(}xv6*po_vqITt-{k#kM8C(T39F zEXB0QIW2Z$isk2rldPNam)ZAZB--|6;T`6QR(nC5_3H7LB0oi29f$s<#sTSeYRGn0 zFH(${g&A$e>X`5#QOZYW*u*q@PNlO_JDVX^@lpzgWfC)n_fjo+*T8^7msGX~ASWk8oEKDRfP zLs0Ph%axHiKc6sQo|b&@;u@Hxz+`T{#Gtq2Y*%4%9#4PY929M{nCdG7J=!L$yG z_Re@?BEBqK?%4YAlp!2n5~;*%1Cq3F2#9c|FB3v6=OyQ#m_9Nh&K%;bBU(<}NtYIe zUUp?j|CWPuLKo-GAL)2#Nayf3EPWT0KV`jDEtKOH^192y@6lnMeXczm79)a2)5ul5 zt2V%^dp&ppRaYt;b>A4CTqz8=RgBJ9g{caoGjEuCfijY3(C*j|_S2jes^T z?Vx|_rY(zBIyay!<(vw(ZG@}hG@^nvpu_d9u285mS&YxP6R@mTQqNddxpCHuSuZ<( zUG(0q35Vk?hnWxDFGDyxS;uIP|4EOv7N;dzck`V2lPjG2KAJLA4&eedbX%)4F(HaM z-e<ZX2 zlwv=;I;{81r6amMT#)McA~W7nxMyj2!4K{I9(*>WTl1Rcb~A4TfBtsjz`IHojecy` zjF4#N30g3BRlUfL1WlcObP6SRX2mN{)w+CWX?XeZ6h~3oypgSBi)GzPa3>K;+B2Uo zqQdq-yQcf)0z0sN-oqzSrir#R3JJOkC>(HaFYX;?S@SB>YGW-$$oI~_+&)BRO(7$u zan^&>7{p|h#aX(JM2JC9<*au8E`O!tlk`;kf7Zr_|Bf5|y}S_G z?U4^B4SM)@w+@o&(<+^`PPIRqG$~v-`YHFd4-(FG3#B2T>QDX6_#{r0YqqSIN4er} zwQDYSQRUu9vM5pi#t3PU7gsA34smlC;*q!@ zuu6~)<1W9(=SCRYs2N1Tf-t_2v)u7%>8i+2vlDGu840#DQAA#L{!SMV|7IKHJK3uo ze?1y+J;XHrYwFNvgW5Ig%;f8J__dQ_q_>+fwb}yVa2Hq38|Of+I)k}Boy*uL7~Wza z)({_0X}b&P3Xm9=r^101!1u|p7a8->7(g8A03Q($)Jpw)wcmfgeaMVs3HED;Vl6z8 zO!k8TvpS>;h|3}{sA}@=DnI4w}6^fQIb7(Q%v~!*ik+1 z%AG%|L)N^JZU1unV8=7TUGKcRZ#$NoN9W_t8PFkM>pj8urOh4jy?wJn9y>TY^o|3w zLnrcVgu*!6m6M6~3X9heKhsBM!;U8Rb7HJzM-r_27#=K$Dz_R(e`0zhO^4$wNA$se z35WS&xl%g^KBp!pf+ERwfCKm}KY7N1Vw5|5#hgjAZF+Er*4j~RHRiQ8q{4%M7=v`> zGM|!0<~hc4CU2R2SNbyhCu`%v|CqHV^1Xt$Cj21x_3=N^clo8OqnON{gVU!H9p#gI zwUq&C)QK8@knk4|>Nucu(dei4&I)~Y|Lo95Q1(e#oaPy8Igy*{_`GzP1ErbG){tcbN2a3*=;sm=00F;|L=R|>LqVHz=;B$2kkalSJ+n8^K>Yj-JW*g&~ z-}*!mZuKr>fh;Qu3~7Vt4`~Sy5-XkSAtYqHg=yEXUn?m$P-6^KbJ`?*YxT`28-^)U za3eC?+QcQy8PwV={dEPxqtBGS>qiXtW&=zc^Wn-1-6ddp((uuF=bd;dasy5ABhZ@J zz$gsxH~sOPo6i|8oTkSE-#?dap*aHvjSCHY2i{kWR5faa3XQe~$XEoJ)TzQGdls~s z{PaZY-uwll68~_^pvB`lx4iw{0UdY-x1vh*LdyXhRqA2W-NWzVdC+9I$jdcJE7D%@ zYUFPYzU=(*e`CY`xI5YU_kvZF)cjOF*C*fc~QKzd|Oob9zASwYty!X2NLHe zcMj`$EX9$h5B!Vk0CCelOba26zX3JokR<{FnjFhg;*PO=nFD5l4twOmA)T6%!Bl0n z)Pdgl;&cxmuJUYOEXh!TZN&ncK$(TsX>VG zU07w07A+hdJy#!pfMq9PBMzC#G_zm(#U)AhV_B*8&mbV~LmOL)GTmITX1usR@_sxi z1h1SQ)e>u>3Z?hBM9ad>Gs)8pzVWY|nEp8=-KzLsFP zY0iT1kHsVmg^d3N&g-3jCX4*R~+}zU131-Sq{+r9j|R->3Dzn**du z>0|@OMam~-Y|kl&;w}5nq&P2=QFE#sr|KCxnshu02RV|HjgHUhJ7?!YV^f+S2ZiR03jG zyk#RS1sV8O=_2#vVeC7WS%14W+4A0jmmKdGz7qMzoR^&+GGAm2=scV9UXA=9bEV^N z^uvF8=P((l6br&cK!`P_$NB4t1E&;S-@?Q_f3oO_WrjF5Q$VO^5D=vlN<1K@Fxj5I zGd5xyf&1q;t$OnZNFe+0XQG90GYD6RVUD=EPdA z>Q;n{^s)0$`OHM?5e{rp`=l01hKz5nqSI|bXXfT`Y_w`nj;Ii(4r8Zb z$KZ-xAmZvlq^Bg_R<`!epaifZKjf;yv{Q{)`}j=h)i&VsyMmH)Q|xoiNwt5zV@B}wM}~Hm1%_tAfn*dAzq@77 zjG{z)352VhnSl<@!O-eDwoCygQy^%0lqA?MAnmg65c5`5ytO6zl@XA%y-N>{SGb4su%u99srbc3WL>)^1dOoyU=gqOsm6;hTm7~eM>(5Z8`O6&}e=%V|B-4v@f9*m-B_PO*xith3HZ|ya zS9AlB>O>>W(%R5KJP82HxF!K12b8M@aa+$eqo5_OKeo(~R+4DDL`{&4lnZgdthKWg zw1z5;3mr9|T7TY3=f5&m*#EvMA>uEYD;yu?t#Evba5mC4p)<=0jgkz5nktyT%vG0r z)KHUb`xvJFo+}=_TgHxcAS$AGQuj6;!I;_kRGBi9!c4c^GrR*2>q$?sZAM31ubJ7l zbac2PG7K`Bv^Z-nEexJCM`p*gu!C}!S`J_rFL&(t`S<~{incl?tqTZA!;YAU9bC=I ztwu6a?Vn}DS&AVjc%}w7Vk==8&evY@;Ve&cL)}kVq6al=^Rk9aCBG} zECkji^1oBJnmDaiG0tZe^(V&oWLa zckSIPsE-`3M9$`R+iVMH6FF#~NFTR0r$r)%_y6IRLH95(AhC$*OM&QL`p+gWgm#-y zxZJU+beSWIE1#J*_Ae+F=QAkOC{S?^Y0<1pZMwACLOD<2Ubn8g1dQb_3e(9I&fRMw z`p{L#-I%Lv`(Fh~qXin}YzP8jbCogUa8=OPL@NFU+s>mVATG5*Uj;^^1`^$gGlZJ^ z`?5nwqxj{7f!$Na^jx|xCgSjk6h{$v?&S1SU04WnXQu;Xv%Z3O+nKbLjz4T!VS6|8 z73VJtUK{_5+}9%CqYHy3Ga5S2k>D2M^nad&Hd#i7T0mC>zNY|4kF}K2=S{614OSX6 zwMO|441-!WwDjYf?;fsB4s@*(z<-jjzfT@ApdiskMo*@o1Pu4u|B?(VdzJIA1+PT@ zZda1^?>iDKpYTxlOl_RyI6I~Y2ndg@FOJLN&a(^`-NdxaC_Ko>tzBFBd^Rm8E-%TJ zxoc*~)7E zD;*zmTXk5Ozoftxp-mSGm^GO=!*v5^_Y|Ydj;6&}FZ0;sYg{lwY7-^Q5m&oa?A(7#G(RnY?H zS_N4x9%n6}5X*hZ`6m%*u!MDir-X&niHDGSbGv5*pK;AlS#grRIB|5(iA*EX>r%kJ zE>eths2P)M2q0{At}iRQ!8%122Q50X~O`RpUgBNGomFyHx8~cIGDf6 z`HyXJ5o>owN9@auv!0@$pjI!8Mf;u%>KZ!*2U6Kt7!S7=hY)y>Q%{*jGHIq$G4YS4 z3>gCfah#1E;iv&SS7$)@*TBFIZBDWL`oJ3Jo5gF!{~8QSrk%3$L6iHEr{(QTuzaS6 zU!$w%vpa+2`OX<3{+aVeIJmLgq3DPcr3u&9Vdw&o$9jIAv&!*zy0vsB$(>)XP(bX6 z4&TRpa*&Yy!&ns= zIt4x2+C?f7jg6uN`{`l`_ERgJyYKANZV2;YaGf<6>HW*4us$=qYt!FM9O(EwCVXAS zGW%Ls?%Bm?pSel4!<;n2HlH4E$%bXRnTK@20^&hK9xV>61z1m9s3}{xCynX(6w`+M zH<*B|E2&P-2IByIve9+fPE6Vrvu=K$$NL3Hyk6GBnm(f| zpnp*u+ITBCeWbL8MO@t5@r#AQKYlEPp_l$zkZYS4|8 zmPV`ILInFf777{kw1D9~%8D;i&HU!4L!?k!=|fQx^Q1-D-u!U7+;+m5bB+G~9SdhJ zjh^>TRwAIo&2c-T8HwO+^9g)f%UFBmbd1bu!vR%Td+9togiv0XFaA_)ji zdH*`3zVsdaxX4?kG+^{M>GRQM>|x>(WiLJ+C1VK)nFaL)x3q}%*5N})Y#0e}V)H5k zxvw6`sHMpbMX>9-TRPsT6QnXpIs><`_&%RAs)>G|#CHb^l5*pvj)>nX?g3qXSDk2b zK(;JU!{0XL_E!6SO-Y_;KL0i9b?8o5$YS757=EcykQ~ef(=Ib^Zw{=NuNAqE8zBLe z2I;S4Kf9D^GV0Zwh#AULqE*tdXAXC^*>z1piDCY zz>1(jm$*~Ul}%T1ql$UCgbx=#bF9nOWkKe#c`J5w3o^1XGO}OkFmQ01@BUc@X^OPK zM+~S@ropVm;r1#E$d{9}dSz(V#+iuY;0LT0|9~34Y+gyuadqh5@K_o1{$^0CkAY5OOaq@x4IcM>dkPsX9d^_N8DoA z4wpR7REkfkTZ|yw@QRr`GYbwmQv>bMUl(-tp9!B!p_jM-e6Q@k%%QXg61N?P1KVyr zsS=5E^XwoL8NC9Z@|yYbuNsvpwcU0kT{kc>czWiK)7wkzrw{eEv3P1h1VijAS5c#- zjyB9on=AMgY-0Z}P{zS2!x0CjLpt4|SM3A!QJffdu!@_!G&pN{_rUFTTTX|A?G>Q5 ztbdqBQ7F)56hz07$)v_z(s~drLc#W+yY2J+D&}-EE!WwTjpJi6Dr7nqWbc^X+H-zxiM-fQ1#0zDWlWTp(X5^Ly45 zYBvv223v$Ml*{wE+D4og;Da-DQ8 z-K{&})=Z&$HJIsP!WDbOjkRzCr|*%w9k2KCr+{o5X&38MUBv4i@Jky!7t71#o#F7C zQEecN*Bx1bzDUdiOU-R1nfgHkJ4`g_rb>W2SGa;IAy%@u^GlY)`bP*k80wIA{J-zt zlp08q7u&s`U`qI~W3$5Ae}W{(r@s)ds{-Rnqjt>8dZO?KyCru6H7Wo9>bNq&_jGvM z0w|%9x!9$(cwi7{5Rk!;85^MgMtR^nfzUM!B%5tTTKUPt}w^%#AR*3zYFi~T| zACO|$;YR&{*n~{AhK+*7N$STmLTOBZhY}Wh$9~89_iy<~fc!8hC?HFSYF8|CpKNUt z{(IkwM}u>>TnzZqmTa3%lvy=YQ|;8^)691U#>^m1AT^AR6Pjrb2fo9uWNE7cZ?#Yh zM~SxV0XB8V&I4D}Ph6ozIg!n{ORu;gJKV@TtO-9LNQ?%PXRvB$mZ3J8p#H8H^phO*&m>kqu$AXIh}&fN)TD+FG(62tpl z#720j9Efu7aZIW7I*hXR`08&nW&D9!A0)0t*S&W<-TPsjj!22Wn&%ZEQVBu%1L>Tn z#Bt}y2oRAm9R#v9dd@Og;ai?!O+0K+i~z+vmOk&6324{fm+)OK^2H!iKN<5u0UVDL zV3&n+b4ASItyn0%vY{vf8l$*cx=RFM6sPX8<~%2;@4~?Yg68LJB5ifqXS0ymoF$s_=TQ z&uV+1$CL{AIydKvKR~|=Ir?SVfrjR07ZE2>#*V~g;vWY+Fg*FtvRy19qJ;A1-Oy@a zBJoX*I*)q4?P1DD`1mGoJcOXrRfY@2bz~d>xQoClsQQkO(J>#$&tg)zVAhbo%7uWQ z0s>BR*ITfgE?&MPYha>fZdEZ`GJ?k^SshJdsV2&x4!Kma^}6q}0;pY83Q1V;h~#(( z@SSe^wHj(5B!_6V=8bHh<`D{+`yX%?oLrTe-$iD<<0mcX+Ee{HjMA5V@fc$-kQ!1} zT-jPf9Y9ViTt?aaGLlzWP`w95Z020ds3!~6%Fi(%7e-W| zkwr|P4YKSlG#6|{AV}OU1KOOazFN{`KT0)qhTiM}QjkO8B~xp>u@5`m4H4Gu3|59Q z3j=%>mI1j-BoxF{RlN0=qr~caovztVGSquo-(B-s1hTIk0-w>pWcT2C zY0bf6!ie--jhH4B%Q-O^XVA4gVJ39kiX0=`-@QWbG=6{9L!jZbZgaCzhbJ z`#(ylX2aaGm3QoZLuQ0>quU=S$mN;HQ%PL3eE@jDD!Im+nr>*Qj14s#Cr<}yRD^~i z?4ojh3SbGX3|lO|;~dT$vN)faO;03<+;E&sG)E~_Vg;4K*@e07Vy@+R1t7TFbChDC zCyQb;I~~?$&%!qCHlO%h1WUXu1AD+tU=F$X)%*V96Ip>l{Cpy9dl|YQBI0V{^(=Y_ zVoqimV^n|lo0q@$VNEWPt5B8`!@0fyJvRzlsf{5`>U=NV&nd#|5dh0pGy8m(w{_P-4Ps;5?xRjoK$ivo0`6u26U4u<;3PS)YGAt zu4YD4z3wRrznavpZ7M%yq+KkcX!@run?2kb2He^xy1ov*O;%!LO)*FD-%{copYKOa z8^XSLCnPwbJch`4(1A-2+^IS3hRO--eSK=fO}LWn?3ZV{B&ofcUzylwY$NeG@BVNU zEHo&dlqt87I9}r~HF=TYu0-Ak!sK!)@?cQr|3ZlOutsWESc&(=sX zwZ;x{U~hKi$AQ7cX7%>=`e{%4#`jmWEs%{zrD#~q5Ug)uq=yeo51^T}0AzEeLv!#m z!>VhP@U3<;!wAS(bpFhb2;VY%Vul>R8w%}ee6ia9?x`p)h7&S+y`q7EA8Q3WyH^lX zy5FTWE&@l5URNW5P@0lY$&k|?XixHYLDOn(SEfsw1S=EG+j`%paiKOnz;L+eBa3Xn zn1Z+_rOUI+ z-+w$6n|eI`wV|*-I2U@Wz%Mt)$F~9%TB(%haw&RdU{NQJ2D7dCSWHypw(lY0EfVIZ zck1nww4o~5pX@oHi`O&_hacu#=pg|oA@hRu%3LiV|BBoDXqe7<5m=+h{C;!r^9LC9 z72jC4Y>k}P2~cVEAhWB>2#|Ee!;P$qi`i~PkHRh^7z!~*nvFRX!*{wQ0j2s_{ObPX zcC&N@NZDN6F((8l>G1FWOxau&wl@dguR&Rc5_y0_yx9SN8_+pOK=>x91ok+%)PV0X zWF4kr!aTrmj&NG?Ry~crfnRi$TBR+gpWZhBMH{;D!dIkOF0UXng z#X^>rXQ59+X-d%HqpvboBwMW$?TFyCb&pO zEHt|Qat=n?)h0}%GFLVf?!|dw1qwWRt%nH&{AOTf(F>eOpewr>Ela@rU7;LW7%e$| z8i$chKy&hG0}?01ApdlU#GRHnrx9$38Z3D^J6m9e$JjC^^_dN!grh*5Ex4QBYxldB zNuFD7Bgy;8-f>w`x->p(b!J;_W8vL|DW7s?;9cy(Uy}PdHTmZE$>H^-=Z`q?y7>3wO`e`qOiY~y zlq)-Mn_6n-A)b_3k|S_eSOGBRAe_L}cJ(~&KKl^gD4+5So^67J__L)p!O(t|>+Wy7%WVe^V6FEif`H&;8^@r^`uX zVp0wpQ$zMJ{9Qy`mt-qDs|^@T2pHQ~;V+q@AqA_d@NC1{;0j-WlaqRhi z;N;~`6vCB_>E&wtxDV?{`&yqR=eSTftybZku%N;7ZE2j_U-JR}N$jyjt&+5%P8 z*KkD2{H4y~W6LfC^7pH1t1~=Y>qQ#+*|xv3FX|mU0UmH0%zXNRb!>N0Os&t8`m5mi1s z^QJFJHmQLYe-LowzU$$H4V66v1l#LG`sS~Ip!P{Dw(v+fliDOeUh1XGl8lA|xqBYv zX!*Ss4C=6}B$7g}K8Oi?vl^NTU=6eu$`acDo__XhJ+ zcgwqQ;?+(M%v)aN2C;|vivOwP<6Z6YkgIMoqO)j2`mM>!460IClC^w2sBBU|^>09n zR)y)4dXjd%j9O17M6<3EN`W!)(*!$>It_@{8MsSCq*d252) zcZNlTR}<$8tgYSf^=U-93uz+GXGciYpo}=2!7`WZ+q&rTUo?Drq(-Sq)ZTVjtqzC$ z*$xUnyoihAb0nK>+u5U+1c9MKK7w-wKKD!n$m4Tt=Z{Jjk$$PGnhp!xMaghQPkcUd z`r`Yt^$W(Gh|6*HUhVU>;%qj_bbZ=&W*XI;XuVopwMh>>Fxtw^_GIhLFxZW;dCKr` ze*SVy33&!4W>&lfby6_i|J!|y!uw1M>tpWZ%ZKkLx}cTufXRn61iUvH3=s} z$ks1b<{a#Cz9nxJJ*5{W1_(1|q;8l9FnxUc8wwr;eh%*Di?SI#M#`YyipSQd00B{fseFfifoHDk}0!I~5Snl&4>=n#(u z8`ac`G^^DUN6SBWD3R{Ug_01~8sXxu|LQ*OrzP12eP4A>=+=HznWhWqtQx!z6&dMF zSu&$qZz>$rK`0p@j*sUH`bd#%rhZwLxhtd#e77Ng#b(3x+$L2G7inhgt%L4k=M|lD z4?35~*(_V+Ue9cDsX5tN6gP*(p_ z2{b^}Hy}SL~&EA&cpl3T{%p{3+-W@gN$3n@3A85q$s*VdV zXyA`mvV;hMY%;}i6)e@JVS-#G7(iYQ0~=H5rUjABSN1=(L)4j6T7X+YK7Djtc=JWn zZAxmQu7hQN6-eWO+nvv37;STQwWDSnwTh$YPZ>%ot#B@ycbZuEpxJ<9w*Wk`dac63vwZ&DWWPGZS{FWg`wW zS-&jF4a<4~eqYMNlo5ko3c3R2!n*vBZfrV7=_3fu(WBd>^J9-Yce|BCm7Wz6GPZ)r z-ab6ppx*%Ofsqn?Y0gcYbqON(By3%4ChUYD)mSiyO=RFJI2Kl>{X`rQzo9|FJ#!ex zUGcXn|H2)jiuf4M>e%3@zMyl-!NTDkYe<>^&6eo~@~!=04L%PM+>MlVh`%)<^XiFZ zxz)bw(S+!95!7If1fXxwlPHZ0eLJM85hzS@4WyLw`MR*kB@%lHFy&S!>c}WAoQ=M- zblj<rWcyLdi|0S0(Tc)WDvgAGimbT~~!j-6i>QL#B^ZZ|4@7y;(8+>GeO%ZdLi}^<*x$G%i%Q% z?ldKPwHNs_KMZQS?@Pj|lzT9mWLqgm-w4VhV|E+8tj~GjAr=2R=w$!UXA5UGo$%C* zQ^K3C6lmMn^I7N{O}J{FLs)cK%1eYFF{DGaUrWQgepLeEZfXP$sp%3Y#0&kYUvvq^ z(g-?3hu_9=_R$=hSSp7&eu8&RRJA&i1$oJ7GZC)WuSTUz>2H)}m{17W->q=SZYJ`5 z!@&h3$r7Z%2;N~|Jt6A*$^_pOX1e~cu{`|AXOptWN=M0Jiq(u*rP<1>{`JrM#yX}F#1)*1)^cdY+ZA$v5$X*oTEZ zA2?2BVRNDq++e#>;*h+|hZ;oAO{sZrN|M!_1aAaNWq;S&<|uy|%jL^T^v$b2GV_s3 zX8i{nz{p!#ZV&e$s#myCTEQNtSDXYOgk!H-;v;kuNDp}ap@ka!v8U_Ucm-L0d};Ra zN#z6M5BY7U^r3%Y(L+MeK49G$QP1H)icgNT^UUZ-fWe^Tr~5!&}(lr-Yf$5#;mRIx7Wi(?5(|zN`4uH7An*GkK(@fGc}t%D40?> zhn{|$52Q&1hGMyK(DAOId>3BkC4&1~%O#W~n|3gy z$@jP-Z1<+C!Jf+GaRyU=KK(}ixPe+CwNL-x)(bK%ds*SQ0k=a7h%fJ$4t% zhp6PR*D|5bp_1~0Llti3U3>hD@J3VMGtBvEa7vTNfy8h1`Nz)5NH>u}gZ&{CVq3Bt z`BgkE|I}q%6ki)X&)Yme(IE+$+ctco#rb)hE>vW3+Wyjj$f9$x5?!YcTXFbsqqm&+ zc@Rn({rj6>>(f+7X#1m=V>o_7?X|eIJgb{F zNjBT`JK2p_`g_>D)Ty9F$}MXJtq>=IJ9cxI#V@!tF8}_Uyl*_P$J8qt$})NzI%6MD zUwohkGPptub1(Fb-Wp(#A7d|7`5etnyhh~?i)16*ij1)w>$Op3RDM#T^eX7r&J z#-I$mJqk|ZjV5}2h}S4a7RsHXzyh=(BpHjGVxEKtW z%oTq#%+9Vbzxywoa2{!uR&e;eytjt2Xz6bq_UT`ROevTUFUoYV96B?8up>!)BMrsj zT8dc+{SU`tf4K^ZVgB8KFw>-R2(Z@RBTLZ#+5vzU*}P{Jcrwf+&Qz;Tm3j5+-A(Bt zZKdi{k-rIsfqJaY+qZ>Af~eG59ylEs&qh0sv|Y8IZigB9)v{gMa7BJ}47*&+JlW^+ z|6D%H0Z8SUk1Wl3RO8v&-EK=hKRi#{i}PURSMzac8wW+thzk)vr+=@8D}o6q7j%pl zyeTMwK29kB7MKZ}{ntNMu}gy*h6=CoGoVwC#Z;MZ*s~_CB?R>i(|f4HSpjw0mbKtY zHtPe_hc>+;+i=rOQXSmH-E41X@LAaogAYXgUp>rcrrugEUYub=L*yAnoUaqFx+X{& z^yqhanM=X*yUgY9ek1%#)lHcf9Z}R3=Sy&99_FnBh93(}ZZLTSd9{#e3pyJXYiXT~ z-PhT+nZ;Y2UHwVJd@i!SYiCfdS=%q@-LqSzSlRy6cp!x7ClY+U)g5Z|{o$l@+E0r& zuyh58Uk4@*ttM)}h;%@Fxbu%KE5v0;NsP#q7KA&-sCquZ!^i`FQ845uh znziU>=3OoXYR#7LtrLeLX?Wy4&R`9RcrAD+COQs2>t0hwJDv655TI1)Wg+g@-O%oQ;aI-s(3Q#!c1cs_kbFz)gJ?m zm<+zqog!+&c=O^{=^%SH#-bz;LFr$L5hX5W z;>G7C>w~xZd$6Q%IoQ9QmNO`@7&?oTJ%`<)IVhqW&1Ze=gi)g5U+2S`VUN2IlQfcR zJncry!V4g^!~Kq(YTIup1B3nl_9nBrY0!$#vf(kvbKfiE4O9DCNbu%HQ;SNip~7Xv zFQPHd4L$(U zWK2Y}14~RWRT9h`v{VuR`G5d2aK6?Lo%tkdoSdcyy{mbwau%-hnI(lBwqpBHn&9a| zyn-R>WENs#Vrm$DRQZd+4GLUZ%ypdfcmn!T7s1VKZ@1~jXenbEUWRE4!QZP06RSI0 z>|rDW@U-N_ccW3C=f`J-h3=bA)2F1WNeqrR5X5OiY72^9z$%KNz{QJpZ;$6{l)mlR znGrE9?Ug2=^0FacTt+Sil_OEOBoI6wuvcmeeUFzXoOsgXxrwP;=}9-Pf!d_ZFTnmi zJcel={LpX{*OL~$kbJYwVeqJ_TJd;_3x*@}1z4bD z^RYsosAIIK(@)5Iu7l;x>5ZO0i*d?4^mghyNxwDZ`21b7@IM8c62H=;Z_ysHL{Q*1 zsQ|Xdfh)nRU_sKWjOxsLQd$UY5x}MR+Qakj<^M)tDK3jaBv*cQDDsr z*#o|_uqfv@3>N%}{C}8Yk8yavIMoT?E=G#%21Eq1G239%YNnA!H=h;Sz*sHmF=XaJ z=aoPE*&QP-qeTQqr|$8)hW$G=qv}iESHgv}5Zh@M*cgQF_(oHU``iYJhbjaoG|W7J zh-q8Q&!#XWZ4}9MO;~E+KkhRjIG*YwT3EQUwE4IB9d8t`4(7H(qfean`%*mBI*+pe zv)>v+r2t-Y=~X#`cN;ehiNmBqOl{^r9h9jj@sE_D3I%I1LP(Tc;d3gN!zfp*T&yD3 z!BP+Kp=nn-ywe=IkikBe8dO{+B5XgO=_U?c6f>1PVkuWEYQPBCsBRMn! zAzF!&Xs;7q{D4$%Xx_i@h_Cbm32dgA+(N%7abTzj2|aqRQtD>K)U(>4fhcV6J)jGTw! zxM*gZ3TpG_&+{|}Wz=KB%L&T3RD3O5x#1lziPCxSbYnV!f(nZ^pTLPv-rpe>;@NW} zt_{xOU&O^9>}E&$;^!GL?qx9Wf8p_yowa$IG+7U1@epq%QZ@fDBWGQ@SPoxD9*zP9 z2nRpQFBXgfgUP#U!}iwiXJT{W*UaMwQf0RzKx(FNqMV?lU%|=&0PVX=4DYdLx^lPR zq1=}15p)du{?U89#@{wx0u$u(5G*{UL`B-q(X*2m<*sB~3fu7;+|ZNPxIv@|c^mC| zF94j(sKkG32M2QaUbj?Q9Pfmk!y&PPfIvCvq1O<9?NWWsn4D6Dl_b9=9Iw6U zqHYQMmr5eQ7hzuhn87XG+bXM}B6%n2^=(;`!OrCs7ebJ~v_bc?Uj{ND zTDXJTMdUoTi!-gSCz9q!&9y1%y zu!}lIhPJPuV+00b=vP>HODaejh-{2^s14(gROJi&34XHT-wU1ivMjN3B%Lsz>t)YH zSjweV8Ps0!^Ms({K|~OiYe(KS^3CjlILgGE>hohs-03q@fNSTYH*4YJxl5rO4MkwI ze&ad6;`v%*YX6{uet*e1h&aLjA#_$4)FtZQ6ARo>n>)?oa4Wv#&66v)NDl*hyl0Yr z$w778;$*9#j>LBa3|rc}YuFS`1kt_ZA!h{GWJ(K@YlnFb@fXE>5kA6WQsci?HZlu5 zlVf2!(UK7l%#8!U;eKSRh#TDxG(kMG6ZM(Jbp@R~ngu|Xg<1eP21U{1TK5l$@AH~90#WnMd5|a8O6w`Hy3^jp$Ir1-`BDcj`)d?R2xtrWR zIgfb5*bMAo%{)6>2p5-x-KBR(Zgk~StF$ctLD@&Q-S+D-xR<%?t!N!qUr_jK=UOY- zHr=(GX(n=Sdc(?KS1#_nxkYftf6GCq5H5A^5PMyOm)(3V>2S9B$tbJLD}CL>p|e_Q z;xqPwgXV!;RaF^~9~q}^2BN$%7!MLgh|Gy-g9W!W#Ue>e-sw7I;fypBseA3?2tJ@VL8x;0Q%Ncz9Gy^4)^^B0=K-s;ksiix=>z{SXG| zyDQypxwZ(fyIk`Ox7DJz$D0&A7PrFvq=3WMy6@6EV}(DtiQ36&ztZ-5Z?BwX=12&W z-d^VI9Mx;-KXzeKTEQ=c5EvmpMoW;#Xs zfRTRsv9?rKE1bjhwZ_EG=6NYiJ>D>X=Nc1i#DUD9AA3r0%A;G^u*~El!uhTE zMdN+alq;Ry-3IJ^IQJ{KG~{t(HuJx8<#Rx zpWb~VZstLT3`xzs9OW}3593KU90P{Rq|#o*@vd&o;zsV*qn-xYa683+D?6B@h2Q!- z{yMw~ZMXXX%#-dMf0Vr=Ua);_mI9_mC6;EUf9wgI)N`ButDsqm3Qg}k{sC8C@Go$> z{o$S2h(|C9&CxJVAMdhm+}A9GvoI)9XM*^ZvZ3Bukmf7=PZDMbor2<(1(XcaB?cBs zK7%)eV#7IE#iD4RP@XKFHRoEYUibULnjh20M!)Un4yz|~f4u_Pb$(aisAFfPjfwVt#DxvmIw&m}w$HR|w`;CnK@ zTpFkp0fl=HQJ>Eh+Ha|X4`L>`sVIIQEoE&Z-I+}Ec@`nQ3wXAaEWNKtb}t>7#OTCM@sJ^HF;a?f`SjJCVwFM8 zFiA_tddOM82!f?sM453SmN~%_U*jlXQrV)~O zmF)`&J`27yW5j}BGHgg|K>+umL5vj;Q-lmIUa31*u(|gR*tb}i;M{aFtY9Tx^dO8+ zh5MOlfw>+o?P`o1rtMt1v`uVn<_?09Fp8!Q808+K*&JxuG7woxY{j5b)@- zJH5Tb6xRp&;&5NoA4;}ULvZFG9_#G54jeGmFf6$(q@blW6o0n+UEO-YH&I;7Qy)@D zZvPP;d4bSDsZ*9WF|6X?l~}~T4J)tBX6UqmK$n1cx!J3Pev6+s0PKybL6uw9o+?(YJz{m8E&87lTKFa&N+fmrS zL((1TM%%zAs_z_K2S)F-#+_a?df(zLSn8|Ci}-t= z3sj4JaB*8HpERC$%$}ZuYk>{)=z}W}jV?_wB)}8_e;nSAWY(S^{>iGlKc+ zV`6|h0QgT|I}_|dPqV^5Mu4{0RIh>MB^C;Y>X$+C>s%&fp4OIZ^~W-Z+nxrOnPd<$ zG+MDYh-y_yIU%J;042G~(f-xfYQ=rvU201sXiS0)<922RNgQu?ba8K)Sd6#_;%^`L zkBb%`sx^u|PHu6$-+FoH!L{N*>{YJG#XNPwoD*cEZm3J8)wB^2wdHhrwIxsRwDAl5 z?~lMamp~BZ9yn)8CupNT!J_ASe+uweHJ+2FmxmM%R$e)kl4JhJpkY;~(rEAjck(40iw)w1L0cB?L00{0`Sx#QBRR$_ zACF@G(3np55}w3`2&vOE-Go#SA3vF`3`^GiYn|{<5kK%Wylhft063Tf2tp`o_`O^S*4mzhxo^1yoUz}6LmW7Bg)F= zXbI6=to)gE>d5vowB1$8e9!h_Z&?4A?;WB`*@+MZ6EOCb6(dDq)E z#ihS0z1QPw4++~suU*FTSvvl%z>)N<4M=3tM8>V#?r|c4PRkTNlJencmtBhEO5YHo zCU8H*1_{jq#uwM)A*j{~xN=BW!kylC0&3&#W?#K(**s*$Z}{sj|Dv5b7o_0GLC|CD zXqxs(Vro97R+8ux2?8tZl%BJ-DO1e2qy)Hk0D=zo!+W`K#YWW&;7*c%v$ve45yR_?do;BK+R;p)%gm@|X~cZuwWr)cqi$ zEUlg&pY1WoC)`EGDCu(j)&1ipsCGI_PlyKHj*?^xt%}W2Y0mwuaHNq`o`|p1qg>1? zscle;*7$kea(Eiy{CNLr6EctJZ}7v@ol~;*_c9aKmx&?_y>A%jv_ZE=O3QkF#R-KHzF6B)m1MDj<)1E|1u^o zYl`{P^%T*`UQy7?%0UG^tb8i~CWVl?e}YZ}{0j%#W?r$NdDbHYx6r+*J3I{T@L|~? zJ>j$vsO(}<)&oBpLp0xrQKi5i_ukj@sE`(UQ(S4MNqdj!D&@(hP~4 zCf91uvZ;#i&IVdJ1`;zxKx`p4%gZ@{7cD4qNsDwYJ*doq^D4bo-UbR|Qrt|Uf;o`b zK#{ormM}O0ErqryTB2UVOYQ10r96{5&c<#32>z+_&W1tkrISG125DJ_vhzaixrTU& zSELEviqewNAZq`~jtZx&_WM%foSLLsY>)iaMsjHU-uM*cQ+rTW^tOX`9O9KeDYP&g ztJml^`+~>BvKO4Z7ZCc~G#OGC``f-bIR_^+P8USFpE_HY#oGtr*AYB^|Hc`E`(LRY zYTukMznKHi=a8i;lFPQK|9g`kH^3|Z{y$F(tD`cwo&&my?h&|qAsNAd$5&}ZsVWJ> G;Qs;hG7C`v literal 0 HcmV?d00001 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 += '{
    '; + for (var key in json) { + if (Object.prototype.hasOwnProperty.call(json, key)) { + html += '
  • '; + var keyRepr = options.withQuotes ? + '"' + key + '"' : key; + // Add toggle button if item is collapsable + if (isCollapsable(json[key])) { + html += '' + keyRepr + ''; + } else { + html += keyRepr; + } + html += ': ' + json2html(json[key], options); + // Add comma if item is not last + if (--keyCount > 0) { + html += ','; + } + html += '
  • '; + } + } + 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