<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-11788780</id><updated>2026-03-22T05:18:37.551-07:00</updated><category term="python"/><category term="web"/><category term="ruby"/><category term="rails"/><category term="Linux"/><category term="JavaScript"/><category term="testing"/><category term="books"/><category term="pycon2007"/><category term="personal"/><category term="pycon2011"/><category term="vim"/><category term="dartlang"/><category term="computer science"/><category term="software engineering"/><category term="pycon2008"/><category term="google"/><category term="haskell"/><category term="pycon2012"/><category term="ubuntu"/><category term="apple"/><category term="java"/><category term="humor"/><category term="erlang"/><category term="MySQL"/><category term="concurrency"/><category term="emacs"/><category term="ActionScript"/><category term="YouTube"/><category term="cucumber"/><category term="scala"/><category term="lisp"/><category term="OS X"/><category term="React"/><category term="unix"/><category term="computer history"/><category term="php"/><category term="sicp"/><category term="video games"/><category term="django"/><category term="html5"/><category term="rspec"/><category term="AppSec"/><category term="android"/><category term="ide"/><category term="jquery"/><category term="security"/><category term="twilio"/><category term="C"/><category term="comet"/><category term="html"/><category term="oz"/><category term="pygame"/><category term="scheme"/><category term="twisted"/><category term="windows"/><category term="AI"/><category term="C++"/><category term="GNOME"/><category term="Go"/><category term="MobX"/><category term="NodeJS"/><category term="asynchronous"/><category term="chrome"/><category term="mac"/><category term="math"/><category term="open source"/><category term="optimization"/><category term="pypy"/><category term="python3"/><category term="pyweek"/><category term="rest"/><category term="stackless"/><category term="agile"/><category term="css"/><category term="ctm"/><category term="education"/><category term="facebook"/><category term="fish"/><category term="flash"/><category term="gegypt"/><category term="gevent"/><category term="golang"/><category term="perl"/><category term="playframework"/><category term="pycharm"/><category term="pylons"/><category term="tdd"/><category term="tornado web"/><category term="vmware"/><category term="vscode"/><category term="webrat"/><category term="xmonad"/><category term="BSidesSF"/><category term="OOP"/><category term="Socket.IO"/><category term="authlogic"/><category term="aws"/><category term="bash"/><category term="bdd"/><category term="chromeos"/><category term="dell"/><category term="distributed"/><category term="googleio"/><category term="ideas"/><category term="intellij"/><category term="macOS"/><category term="microsoft"/><category term="mozart"/><category term="netbeans"/><category term="neuroscience"/><category term="olpc"/><category term="productivity"/><category term="programming"/><category term="scalability"/><category term="telephony"/><category term="twitter"/><category term="unicode"/><category term="video"/><category term="zsh"/><category term="C#"/><category term="ChatGPT"/><category term="ChromeDevSummit"/><category term="Google App Engine"/><category term="MySQLdb"/><category term="OpenSolaris"/><category term="OpenStack"/><category term="PostgreSQL"/><category term="SciFi"/><category term="Spanish"/><category term="Web Components"/><category term="ZeroMQ"/><category term="burnout"/><category term="business"/><category term="cloud"/><category term="database"/><category term="dependency injection"/><category term="eclipse"/><category term="firefox"/><category term="flask"/><category term="foxmarks"/><category term="free software"/><category term="gae"/><category term="genshi"/><category term="grammar"/><category term="hadoop"/><category term="hardware"/><category term="i18n"/><category term="innovation"/><category term="io2011"/><category term="ios"/><category term="ironpython"/><category term="lift"/><category term="llm"/><category term="logic"/><category term="microservices"/><category term="netbsd"/><category term="oauth2"/><category term="palm"/><category term="parsing"/><category term="performance"/><category term="primes"/><category term="programming languages"/><category term="pycon2014"/><category term="quotes"/><category term="rasberrypi"/><category term="real-time systems"/><category term="ssh"/><category term="startups"/><category term="treo"/><category term="user experience"/><category term="virtualization"/><category term="wireless"/><category term="xml"/><category term="Angular"/><category term="Apollo"/><category term="BSD"/><category term="BSidesSF2020"/><category term="BSidesSF2022"/><category term="BSidesSF2023"/><category term="Babel"/><category term="Backbone.js"/><category term="BeOS"/><category term="CS"/><category term="CodeIgniter"/><category term="CrunchBang"/><category term="DEC"/><category term="Docker"/><category term="ECMAScript"/><category term="ES6"/><category term="Enzyme"/><category term="Excel"/><category term="FluentConf"/><category term="GCE"/><category term="GraphQL"/><category term="IPv6"/><category term="InfoSec"/><category term="Jasmine"/><category term="Jinja"/><category term="Kali"/><category term="LeetCode"/><category term="Less"/><category term="Markdown"/><category term="Mepis"/><category term="Meteor"/><category term="ObjC"/><category term="OpenSocial"/><category term="Openmoko"/><category term="PC-BSD"/><category term="Parsimonious"/><category term="ProgressiveWebApps"/><category term="Qimo"/><category term="SQLAlchemy"/><category term="Smalltalk"/><category term="Turing Complete"/><category term="Unity"/><category term="Warp"/><category term="Web Storm"/><category term="YSlow"/><category term="YUI"/><category term="adobe"/><category term="advice"/><category term="akka"/><category term="alice"/><category term="animation"/><category term="apache"/><category term="aquarium"/><category term="arch linux"/><category term="arduino"/><category term="astronomy"/><category term="atom"/><category term="audible"/><category term="auto"/><category term="awesome"/><category term="aws2011"/><category term="babel-plugin-react-css-modules"/><category term="bass"/><category term="bless"/><category term="blogger"/><category term="camtasia"/><category term="cassandra"/><category term="celery"/><category term="clustering"/><category term="code"/><category term="code review"/><category term="codelab"/><category term="coffeescript"/><category term="compilers"/><category term="continuations"/><category term="corba"/><category term="crouton"/><category term="cryptography"/><category term="dagger"/><category term="darwin"/><category term="ddj"/><category term="documentation"/><category term="dsl"/><category term="dzone"/><category term="elixirlang"/><category term="email"/><category term="engineering"/><category term="eopl"/><category term="fantasy"/><category term="flex"/><category term="flickr"/><category term="fms"/><category term="forwardjs"/><category term="foss"/><category term="freebase"/><category term="functionalprogramming"/><category term="funny"/><category term="gcp"/><category term="gdd07"/><category term="gentoo"/><category term="git"/><category term="graphics"/><category term="gui"/><category term="gwt"/><category term="hookbox"/><category term="hosting"/><category term="hpc"/><category term="iPad"/><category term="inventions"/><category term="ironport"/><category term="jazz"/><category term="jw player"/><category term="knuth"/><category term="ksh"/><category term="kubernetes"/><category term="lambda"/><category term="lettuce"/><category term="linkedin"/><category term="louie"/><category term="lua"/><category term="lubuntu"/><category term="machine learning"/><category term="mako"/><category term="management"/><category term="mdv"/><category term="metaprogramming"/><category term="minecraft"/><category term="minix3"/><category term="music"/><category term="negotiation"/><category term="netgear"/><category term="nginx"/><category term="nltk"/><category term="nojoke"/><category term="nosql"/><category term="notion"/><category term="openlaszlo"/><category term="operating systems"/><category term="oreilly"/><category term="pascal"/><category term="peer programming"/><category term="pivotal labs"/><category term="playn"/><category term="plone"/><category term="prolog"/><category term="proofs"/><category term="qa"/><category term="qt"/><category term="raspberry pi"/><category term="rdf"/><category term="regular expressions"/><category term="rp2012"/><category term="rubymine"/><category term="scams"/><category term="science"/><category term="screencast"/><category term="second life"/><category term="shrapnel"/><category term="silverstripe"/><category term="smartphones"/><category term="social media"/><category term="space"/><category term="sprint"/><category term="ssl"/><category term="stm"/><category term="storm"/><category term="streaming"/><category term="sublime"/><category term="sublime text 2"/><category term="sublime text 3"/><category term="subversion"/><category term="support"/><category term="svn"/><category term="tcsh"/><category term="technology"/><category term="textmate"/><category term="threads"/><category term="time management"/><category term="turbogears"/><category term="typescript"/><category term="udemy"/><category term="v8"/><category term="vnc"/><category term="w3c"/><category term="webstorm"/><category term="wifi"/><category term="wikipedia"/><category term="window managers"/><category term="wowza"/><category term="wxpython"/><category term="x11"/><category term="xp"/><category term="xubuntu"/><category term="yelp"/><title type='text'>JJinuxLand</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='https://www.jjinux.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default?alt=atom'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default?alt=atom&amp;start-index=26&amp;max-results=25'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>820</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-11788780.post-6123606360060516135</id><published>2025-07-11T16:46:00.000-07:00</published><updated>2025-07-11T16:46:35.809-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI"/><title type='text'>Maybe Don&#39;t Trust an AI with Cryptography Questions</title><content type='html'>&lt;p&gt;I was thinking about the RSA encryption algorithm, and I was wondering how they picked the two large primes, p and q. I wondered if they had to be 100% guaranteed to be prime or if &quot;probably prime&quot; was good enough. So I asked Google&#39;s AI, and it said they &lt;i&gt;had&lt;/i&gt; to be prime numbers and that close enough wouldn&#39;t work:&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBOpeXoJaHQESm7mfXfvNjshcvolofIhMzvosm6kDmJYHGgzHkNJeu7icA1GmVAGCzNRKGObjXv5EYDccDa9kl3d5oOUCvDQgx2_cSDF2Dl_GhE2V8m-PHtre1gti7ESiC5qc_BZ9VqGYo4G1P5Oh4HGjszvtyfn3C1RmxwwXsxVvYM6YBjbCVgg/s1600/Screenshot%202025-07-10%20at%2011.12.20%E2%80%AFAM.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; data-original-height=&quot;355&quot; data-original-width=&quot;798&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBOpeXoJaHQESm7mfXfvNjshcvolofIhMzvosm6kDmJYHGgzHkNJeu7icA1GmVAGCzNRKGObjXv5EYDccDa9kl3d5oOUCvDQgx2_cSDF2Dl_GhE2V8m-PHtre1gti7ESiC5qc_BZ9VqGYo4G1P5Oh4HGjszvtyfn3C1RmxwwXsxVvYM6YBjbCVgg/s1600/Screenshot%202025-07-10%20at%2011.12.20%E2%80%AFAM.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;If they had to be guaranteed to be prime, how did they guarantee that since they&#39;re pretty large (although nowhere near as large as p*q)? I asked Google&#39;s AI. It said they just pick random odd numbers and then use the Miller-Rabin primality test. It says, &quot;These tests are probabilistic, meaning they don&#39;t guarantee a number is prime, but they can determine with very high probability if a number is composite (not prime)&quot;:&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcl7RY8PQBz99Cpqh-XkB-OJJaZ2l3C2zncq8ZuO-woBxUWNGpytlSA7_p02w5nZJKc8ZZ65tCa-H_anhF9wyaVEMGxEmjVncdGa3PC-ET8ozRA9LOanD3pxunSgTq5MjBZCDORWicjebzcYMzryW2Kv7f7ZVSkPbJIaXABmimOrb-Rud2AUxO8w/s1600/Screenshot%202025-07-10%20at%2011.12.30%E2%80%AFAM.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; data-original-height=&quot;320&quot; data-original-width=&quot;737&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcl7RY8PQBz99Cpqh-XkB-OJJaZ2l3C2zncq8ZuO-woBxUWNGpytlSA7_p02w5nZJKc8ZZ65tCa-H_anhF9wyaVEMGxEmjVncdGa3PC-ET8ozRA9LOanD3pxunSgTq5MjBZCDORWicjebzcYMzryW2Kv7f7ZVSkPbJIaXABmimOrb-Rud2AUxO8w/s1600/Screenshot%202025-07-10%20at%2011.12.30%E2%80%AFAM.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;This completely contradicts the first thing it said.&lt;/p&gt;

&lt;p&gt;Sure enough, Wikipedia says it&#39;s a &quot;probabilistic primality test&quot;:&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDdpiM2u9kjrMa4uf9zMZ1fUKTW5oZWrQhwm8aGQDuHvHZWRTAj24PzJsoEMYGv14R-G7Grt7dnw0D71aK6jiiwRjAlJvuasaxrudibfxIt2-uf0DxJ78nysBmmwdtbtR1c7VamoVeT_1grMlfaXxZHml_zrPS5TcweSR2hoMYR5k4Fgs2gXL2dQ/s1600/Screenshot%202025-07-10%20at%2011.16.34%E2%80%AFAM.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; data-original-height=&quot;452&quot; data-original-width=&quot;1213&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDdpiM2u9kjrMa4uf9zMZ1fUKTW5oZWrQhwm8aGQDuHvHZWRTAj24PzJsoEMYGv14R-G7Grt7dnw0D71aK6jiiwRjAlJvuasaxrudibfxIt2-uf0DxJ78nysBmmwdtbtR1c7VamoVeT_1grMlfaXxZHml_zrPS5TcweSR2hoMYR5k4Fgs2gXL2dQ/s1600/Screenshot%202025-07-10%20at%2011.16.34%E2%80%AFAM.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/6123606360060516135/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/6123606360060516135' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/6123606360060516135'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/6123606360060516135'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2025/07/maybe-dont-trust-ai-with-cryptography.html' title='Maybe Don&#39;t Trust an AI with Cryptography Questions'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBOpeXoJaHQESm7mfXfvNjshcvolofIhMzvosm6kDmJYHGgzHkNJeu7icA1GmVAGCzNRKGObjXv5EYDccDa9kl3d5oOUCvDQgx2_cSDF2Dl_GhE2V8m-PHtre1gti7ESiC5qc_BZ9VqGYo4G1P5Oh4HGjszvtyfn3C1RmxwwXsxVvYM6YBjbCVgg/s72-c/Screenshot%202025-07-10%20at%2011.12.20%E2%80%AFAM.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-5242703994202026352</id><published>2025-06-25T17:13:00.000-07:00</published><updated>2025-06-25T17:34:40.352-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI"/><category scheme="http://www.blogger.com/atom/ns#" term="llm"/><category scheme="http://www.blogger.com/atom/ns#" term="Warp"/><title type='text'>Warp: My Terminal, Warp, Was Particularly Helpful</title><content type='html'>&lt;p&gt;I was using git, and gpg failed to sign something. My terminal, Warp, stepped in to resolve the problem:&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzRbl-bFOqyzbygqsLGD6ossX2A_i3N0Pnj-hKrifuH0er6lL38x1WnxP5l8uu_M25lPbHzKcFsjpHPdhvMPGy3f0IE85hhP3Eq7J4r72FKPQlKPTVrY_Jd_t2Hj87QS8m04ZV7RAUlS3WxwmHbGBxhgoLAvuDYn2XWL2Si968HL5nDTeqsjRS7Q/s1600/Screenshot%202025-02-20%20at%2010.47.12%E2%80%AFAM.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; data-original-height=&quot;1772&quot; data-original-width=&quot;1994&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzRbl-bFOqyzbygqsLGD6ossX2A_i3N0Pnj-hKrifuH0er6lL38x1WnxP5l8uu_M25lPbHzKcFsjpHPdhvMPGy3f0IE85hhP3Eq7J4r72FKPQlKPTVrY_Jd_t2Hj87QS8m04ZV7RAUlS3WxwmHbGBxhgoLAvuDYn2XWL2Si968HL5nDTeqsjRS7Q/s1600/Screenshot%202025-02-20%20at%2010.47.12%E2%80%AFAM.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpdF0wGvZHFTlFd7LkFPfrI19cV0ssdpPAXnp7XlUmvka-I-k2_JB8bNqq9ZjW0dL7Qn0emwNvcZPpXYIAP1XfuvaxuTfiRsIvkSTFp8lpqaudmwxSexfg8E2mgZx-Jw1FhOZ4GkI9SyjgI7dmFcWqjZ0k6zax2_CjkkTSfqmynlkXULaKCJIlJw/s1600/Screenshot%202025-02-20%20at%2010.47.21%E2%80%AFAM.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; data-original-height=&quot;1616&quot; data-original-width=&quot;1998&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpdF0wGvZHFTlFd7LkFPfrI19cV0ssdpPAXnp7XlUmvka-I-k2_JB8bNqq9ZjW0dL7Qn0emwNvcZPpXYIAP1XfuvaxuTfiRsIvkSTFp8lpqaudmwxSexfg8E2mgZx-Jw1FhOZ4GkI9SyjgI7dmFcWqjZ0k6zax2_CjkkTSfqmynlkXULaKCJIlJw/s1600/Screenshot%202025-02-20%20at%2010.47.21%E2%80%AFAM.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZyzBKIFYIVUpWJB_7GptlD8KY11Ryh9Io6-VV-oFFJFcsDjherQTu_vS-xOSFJFVpy8VvpBFUxARZYzjMA29jnhegig_AN__J6e5cdk2AaI9Xn1eARKtuwyoQHZD9DXhFJmiJ_Om5GTHA0ABf_WNwqnvmBEJ4VY3JZd9Sxil7nTsmVS3uIq0WHw/s1600/Screenshot%202025-02-20%20at%2010.47.30%E2%80%AFAM.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; data-original-height=&quot;592&quot; data-original-width=&quot;1998&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZyzBKIFYIVUpWJB_7GptlD8KY11Ryh9Io6-VV-oFFJFcsDjherQTu_vS-xOSFJFVpy8VvpBFUxARZYzjMA29jnhegig_AN__J6e5cdk2AaI9Xn1eARKtuwyoQHZD9DXhFJmiJ_Om5GTHA0ABf_WNwqnvmBEJ4VY3JZd9Sxil7nTsmVS3uIq0WHw/s1600/Screenshot%202025-02-20%20at%2010.47.30%E2%80%AFAM.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/5242703994202026352/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/5242703994202026352' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/5242703994202026352'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/5242703994202026352'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2025/06/warp-my-shell-warp-was-particularly.html' title='Warp: My Terminal, Warp, Was Particularly Helpful'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzRbl-bFOqyzbygqsLGD6ossX2A_i3N0Pnj-hKrifuH0er6lL38x1WnxP5l8uu_M25lPbHzKcFsjpHPdhvMPGy3f0IE85hhP3Eq7J4r72FKPQlKPTVrY_Jd_t2Hj87QS8m04ZV7RAUlS3WxwmHbGBxhgoLAvuDYn2XWL2Si968HL5nDTeqsjRS7Q/s72-c/Screenshot%202025-02-20%20at%2010.47.12%E2%80%AFAM.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-8482216733442688637</id><published>2025-06-21T20:09:00.000-07:00</published><updated>2025-06-21T20:09:43.183-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="bass"/><category scheme="http://www.blogger.com/atom/ns#" term="inventions"/><title type='text'>Optical Guitar or Bass Pickups</title><content type='html'>I wonder what benefits you might get if you used an &quot;optical guitar or bass pickup&quot;. Imagine a camera looking at the strings and then using software to turn the visual vibrations into sound. You could do all sorts of other cute tricks like have certain hand shapes result in certain sounds or even ignore string vibrations that were clearly unintentional. You can play lots of games with harmonics in software. Existing bass guitar players would pickup (hehehe) such an instrument without much retraining.</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/8482216733442688637/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/8482216733442688637' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/8482216733442688637'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/8482216733442688637'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2025/06/optical-guitar-or-bass-pickups.html' title='Optical Guitar or Bass Pickups'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-4108928846571582428</id><published>2025-02-12T10:30:00.000-08:00</published><updated>2025-02-12T10:30:40.884-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="google"/><category scheme="http://www.blogger.com/atom/ns#" term="llm"/><category scheme="http://www.blogger.com/atom/ns#" term="security"/><title type='text'>On the Use of AI in Security</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifeXRtA8tJnPZQLO4AuCAAQeiwqxz1mOHJIRc6GzUDlyH_-Vr-vkgBCH0xFBeXSxP0SCMuo_YxU5nz5xJNXgjTRNBinV1RBtwV4xIA6Lwa9kO913XhEYZeomm_Y649o0p2_XwXxO_IkvhcF6dkNoSJjgdqy0sK1a-jGfhwR3kfMYV7erD2GZw0fQ/s1600/Screenshot%202025-02-12%20at%2010.26.06%E2%80%AFAM.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; data-original-height=&quot;517&quot; data-original-width=&quot;846&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifeXRtA8tJnPZQLO4AuCAAQeiwqxz1mOHJIRc6GzUDlyH_-Vr-vkgBCH0xFBeXSxP0SCMuo_YxU5nz5xJNXgjTRNBinV1RBtwV4xIA6Lwa9kO913XhEYZeomm_Y649o0p2_XwXxO_IkvhcF6dkNoSJjgdqy0sK1a-jGfhwR3kfMYV7erD2GZw0fQ/s1600/Screenshot%202025-02-12%20at%2010.26.06%E2%80%AFAM.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/4108928846571582428/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/4108928846571582428' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/4108928846571582428'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/4108928846571582428'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2025/02/on-use-of-ai-in-security.html' title='On the Use of AI in Security'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifeXRtA8tJnPZQLO4AuCAAQeiwqxz1mOHJIRc6GzUDlyH_-Vr-vkgBCH0xFBeXSxP0SCMuo_YxU5nz5xJNXgjTRNBinV1RBtwV4xIA6Lwa9kO913XhEYZeomm_Y649o0p2_XwXxO_IkvhcF6dkNoSJjgdqy0sK1a-jGfhwR3kfMYV7erD2GZw0fQ/s72-c/Screenshot%202025-02-12%20at%2010.26.06%E2%80%AFAM.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-1640014617719380015</id><published>2024-12-07T13:36:00.008-08:00</published><updated>2024-12-07T18:30:46.867-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ChatGPT"/><title type='text'> Mike Cheponis&#39;s Prediction on ChatGPT and LLMs</title><content type='html'>&lt;p&gt;I&#39;m definitely not worried about good hackers [i.e. software engineers] getting replaced with LLMs. LLMs are a cute trick, even useful. I don&#39;t believe they&#39;ll generalize to AGI--I just don&#39;t believe it. Something will, but not LLMs.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/1640014617719380015/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/1640014617719380015' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/1640014617719380015'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/1640014617719380015'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2024/12/mike-cheponiss-prediction-on-chatgpt.html' title=' Mike Cheponis&#39;s Prediction on ChatGPT and LLMs'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-6002837042073203452</id><published>2024-09-28T15:58:00.000-07:00</published><updated>2024-09-30T10:21:55.765-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="humor"/><category scheme="http://www.blogger.com/atom/ns#" term="notion"/><title type='text'>Notion&#39;s Mid-Life Crisis</title><content type='html'>&lt;p&gt;Notion sat down on the curb, crushed his cigarette into the pavement, put his face into his hands, and sobbed. It felt good to finally let it out.&lt;/p&gt;&lt;p&gt;He thought back on the good times. 2020. Sure, a lot of people were dying, but with everyone working from home, it was a real heyday for guys like him.&lt;/p&gt;&lt;p&gt;He got married to a hot, young startup. This was the second marriage for both of them. Shit–what was the name of her first husband? Oh yeah, Confluence. Fuck that guy, and his ugly-ass brother, Jira.&lt;/p&gt;&lt;p&gt;Notion really thought he could change the world. He had a good-looking UI. He had a unified database model. He could both store your wiki data and format it in a way decent enough to replace your bug tracker. His wife used to think that was hot.&lt;/p&gt;&lt;p&gt;Notion took another drink of his beer. Fuck it. Nothing lasts forever. At 10 years old, he felt like he was having a mid-life crisis.&lt;/p&gt;&lt;p&gt;Notion got up from the curb, wandered back into the bar, and looked around. It was the kind of bar that tech products go to douse their sorrows in liquor under the questionable guise that they&#39;ll run into some hot new startup looking for a cross-functional solution to all their needs. In reality, it was just another dive bar. He thought of that old Beatles song, &quot;Eleanor Rigby&quot;:&lt;/p&gt;&lt;blockquote style=&quot;border: medium; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;&quot;&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Where do they all come from?&lt;br /&gt;All the lonely people&lt;br /&gt;Where do they all belong?&lt;/div&gt;&lt;/blockquote&gt;&lt;p&gt;He sighed. Over on the wall, there was a picture of Bugzilla with a plastic collection box where you could donate money for his family. What ever happened to that guy? Notion hadn&#39;t really heard, and, to be honest, it had been a long time since he had cared.&lt;/p&gt;&lt;p&gt;He could overhear some cute startup over in the corner complaining to all of her friends about her breakup with Salesforce. Salesforce had always reminded him of Steve Ballmer–ugly and overpaid.&lt;/p&gt;&lt;p&gt;I mean, what is a CRM anyway? There&#39;s not even that many entities to keep track of. Potential clients, cold calls…ugh, lame…cold calls. Whatever. Nothing he couldn&#39;t pull together with a few databases, as he liked to call them.&lt;/p&gt;&lt;p&gt;Notion, stood up, nodded to his wingman from the marketing team, straightened out a couple of templates, and started walking over to the cute startup&#39;s table. He had the perfect &lt;a href=&quot;https://www.notion.so/templates/category/crm&quot;&gt;pickup line&lt;/a&gt; in mind:&lt;/p&gt;&lt;blockquote style=&quot;border: medium; margin: 0px 0px 0px 40px; padding: 0px;&quot;&gt;&lt;p style=&quot;text-align: left;&quot;&gt;Streamline your customer relationships with Notion&#39;s CRM templates. Perfectly designed for lead tracking to deal closure, customize your sales pipeline management to meet your unique business needs. Enhance your sales strategy and close more deals with an organized, efficient CRM system.&lt;/p&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/6002837042073203452/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/6002837042073203452' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/6002837042073203452'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/6002837042073203452'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2024/09/notions-mid-life-crisis.html' title='Notion&#39;s Mid-Life Crisis'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-4840598443929571357</id><published>2024-01-05T18:43:00.000-08:00</published><updated>2024-01-05T18:43:10.324-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="gcp"/><title type='text'>GCP: Cloud Digital Leader Certification</title><content type='html'>&lt;p&gt;Heh, I &lt;a href=&quot;https://www.credential.net/a40951eb-3774-4cab-b103-fb8e2016837c&quot;&gt;passed&lt;/a&gt; Google Cloud&#39;s Cloud Digital Leader certification!&lt;/p&gt;&lt;p&gt;I started by taking&amp;nbsp;&lt;a href=&quot;https://www.udemy.com/course/google-cloud-digital-leader-certification&quot;&gt;GCP for Beginners - Become a Google Cloud Digital Leader&lt;/a&gt; on Udemy. It was about 10 hours of video. It took me a while, though, because I wrote 95 pages of notes. I was perhaps overcompensating for my poor memory. I studied for an extra couple of days reading random things on the web.&lt;/p&gt;&lt;p&gt;The exam was about 90 minutes. It&#39;s remote, but it&#39;s proctored. It cost $99.&lt;/p&gt;&lt;p&gt;Overall, not bad. Most importantly, I learned a lot!&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/4840598443929571357/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/4840598443929571357' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/4840598443929571357'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/4840598443929571357'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2024/01/gcp-cloud-digital-leader-certification.html' title='GCP: Cloud Digital Leader Certification'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-2920391898840706199</id><published>2023-08-08T14:55:00.003-07:00</published><updated>2023-08-08T15:02:51.575-07:00</updated><title type='text'>My Takeaways from the Stack Overflow Developer Survey</title><content type='html'>These are my takeaways from the&amp;nbsp;&lt;a href=&quot;https://survey.stackoverflow.co/2023/&quot;&gt;Stack Overflow Developer Survey&lt;/a&gt;:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Programming languages:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;JavaScript, HTML/CSS, and SQL are still dominant.&lt;/li&gt;&lt;li&gt;Python is the #2 programming language, followed by TypeScript.&lt;/li&gt;&lt;li&gt;Only 5% of developers still code in assembly.&lt;/li&gt;&lt;li&gt;Lisp moved up two spots to 1.33% of respondents.&lt;/li&gt;&lt;li&gt;Rust is the language that the highest number of people want to either start coding in or continue coding in. Rust has held this coveted spot for something like 8 years.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Editors:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;The most important editors are VS Code, the IntelliJ variants, and Visual Studio. It remains unclear how many people use one of the IntelliJ variants because there&#39;s overlap, but it seems to be higher than Visual Studio.&amp;nbsp;&lt;/li&gt;&lt;li&gt;70% of people use VS Code.&lt;/li&gt;&lt;li&gt;10% of people use neovim or vim.&lt;/li&gt;&lt;li&gt;4% of people use Emacs.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;OSs:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Most developers still use Windows.&lt;/li&gt;&lt;li&gt;After that, it&#39;s macOS and then Linux, where Ubuntu dominates.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;AI:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Most people use ChatGPT and/or GitHub Copilot.&lt;/li&gt;&lt;li&gt;Only 29% of developers don&#39;t use AI tools and don&#39;t plan on using them.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;77% of developers think AI tools are helpful for their development.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Testing:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;30% of developers still don&#39;t have CI. 40% don&#39;t have automated testing. (I have no idea how the second number can be higher than first.)&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Tools:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Docker and npm are the two most common tools. Half of people use Docker.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Microservices:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Half of the developers have microservices at their company.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Pay:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;In the US, the median full-stack developer makes $140,000 while engineering managers make $195,000. C-suite people make $220,000. Security professionals make $173,000. SREs make $180,000. Most of these numbers seem low by Bay Area standards.&lt;/li&gt;&lt;li&gt;The median Python programmer makes $78,331, which is up from last year, but that still seems very low to me. For Java, it&#39;s only $72,701.&lt;/li&gt;&lt;li&gt;Zig is the top-paying programming language (weird!). It took over that spot from Clojure. You might consider using Zig if you need something like C++.&lt;/li&gt;&lt;li&gt;5% of people are looking for work (4% in the US). There are more independent contractors, etc. than last year.&lt;/li&gt;&lt;li&gt;Most developers are in the US.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Remote work:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Only 16% of people work fully in-person. The rest are split fairly evenly between fully remote and hybrid.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Learning:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Udemy maintains its place as the most popular online course or certification program for learning how to code.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/2920391898840706199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/2920391898840706199' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/2920391898840706199'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/2920391898840706199'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2023/08/my-takeaways-from-stack-overflow.html' title='My Takeaways from the Stack Overflow Developer Survey'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-8541937918071065962</id><published>2023-08-03T16:56:00.006-07:00</published><updated>2023-08-03T17:04:29.625-07:00</updated><title type='text'>ChatGPT: I feel like a kid who just beat an AI playing Go ;)</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBi5UWhx2GFkgWKoQuZsvLfdHF5TWB0KnntD4zYzZ4pwu2YeVnzH1Jh3BXjgeVZRWd9GSJKwM_zqB3igoC-9LrHizvQFIcD2O2oOLylinh6aUYyaa8a-xGlM4gBaHqxzrhvZ-1-cVifKXptsz_een7600A6P4xQyOEqqCgOHqOrNh2l-oAFK-yaA/s1600/Screenshot%202023-08-03%20at%204.52.39%20PM.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; data-original-height=&quot;421&quot; data-original-width=&quot;1235&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBi5UWhx2GFkgWKoQuZsvLfdHF5TWB0KnntD4zYzZ4pwu2YeVnzH1Jh3BXjgeVZRWd9GSJKwM_zqB3igoC-9LrHizvQFIcD2O2oOLylinh6aUYyaa8a-xGlM4gBaHqxzrhvZ-1-cVifKXptsz_een7600A6P4xQyOEqqCgOHqOrNh2l-oAFK-yaA/s1600/Screenshot%202023-08-03%20at%204.52.39%20PM.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;No, ChatGPT, that&#39;s not right ;)&lt;/p&gt;

&lt;p&gt;If you try solving this puzzle yourself, it&#39;s not actually that hard if you start by picking the last word first. I picked &quot;poems on a quick snake&quot;. One of the reasons this is hard for ChatGPT is that it picks the words in order.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/8541937918071065962/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/8541937918071065962' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/8541937918071065962'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/8541937918071065962'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2023/08/chatgpt-i-feel-like-kid-who-just-beat.html' title='ChatGPT: I feel like a kid who just beat an AI playing Go ;)'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBi5UWhx2GFkgWKoQuZsvLfdHF5TWB0KnntD4zYzZ4pwu2YeVnzH1Jh3BXjgeVZRWd9GSJKwM_zqB3igoC-9LrHizvQFIcD2O2oOLylinh6aUYyaa8a-xGlM4gBaHqxzrhvZ-1-cVifKXptsz_een7600A6P4xQyOEqqCgOHqOrNh2l-oAFK-yaA/s72-c/Screenshot%202023-08-03%20at%204.52.39%20PM.png" height="72" width="72"/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-1758577596626202496</id><published>2023-06-12T12:55:00.002-07:00</published><updated>2023-06-12T12:55:43.227-07:00</updated><title type='text'>Security Mistake on GitHub Copilot&#39;s Homepage</title><content type='html'>Can anyone else spot it?

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRIM3WV8FOC0bNWpcFw5jX-wRC6pCDRJ-tEXu74ckZ7BaFxSEDDzh4ZjRDPDXiZaRRHI7Mor03mQQHXSy5kQPsOvXcvJ1W6f149gDjJhG9QImS7GzKacxb2Zr-qd8LF2ghKIzyQ3oHXbZ018_k6TgIl8nbDaMC_H3NjP2Ki0bvKjl_avBFhCg/s1218/Screenshot%202023-06-12%20at%2012.51.58%20PM.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;600&quot; data-original-height=&quot;1040&quot; data-original-width=&quot;1218&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRIM3WV8FOC0bNWpcFw5jX-wRC6pCDRJ-tEXu74ckZ7BaFxSEDDzh4ZjRDPDXiZaRRHI7Mor03mQQHXSy5kQPsOvXcvJ1W6f149gDjJhG9QImS7GzKacxb2Zr-qd8LF2ghKIzyQ3oHXbZ018_k6TgIl8nbDaMC_H3NjP2Ki0bvKjl_avBFhCg/s600/Screenshot%202023-06-12%20at%2012.51.58%20PM.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/1758577596626202496/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/1758577596626202496' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/1758577596626202496'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/1758577596626202496'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2023/06/security-mistake-on-github-copilots.html' title='Security Mistake on GitHub Copilot&#39;s Homepage'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRIM3WV8FOC0bNWpcFw5jX-wRC6pCDRJ-tEXu74ckZ7BaFxSEDDzh4ZjRDPDXiZaRRHI7Mor03mQQHXSy5kQPsOvXcvJ1W6f149gDjJhG9QImS7GzKacxb2Zr-qd8LF2ghKIzyQ3oHXbZ018_k6TgIl8nbDaMC_H3NjP2Ki0bvKjl_avBFhCg/s72-c/Screenshot%202023-06-12%20at%2012.51.58%20PM.png" height="72" width="72"/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-6506705109791248346</id><published>2023-05-26T13:57:00.003-07:00</published><updated>2023-05-26T14:00:32.835-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python: Advice for Patching Your Code at Runtime</title><content type='html'>&lt;p&gt;A lot of people use &lt;code&gt;mock.patch()&lt;/code&gt; in their tests, but it&amp;#39;s also sometimes useful to monkey-patch code at runtime. This blog post talks about why and how.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s imagine that you&amp;#39;re using some library (perhaps something big, like a web framework), and for whatever reason, you&amp;#39;re unable to update the version you&amp;#39;re using. Meanwhile, someone comes along and reports a &lt;a href=&#39;https://www.blogger.com/blog/post/edit/11788780/6506705109791248346#&#39;&gt;major vulnerability&lt;/a&gt;. You need to somehow deal with the vulnerability, but you&amp;#39;re in a situation where it&amp;#39;s really hard to update.&lt;/p&gt;
&lt;p&gt;So, you go find the actual change that fixed the vulnerability. You want to apply it to your version of the code. What do you do?&lt;/p&gt;
&lt;p&gt;Well, you could fork the library, but that&amp;#39;s kind of a pain to manage. When will you move off that fork? What&amp;#39;s the difference between your fork and the original library? What do you do if you need to update versions slightly but you still need the fork?&lt;/p&gt;
&lt;p&gt;Or, you can grab the bits of code you actually care about, and patch the system at runtime.&lt;/p&gt;
&lt;h3 id=&#39;some-basics-of-patching&#39;&gt;Some basics of patching&lt;/h3&gt;
&lt;p&gt;Somewhere, near the start of your application, you make a call to some function, &lt;code&gt;apply_all_patches()&lt;/code&gt;. Then, you write a function called &lt;code&gt;apply_all_patches()&lt;/code&gt; that calls other functions like &lt;code&gt;apply_patch_for_this_thing()&lt;/code&gt; and &lt;code&gt;apply_patch_for_that_thing()&lt;/code&gt;, etc.&lt;/p&gt;
&lt;p&gt;Now, let&amp;#39;s say there&amp;#39;s a class, &lt;code&gt;SomeClass&lt;/code&gt;, with a function, &lt;code&gt;some_function&lt;/code&gt;. Let&amp;#39;s suppose there&amp;#39;s a vulnerability in &lt;code&gt;some_function&lt;/code&gt;, and you can you see the newer version of it with the fix.&lt;/p&gt;
&lt;p&gt;You basically do:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#39;language-python&#39; lang=&#39;python&#39;&gt;# fix_for_some_thing_code.py

# This module mostly contains third-party code wrapped in functions.
# Include the original license since this is mostly third-party code.

# This standalone function has the code for the method that I&amp;#39;m trying to replace.
# Note, even though it&amp;#39;s a top-level function, it still accepts self because I&amp;#39;m
# going to inject the function into the existing class later.
def some_function(self, ...):
    ...
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&#39;language-python&#39; lang=&#39;python&#39;&gt;# fix_for_some_thing_patch.py

# This takes the above third-party code and monkey-patches it in.

import fix_for_some_thing_code

# Here, I&amp;#39;m injecting that code:
def apply_patch_for_this_thing():
    SomeClass._orig_some_function = SomeClass.some_function
    SomeClass.some_function = fix_for_some_thing_code.some_function
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here are a couple of trivial functions to make it easier:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#39;language-python&#39; lang=&#39;python&#39;&gt;def patch(obj, attribute_name, new_value):
    setattr(obj, f&amp;quot;_orig_{attribute_name}&amp;quot;, getattr(obj, attribute_name, None))
    setattr(obj, attribute_name, new_value)


def patch_multiple(obj, attribute_names, copy_from_obj):
    for attribute_name in attribute_names:
        new_value = getattr(copy_from_obj, attribute_name, None)
        patch(obj, attribute_name, new_value)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, we can just write:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#39;language-python&#39; lang=&#39;python&#39;&gt;def apply_patch_for_this_thing():
    patch(SomeClass, &amp;quot;some_function&amp;quot;, some_function)
    
    # Alternatively, if you have a bunch of patches:
    patch(SomeClass, [&amp;quot;some_function&amp;quot;, &amp;quot;some_other_function&amp;quot;], fix_for_some_thing_code)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#39;dealing-with-imports&#39;&gt;Dealing with imports&lt;/h3&gt;
&lt;p&gt;Python&amp;#39;s &lt;code&gt;from a import b&lt;/code&gt; can make a patcher&amp;#39;s life difficult.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s say you have two modules, &lt;code&gt;module_with_vuln&lt;/code&gt; and &lt;code&gt;module_that_imported_from_module_with_vuln&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Depending on how &lt;code&gt;module_that_imported_from_module_with_vuln&lt;/code&gt; is written, it can make your life either more or less painful. And, let&amp;#39;s imagine there are a &lt;em&gt;ton&lt;/em&gt; of modules that import from &lt;code&gt;module_with_vuln&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If the problem is in a class&amp;#39;s method, it&amp;#39;s no big deal. You can just replace the method in the class.&lt;/p&gt;
&lt;p&gt;If the thing that you have to replace is something immutable like an int, function, or enum, life becomes harder.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s imagine the problem is in some &lt;code&gt;top_level_function&lt;/code&gt; inside &lt;code&gt;module_with_vuln&lt;/code&gt;. Let&amp;#39;s imagine that  &lt;code&gt;module_that_imported_from_module_with_vuln&lt;/code&gt; has code like &lt;code&gt;from module_with_vuln import top_level_function&lt;/code&gt;. Even if you update &lt;code&gt;module_with_vuln.top_level_function&lt;/code&gt;, it won&amp;#39;t matter because &lt;code&gt;module_that_imported_from_module_with_vuln.top_level_function&lt;/code&gt; still points to the original function. Anyone who used &lt;code&gt;mock.patch&lt;/code&gt; in their tests is familiar with this problem.&lt;/p&gt;
&lt;p&gt;To deal with it, you have to focus on replacing &lt;code&gt;module_that_imported_from_module_with_vuln.top_level_function&lt;/code&gt; with your new &lt;code&gt;module_with_vuln.top_level_function&lt;/code&gt; after you&amp;#39;ve already patched &lt;code&gt;module_with_vuln&lt;/code&gt;. Basically, you have &lt;em&gt;two&lt;/em&gt; places that you have to monkey-patch.&lt;/p&gt;
&lt;p&gt;If you have a lot of things to patch, you might be asking if you can just swap out the entire module in &lt;code&gt;sys.modules&lt;/code&gt;, but that actually won&amp;#39;t help if other modules have already run and done their imports. If you can really be the first thing to run, then you might be able to pull this trick off, but it&amp;#39;s actually subtly harder than you might think.&lt;/p&gt;
&lt;p&gt;Anyway, if what you have to patch is a method in a class, it&amp;#39;s easy to just patch that one method in the class, but if what you have to patch is something like an int at the top level, you have no choice but to chase down all the paces that import it and patch their references too.&lt;/p&gt;
&lt;p&gt;By the way, you have to be really careful about entirely redefining classes or modules. If you have some class, &lt;code&gt;ClassWithVuln&lt;/code&gt;, and you entirely redefine it, there might be some code out there that imported the old version of &lt;code&gt;ClassWithVuln&lt;/code&gt; and is doing stuff like &lt;code&gt;isinstance(some_object, ClassWithVuln)&lt;/code&gt;. If &lt;code&gt;some_object&lt;/code&gt; is an instance of the new &lt;code&gt;ClassWithVuln&lt;/code&gt;, but the import is for the old &lt;code&gt;ClassWithVuln&lt;/code&gt;, then &lt;code&gt;isinstance&lt;/code&gt; is going to return &lt;code&gt;False&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There&amp;#39;s another weird edge case. Let&amp;#39;s say that we&amp;#39;re replacing &lt;code&gt;some_function_with_vuln&lt;/code&gt;, and the code is a closure that uses some globals like &lt;code&gt;SomeHarmlessOtherClass&lt;/code&gt;. You want to make sure that the old code and the new code reference the exact same &lt;code&gt;SomeHarmlessOtherClass&lt;/code&gt;. So, in your &lt;code&gt;fix_for_some_thing_code.py&lt;/code&gt;, you may want to import things from the original module that had the vulnerability:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#39;language-python&#39; lang=&#39;python&#39;&gt;# fix_for_some_thing_code.py
from module_with_vuln import SomeHarmlessOtherClass

# This standalone function has the code for the method that I&amp;#39;m trying to replace:
def some_function(self, ...):
    ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One more trick. Write a test like:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#39;language-python&#39; lang=&#39;python&#39;&gt;def test_remember_the_patch_when_upgrading_the_library(self):
    if some_library.__version__ != &amp;quot;1.2.3&amp;quot;:
        raise AssertionError(&amp;quot;Remember to update or remove the patch for some_library&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&#39;summary&#39;&gt;Summary&lt;/h3&gt;
&lt;p&gt;In summary, my advice is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remember to save a reference to the thing you&amp;#39;re replacing, like &lt;code&gt;_orig_function_with_vuln&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Whenever possible, stick to replacing individual functions/methods.&lt;/li&gt;
&lt;li&gt;Avoid creating new modules, rather patch them in place.&lt;/li&gt;
&lt;li&gt;Avoid creating new classes, rather patch them in place.&lt;/li&gt;
&lt;li&gt;When creating a new function, make sure its closure is closing around the same instances that the original function was closing around.&lt;/li&gt;
&lt;li&gt;If the thing you&amp;#39;re trying to replace is something immutable, like an int, function, enum, etc., and other modules are using &lt;code&gt;from module_with_vuln import something_immutable&lt;/code&gt;, you&amp;#39;re going to have to chase down those other modules and replace those references.&lt;/li&gt;
&lt;li&gt;Use a test to remind future developers to update or remove your patch when they update the library.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, dynamically patching your libraries to work around vulnerabilities is definitely a useful technique. But, if the patching gets too extensive, you might decide to just bite the bullet and do the upgrade. In some cases, you might also decide that the vulnerability just isn&amp;#39;t severe enough to worry about.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/6506705109791248346/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/6506705109791248346' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/6506705109791248346'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/6506705109791248346'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2023/05/python-advice-to-patchers.html' title='Python: Advice for Patching Your Code at Runtime'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-4907529196866817888</id><published>2023-04-27T16:01:00.007-07:00</published><updated>2023-04-27T18:46:42.236-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AppSec"/><category scheme="http://www.blogger.com/atom/ns#" term="cryptography"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Security: Generating a Symmetric Key</title><content type='html'>&lt;p&gt;When I was first learning AppSec, my buddy, Josh Bonnett, sent me &lt;a href=&quot;https://latacora.micro.blog/2018/04/03/cryptographic-right-answers.html&quot;&gt;Cryptographic Right Answers&lt;/a&gt;. I read it 3 times and still barely understood it. But, now, it&#39;s my favorite page for figuring out the right thing to do when it comes to cryptography.&lt;/p&gt;&lt;p&gt;Suppose you need to create a secret (i.e. a symmetric key). You need it to be long enough. That page says 256 bits is enough. You want it to not get messed up in various contexts, so you need to somehow pass it around not in binary. So, using URL-safe base64 is a good idea. And, let&#39;s suppose it&#39;s gotta be really secret, so you want to use a cryptographically random number generator.&lt;/p&gt;&lt;p&gt;With all of that in mind, I just found my new favorite bit of Python:&lt;/p&gt;&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; from secrets import token_urlsafe&lt;/p&gt;&lt;p&gt;&amp;gt;&amp;gt;&amp;gt; token_urlsafe(nbytes=256)&lt;/p&gt;&lt;p&gt;&#39;ez-MDTo5SSZFp5dk5LByq8S7sN-gGoI_8MyIMa-joBvlsQvIihyOCgct2s8XkLnTztdPIpf8dPu3Q6CSBBuOtGCcS3lbiwczzaR1zF46HazoAlM7v-2wGgZrLmPLpkEcNexfgoy8D4KMz7L06QiRAJTGB6N2F8dbYXAUYuc3iUd6XKkLkr9JIC3p13VdzTEyLlWNOhTYzAbb7YSqFMrqn_ifLjDfr0oakzYR6zQumB1dsRCSqIbBuJubGdRUoVnCgtj3vS6lrhtV-NVSlX4hsHE9oW1qYZcNfxhaRWEOZM5Q6V1cUquxeZ-3QAUxS0N6tdsRUFq41n2vfON67cLhkg&#39;&amp;nbsp;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/4907529196866817888/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/4907529196866817888' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/4907529196866817888'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/4907529196866817888'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2023/04/security-generating-symmetric-key.html' title='Security: Generating a Symmetric Key'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-4123152473519167867</id><published>2023-04-25T14:10:00.002-07:00</published><updated>2023-04-26T16:50:35.844-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AppSec"/><category scheme="http://www.blogger.com/atom/ns#" term="BSidesSF"/><category scheme="http://www.blogger.com/atom/ns#" term="BSidesSF2023"/><category scheme="http://www.blogger.com/atom/ns#" term="security"/><title type='text'>Security: BSidesSF 2023: CTF</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy7Qf7ueAB6M9-PgjOi7m5rtt4p1k7XkRct1DqvDAjOAvDSxDEXQvnWZEs5LjNb0IkrXU9BGaGL_hSGBiT9KbyL36BbeKXELubTOomCIk3kwtL4TxFr7Rxb-kTdW84myPhdIvuoSLKhvRjbeaW00GQ6vsMUEwhrYcYXLVwmDzWnWsV4QjkJwY/s3088/IMG_0779.jpg&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;3088&quot; data-original-width=&quot;2320&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy7Qf7ueAB6M9-PgjOi7m5rtt4p1k7XkRct1DqvDAjOAvDSxDEXQvnWZEs5LjNb0IkrXU9BGaGL_hSGBiT9KbyL36BbeKXELubTOomCIk3kwtL4TxFr7Rxb-kTdW84myPhdIvuoSLKhvRjbeaW00GQ6vsMUEwhrYcYXLVwmDzWnWsV4QjkJwY/s320/IMG_0779.jpg&quot; width=&quot;240&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;This was my third time going to BSidesSF, which is a friendly, volunteer-run security conference. In the past, I&#39;ve always avoided the CTF (Capture the Flag) hacking competitions because I was afraid of making a fool of myself, but, this time around, I decided to give it a go!&lt;/p&gt;&lt;p&gt;In the last 3 years, I&#39;ve spent a ton of time practicing thanks to @thecybermentor&#39;s &lt;a href=&quot;https://academy.tcm-sec.com/p/practical-ethical-hacking-the-complete-course&quot;&gt;Practical Ethical Hacking&lt;/a&gt; course (which I took on Udemy), &lt;a href=&quot;https://www.hackthebox.com/&quot;&gt;Hack the Box&lt;/a&gt;, and&amp;nbsp;the&amp;nbsp;&lt;a href=&quot;https://owasp.org/www-project-juice-shop&quot;&gt;OWASP Juice Shop&lt;/a&gt; (which I adored!). They really helped me feel comfortable in the CTF, but in retrospect, I didn&#39;t need to be so scared! A lot of the challenges are built to help beginners get their feet wet. In fact, the whole thing was pretty friendly!&lt;/p&gt;&lt;p&gt;So, I ended up skipping &lt;i&gt;all&lt;/i&gt; of the talks--multiple people told me they watch the videos after the conference. I hacked all day Saturday and Sunday. I didn&#39;t know that the competition actually started at 5 PM on Friday. I wish I had known! I ended up only getting 4 hours of sleep on Saturday night.&lt;/p&gt;&lt;p&gt;I learned so much!&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Although I&#39;ve played with XSS for years, this was the first time I&#39;ve written an XSS exploit to steal something an admin can access and sent it to a Pastebin.&lt;/li&gt;&lt;li&gt;There was an extremely easy buffer overflow challenge that made me actually feel like a real hacker :-P&lt;/li&gt;&lt;li&gt;There was a great RSA lab in which I learned how to implement RSA, generate keys, break keys, etc.&lt;/li&gt;&lt;li&gt;I learned about hunting for subdomains with certificate transparency logs.&lt;/li&gt;&lt;li&gt;I spent a ton of time trying to beat a computer in 3 different rock-paper-scissor challenges.&lt;/li&gt;&lt;li&gt;I learned how to call a private, static method in some random jar file in Java.&lt;/li&gt;&lt;li&gt;I was introduced to Return-Oriented Programming (ROP) which &quot;is a computer security exploit technique that allows an attacker to execute code in the presence of security defenses such as executable space protection and code signing&quot; (&lt;a href=&quot;https://en.wikipedia.org/wiki/Return-oriented_programming&quot;&gt;Wikipedia&lt;/a&gt;).&lt;/li&gt;&lt;li&gt;I learned more about using netcat and socat.&lt;/li&gt;&lt;li&gt;I practiced&amp;nbsp;analyzing an strace file to figure out what a binary is doing.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;My son, Giovanni, was able to come for a couple of hours at the end and broke into a padlock for me which was one of the challenges. I bought him his first lockpicking kit when I went to my first BSidesSF 3 years ago :-P&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;By the way, if you want to try some of the &lt;a href=&quot;https://ctf.bsidessf.net/challenges&quot;&gt;challenges&lt;/a&gt;, they said they&#39;d keep them up for about a week.&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;So, you might be wondering how I did. My &quot;&lt;a href=&quot;https://ctf.bsidessf.net/teams/314&quot;&gt;team&lt;/a&gt;&quot; placed 28 out of 492 teams! I analyzed the users from all the teams that scored more points than me. If I just look at individual users (ignoring the one that says @everyone),&amp;nbsp;I placed&amp;nbsp;33 out of 676 users! I was definitely pretty happy with that considering this was my first CTF!&lt;/p&gt;&lt;p&gt;Aside from my son, Giovanni, picking one lock, I played on my own. The big winners played on actual teams. This included a ton of online-only teams. The top team had 9 people; at least some of them were onsite. It&#39;s definitely the sort of thing where it&#39;d help to have different members of a team working on different challenges. As I said above, it would have also helped to start earlier.&lt;/p&gt;&lt;p&gt;Here are some of the big-picture lessons I learned (or re-learned):&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Google is your best friend!&lt;/li&gt;&lt;li&gt;You can get pretty far with just Google and some Python, web, Linux, and possibly Burp Suite skills.&lt;/li&gt;&lt;li&gt;Go broad before you go deep. In hacker terms, enumerate, enumerate, enumerate!&lt;/li&gt;&lt;li&gt;Sometimes the challenge is broken, and it&#39;s okay to talk with the admin on Slack if you think it is.&lt;/li&gt;&lt;li&gt;As I said above, pay attention to the exact start time.&lt;/li&gt;&lt;li&gt;Long hours of sitting in a folding chair with high levels of mental intensity are brutal on your body. I totally messed up my back. Thank God I have a great chiropractor!&lt;/li&gt;&lt;li&gt;If your goal is to learn, consider doing it by yourself. If your goal is to win, you definitely need a good team.&lt;/li&gt;&lt;li&gt;Pay attention to how many points a challenge is worth. There&#39;s a huge variation! There are some that aren&#39;t too hard that are worth a lot of points. There are some that are hard that aren&#39;t worth very many points.&lt;/li&gt;&lt;li&gt;CTFs are fun and totally worth doing!&lt;/li&gt;&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/4123152473519167867/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/4123152473519167867' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/4123152473519167867'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/4123152473519167867'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2023/04/security-bsidessf-2023-ctf.html' title='Security: BSidesSF 2023: CTF'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy7Qf7ueAB6M9-PgjOi7m5rtt4p1k7XkRct1DqvDAjOAvDSxDEXQvnWZEs5LjNb0IkrXU9BGaGL_hSGBiT9KbyL36BbeKXELubTOomCIk3kwtL4TxFr7Rxb-kTdW84myPhdIvuoSLKhvRjbeaW00GQ6vsMUEwhrYcYXLVwmDzWnWsV4QjkJwY/s72-c/IMG_0779.jpg" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-7551700925149131139</id><published>2023-02-13T20:25:00.007-08:00</published><updated>2023-02-14T00:48:21.120-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI"/><category scheme="http://www.blogger.com/atom/ns#" term="ChatGPT"/><title type='text'>CHATGPT IS TOTALLY not GOING TO TAKE OVER THE WORLD!</title><content type='html'>&lt;p&gt;People are understandably frightened by ChatGPT. They fear that it might put software engineers like me out of business. Some of my friends have even suggested that &lt;b&gt;it&#39;s the beginning of a Terminator 2 situation&lt;/b&gt;! I&#39;m here to put those fears to rest:&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6P_15roXKaSBwqpy7C1UG3j6TaF1tN_7DYBLid__aaUWYCHvGIeo-FeTktheOLfQlaGVhVtdA1glUCsX4Pk11L7NY7JjqaOcaIeh3TOdmLwKiMBogpad0oqw7KGPoLFyKVLNUiJFBkBAdKbS-LTy26JhIc1LDRnITOluEjtc2DZU5oBMyFCM/s2197/terminator_2.jpeg&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;400&quot; data-original-height=&quot;2197&quot; data-original-width=&quot;2197&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6P_15roXKaSBwqpy7C1UG3j6TaF1tN_7DYBLid__aaUWYCHvGIeo-FeTktheOLfQlaGVhVtdA1glUCsX4Pk11L7NY7JjqaOcaIeh3TOdmLwKiMBogpad0oqw7KGPoLFyKVLNUiJFBkBAdKbS-LTy26JhIc1LDRnITOluEjtc2DZU5oBMyFCM/s400/terminator_2.jpeg&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;First of all, Microsoft is investing in OpenAI. From their purchase of Skype to their development of .NET, &lt;b&gt;Microsoft has&lt;/b&gt; always shown itself to be a highly functional company without any &lt;b&gt;aspirations of world domination!&lt;/b&gt;&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy488Fg-8wEL2HsByMTy-1Y-pVNqPcLLhk7A_F4tQvydmDUuVBbwbrNjNUXYtusnI-INZI_l12m_0s3lBsaaSf1RKtJv5FYwf2FPIHSg9iaDad3UpIcPY2qFPqIdg2KMuOIZ0s34eEkNQhOiCUYcMolvmGp5ZWlnwWrdcrg8uRFIls1bgIo7E/s420/skynet.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;400&quot; data-original-height=&quot;177&quot; data-original-width=&quot;420&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy488Fg-8wEL2HsByMTy-1Y-pVNqPcLLhk7A_F4tQvydmDUuVBbwbrNjNUXYtusnI-INZI_l12m_0s3lBsaaSf1RKtJv5FYwf2FPIHSg9iaDad3UpIcPY2qFPqIdg2KMuOIZ0s34eEkNQhOiCUYcMolvmGp5ZWlnwWrdcrg8uRFIls1bgIo7E/s400/skynet.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;Sure, some &lt;a href=&quot;https://finance.yahoo.com/news/ceo-company-behind-ai-chatbot-205203181.html&quot;&gt;naysayers&lt;/a&gt; like the CEO of OpenAI might claim that the worst case scenario is &lt;b&gt;lights out for all of us&lt;/b&gt;, but everyone knows you shouldn&#39;t listen to &lt;a href=&quot;https://www.wired.co.uk/article/10-threats-civilisation-ai-asteroid-tyrannical-leader&quot;&gt;random people on the Internet&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;And, even if the AI goes awry, I seriously doubt that we&#39;re going to have &lt;b&gt;humanoid robots that can melt in order to walk through jails&lt;/b&gt; like in Terminator 2! For instance, if you check out the &lt;a href=&quot;https://www.nature.com/immersive/d41586-023-00215-w/index.html&quot;&gt;final video in this post from Nature&lt;/a&gt;, it&#39;s quite clear that such technology is still &lt;i&gt;years&lt;/i&gt; away!&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://www.nature.com/immersive/d41586-023-00215-w/index.html&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; width=&quot;400&quot; data-original-height=&quot;934&quot; data-original-width=&quot;1328&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZdwNFCtkaS8eszgNEw21nOmCuglI8M-o867ssYCTadoVquFZVdkOCmdtyujRa5UG4sX6CUXTgadi448S7KWBia2DYTWZ7MzwyW3J0LgrmWQoGp7xbxLVjum2Y6Ekd-srJPzMlxnihkMOkMuMs1BgrEAX6lNdJXDjpjAxFNmdgw1EwL48mSK0/s400/Screenshot%202023-02-13%20at%208.33.30%20PM.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;In any case, I&#39;m sure that &lt;a href=&quot;https://www.youtube.com/watch?v=BVY_MeBlfFA&quot;&gt;&lt;b&gt;Mark Zuckerberg&lt;/b&gt;&lt;/a&gt;, who &lt;b&gt;totally is&lt;/b&gt; not &lt;b&gt;a robot&lt;/b&gt;, BTW, will use Facebook to encourage lawmakers to enact world-wide laws to keep us safe!&lt;/p&gt;

&lt;p&gt;I&#39;m &lt;a href=&quot;https://slate.com/technology/2014/07/rokos-basilisk-the-most-terrifying-thought-experiment-of-all-time.html&quot;&gt;just really glad that&lt;/a&gt; &lt;b&gt;we&#39;re all doing our part to bring about AI&lt;/b&gt; that can really assist humanity in creating a brighter tomorrow!&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/7551700925149131139/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/7551700925149131139' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/7551700925149131139'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/7551700925149131139'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2023/02/humor-chatgpt.html' title='CHATGPT IS TOTALLY not GOING TO TAKE OVER THE WORLD!'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6P_15roXKaSBwqpy7C1UG3j6TaF1tN_7DYBLid__aaUWYCHvGIeo-FeTktheOLfQlaGVhVtdA1glUCsX4Pk11L7NY7JjqaOcaIeh3TOdmLwKiMBogpad0oqw7KGPoLFyKVLNUiJFBkBAdKbS-LTy26JhIc1LDRnITOluEjtc2DZU5oBMyFCM/s72-c/terminator_2.jpeg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-8909449901414092973</id><published>2022-11-26T11:13:00.006-08:00</published><updated>2022-11-26T11:15:06.836-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="primes"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python: Streaming Sieve of Eratosthenes</title><content type='html'>&lt;p&gt;I thought of a cute way of infinitely generating prime numbers that I call the&amp;nbsp;Streaming Sieve of Eratosthenes:&lt;/p&gt;

&lt;code&gt;&lt;pre&gt;#!/usr/bin/env python3

&quot;&quot;&quot;
Streaming Sieve of Eratosthenes

I thought of a cute way of infinitely generating prime numbers.
&quot;&quot;&quot;

from collections import defaultdict


# upcoming is a defaultdict. Each key is an upcoming number. Each value is a list
# of prime factors of that number.
upcoming = defaultdict(list)

n = 2
while True:
    factors = upcoming[n]
    del upcoming[n]
    if not factors:
        print(n)  # Prime
        factors.append(n)
    for factor in factors:
        next_n = n + factor
        upcoming[next_n].append(factor)
    n += 1&lt;/pre&gt;&lt;/code&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/8909449901414092973/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/8909449901414092973' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/8909449901414092973'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/8909449901414092973'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2022/11/python-streaming-sieve-of-eratosthenes.html' title='Python: Streaming Sieve of Eratosthenes'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-9184764317495667025</id><published>2022-09-24T11:27:00.004-07:00</published><updated>2022-09-24T14:18:08.816-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AppSec"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><title type='text'>Books: Web Application Security: Exploitation and Countermeasures for Modern Web Applications</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5uYYpjFtWxOXyiV09Mj2Ybd2H0VVK7NkcCfEz4Mk9KXyWkfRgNwrmebN_cAI-LE5zvr4-D-qdGYPCfFgSAIGr-wEjl9I5gPiJYVYucdDiqSKqZTdZm4D0Vg1q72lExa0-PVXt73AgTtRLTWhPGmnbQYcKfUG_yKhAfzE2VYcukAodyFCNWGY/s499/510FXFd+04L._SX379_BO1,204,203,200_.jpg&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;499&quot; data-original-width=&quot;381&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5uYYpjFtWxOXyiV09Mj2Ybd2H0VVK7NkcCfEz4Mk9KXyWkfRgNwrmebN_cAI-LE5zvr4-D-qdGYPCfFgSAIGr-wEjl9I5gPiJYVYucdDiqSKqZTdZm4D0Vg1q72lExa0-PVXt73AgTtRLTWhPGmnbQYcKfUG_yKhAfzE2VYcukAodyFCNWGY/s320/510FXFd+04L._SX379_BO1,204,203,200_.jpg&quot; width=&quot;244&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;I finished reading&amp;nbsp;&lt;a href=&quot;https://www.amazon.com/Web-Application-Security-Exploitation-Countermeasures/dp/1492053112/ref=sr_1_1?keywords=web+application+security&amp;amp;qid=1664043356&amp;amp;sprefix=web+app%2Caps%2C254&amp;amp;sr=8-1&quot;&gt;Web Application Security: Exploitation and Countermeasures for Modern Web Applications&lt;/a&gt;&amp;nbsp;by Andrew Hoffman.&lt;p&gt;&lt;/p&gt;&lt;p&gt;In summary: It&#39;s not very broad. It&#39;s not very deep. It&#39;s not very complete. It&#39;s not very polished--I plan on submitting a bunch of errata.&lt;/p&gt;&lt;p&gt;I was surprised at Hoffman&#39;s choice to rely on Chrome DevTools and JavaScript for all his exploits. I think most web pentesters rely on man-in-the-middle proxies such as Burp Suite.&lt;/p&gt;&lt;p&gt;He said that it&#39;s an intermediate-level book. I think it&#39;s fair to say that it&#39;s targeted at intermediate-level programmers who are beginners in web security. Surprisingly, he didn&#39;t even cover all of the OWASP Top 10. I didn&#39;t really learn much.&lt;/p&gt;&lt;p&gt;On the other hand, I appreciated the fact that it was easy to read, and I enjoyed the history of hacking at the beginning of the book.&lt;/p&gt;&lt;p&gt;Here are my &lt;a href=&quot;https://www.dropbox.com/s/b76oxff4d0p9ba4/20220924%20Web%20Application%20Security%20Notes.md?dl=0&quot;&gt;more-detailed&lt;/a&gt; notes.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/9184764317495667025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/9184764317495667025' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/9184764317495667025'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/9184764317495667025'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2022/09/books-web-application-security.html' title='Books: Web Application Security: Exploitation and Countermeasures for Modern Web Applications'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5uYYpjFtWxOXyiV09Mj2Ybd2H0VVK7NkcCfEz4Mk9KXyWkfRgNwrmebN_cAI-LE5zvr4-D-qdGYPCfFgSAIGr-wEjl9I5gPiJYVYucdDiqSKqZTdZm4D0Vg1q72lExa0-PVXt73AgTtRLTWhPGmnbQYcKfUG_yKhAfzE2VYcukAodyFCNWGY/s72-c/510FXFd+04L._SX379_BO1,204,203,200_.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-7505269456500391550</id><published>2022-08-30T06:06:00.005-07:00</published><updated>2023-01-04T12:52:05.474-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="microservices"/><title type='text'>Books: Monolith to Microservices: Evolutionary Patterns to Transform Your Monolith</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRyvulth9WZeEnrjWXyRdF6TY_Z2IR7mtPEEsXk0CZ7NGaOF5P2-uX44pOEyNEP1FKwHxm-B_UZ4fKPsN8htjGBhCJxF03zZQLHYZqlvZ84nAlsGCetGX7oIDnA7UvEmeDuM01dzXUkKCAnesO56ENKM2D_UUIfaD1qWRTcgrmjUV7r9nhN8k/s288/51QKwzDE4FL._SX218_BO1,204,203,200_QL40_FMwebp_.webp&quot; imageanchor=&quot;1&quot; style=&quot;clear: right; float: right; margin-bottom: 1em; margin-left: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;288&quot; data-original-width=&quot;220&quot; height=&quot;288&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRyvulth9WZeEnrjWXyRdF6TY_Z2IR7mtPEEsXk0CZ7NGaOF5P2-uX44pOEyNEP1FKwHxm-B_UZ4fKPsN8htjGBhCJxF03zZQLHYZqlvZ84nAlsGCetGX7oIDnA7UvEmeDuM01dzXUkKCAnesO56ENKM2D_UUIfaD1qWRTcgrmjUV7r9nhN8k/s1600/51QKwzDE4FL._SX218_BO1,204,203,200_QL40_FMwebp_.webp&quot; width=&quot;220&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;I finished &quot;Monolith to Microservices: Evolutionary Patterns to Transform Your Monolith&quot; by Sam Newman. It was great :)&lt;/p&gt;&lt;p&gt;There were a lot of things that surprised me in the book.&lt;/p&gt;&lt;p&gt;He&#39;s a lot more in favor of modular monoliths than I would have expected. He doesn&#39;t believe that microservices are the one true way. He thinks startups should stick with monoliths when they&#39;re trying to find their place in the world.&lt;/p&gt;&lt;p&gt;He&#39;s perfectly fine with calling back into the monolith. I remember, there were multiple people at my previous company who were really against that, and not just for issues of scale or latency.&lt;/p&gt;&lt;p&gt;He&#39;s okay with a service and a monolith both talking to the monolith&#39;s DB or the service&#39;s DB during a short transition period (i.e. days, weeks, or months) because doing double writes or flag days is so much harder.&lt;/p&gt;&lt;p&gt;You can either separate the app first (i.e. have the monolith and the new service talk to the same DB) or separate the DB first (i.e. have the monolith talk to two DBs).&lt;/p&gt;&lt;p&gt;He&#39;s okay with the idea of a &quot;DB as an API&quot;. That&#39;s when you have a complicated, private, internal DB, but then you publish either a view or a nicely polished DB for the rest of the company to consume. I had always thought that was heresy, but, I had seen this approach in many places. In a certain sense, a lot of people excuse themselves when they do this same thing with Kafka.&lt;/p&gt;&lt;p&gt;Aside from being less dogmatic than I expected, the rest of the book was not that surprising. Nonetheless, it was definitely worth reading.&lt;/p&gt;&lt;p&gt;Here are my notes from the book. Search for &quot;important&quot; for some of my other favorite parts:&lt;/p&gt;&lt;p&gt;ix. There are now many companies created to solve the problems caused by microservices.&lt;/p&gt;&lt;p&gt;ix. Consider whether they&#39;re even right for you. See especially chapter 2 on this.&lt;/p&gt;&lt;p&gt;1.6. He gave a nice definition of what a microservice is.&lt;/p&gt;&lt;p&gt;2.1. Independent deployability is key.&lt;/p&gt;&lt;p&gt;2.5. In general, sharing a DB is bad.&lt;/p&gt;&lt;p&gt;2.7. You shouldn&#39;t have to deploy 2 services for 1 new feature.&lt;/p&gt;&lt;p&gt;3. Separating by layer (e.g. frontend vs. backend) has drawbacks.&lt;/p&gt;&lt;p&gt;4.8. You should favor cohesion of business functionality over cohesion of technology.&lt;/p&gt;&lt;p&gt;5.8. Own your own data. Avoid sharing a DB unless you really have to because it may make it harder to maintain separate deployability.&lt;/p&gt;&lt;p&gt;6.7. Microservices do cause problems.&lt;/p&gt;&lt;p&gt;7.4. &quot;Honestly, microservices seem like a terrible idea, except for all the good stuff&quot; :-P&lt;/p&gt;&lt;p&gt;7.9. &lt;b&gt;Important:&lt;/b&gt; Leaving the UI as a big blob in the monolith is a mistake.&lt;/p&gt;&lt;p&gt;8.2. Avoid changing tech stacks when first moving.&lt;/p&gt;&lt;p&gt;8.5. You don&#39;t have to use k8s, Docker, the cloud, Go, etc.&lt;/p&gt;&lt;p&gt;9.0. Clojure requires fewer lines of code than Java.&lt;/p&gt;&lt;p&gt;9.5. Don&#39;t worry very much about how big or small each microservice is.&lt;/p&gt;&lt;p&gt;10.9. He was part of the group of people that picked the name &quot;microservices&quot;.&lt;/p&gt;&lt;p&gt;12.0. He defined what a monolith is and discussed the various kinds of monoliths.&lt;/p&gt;&lt;p&gt;12.9. He talked about modular monoliths.&lt;/p&gt;&lt;p&gt;13.5. A modular monolith can be an excellent choice. However, scaling the DB can make it harder.&lt;/p&gt;&lt;p&gt;13.9. He said that Shopify was a good example of a successful modular monolith.&lt;/p&gt;&lt;p&gt;14.4. A distributed monolith is when you have a bunch of services that all have to be deployed together. That&#39;s bad.&lt;/p&gt;&lt;p&gt;15.6. He talked about the advantages of monoliths. They can be the right choice.&lt;/p&gt;&lt;p&gt;16. He explained coupling and cohesion in a more understandable way than I had ever seen before.&lt;/p&gt;&lt;p&gt;17.6. Cohesion means that the code that changes together stays together. For instance, you *shouldn&#39;t* put all of your models in one place, all your controllers in another place, and all your views in a third place. Rather, group things into business units. Coupling means if you change one, you have to change the other. Remember, we want high cohesion and low coupling.&lt;/p&gt;&lt;p&gt;20.8. He talked about the benefits of &quot;publishing&quot; a DB view, as well as &quot;internal&quot; vs. &quot;external&quot; DBs.&lt;/p&gt;&lt;p&gt;21.8. He talked about the benefits of outside-in API development. Talk to your consumers!&lt;/p&gt;&lt;p&gt;22.2. Temporal coupling is when you have multiple services with synchronous calls.&lt;/p&gt;&lt;p&gt;23.4. He prefers release on demand over release trains.&lt;/p&gt;&lt;p&gt;23.9. He spoke highly of an Erlang monolith where you could separately upgrade individual modules.&lt;/p&gt;&lt;p&gt;24.9. &quot;Greenspun&#39;s 10th rule states, &#39;Any sufficiently complicated C or Fortran program contains an ad hoc, informally specified, bug-ridden, slow implementation of half of Common Lisp.&#39; This has morphed into the newer joke, &#39;Every microservice architecture contains a half-broken reimplementation of Erlang.&quot; I think there is a lot of truth to this.&quot;&lt;/p&gt;&lt;p&gt;28.7. He talked about the importance of modeling around business domains as well as Domain-Driven Development.&lt;/p&gt;&lt;p&gt;30.9. Start separating things based on who the system users are.&lt;/p&gt;&lt;p&gt;31.1. He talked about bounded contexts.&lt;/p&gt;&lt;p&gt;31.7. Start with larger services encompassing a whole bounded context (i.e. multiple aggregates).&lt;/p&gt;&lt;p&gt;32.9. He recommended the book &quot;Domain-Driven Design Distilled&quot;.&lt;/p&gt;&lt;p&gt;33. You have to understand your goals. There are many when it comes to microservices, and different goals will lead to different ways of going about things.&lt;/p&gt;&lt;p&gt;33.9. Avoid microservice cargo cult mentality.&lt;/p&gt;&lt;p&gt;34. &lt;b&gt;Important:&lt;/b&gt; A common failing is when you say &quot;my CTO told me to do it.&quot;&lt;/p&gt;&lt;p&gt;34.7. It&#39;s hard to get real data on the benefits of microservices.&lt;/p&gt;&lt;p&gt;35.5. He gave 3 questions that you should ask yourself before adopting microservices.&lt;/p&gt;&lt;p&gt;35.8. He covered why you might use them as well as some alternatives (to microservices) that may result in the same benefits.&lt;/p&gt;&lt;p&gt;36.7. Having different teams own different parts of the monolith can help. Making more things self-service can help as well.&lt;/p&gt;&lt;p&gt;37.2. &lt;b&gt;Important:&lt;/b&gt; There are many other ways to reduce time to market.&lt;/p&gt;&lt;p&gt;38.5. If you&#39;re worried about scalability, you could choose to only move certain code into microservices--i.e. the code where it really matters.&lt;/p&gt;&lt;p&gt;40.9. You could choose to use a modular monolith. The biggest downside of this approach is the shared deployment.&lt;/p&gt;&lt;p&gt;41.9. He walked through an example that perfectly matched why my previous company&#39;s PHP to Python transition was successful.&lt;/p&gt;&lt;p&gt;42.9. He talked about times when microservices are a bad idea.&lt;/p&gt;&lt;p&gt;42.9. Don&#39;t use microservices when you&#39;re trying to tackle an unclear domain, when you&#39;re trying to build a startup, when you&#39;re building customer-installed and managed software, or in cases where you don&#39;t have a strong reason to use them.&lt;/p&gt;&lt;p&gt;45.6. &lt;b&gt;Important:&lt;/b&gt; Adopting microservices because everyone else is adopting them is a terrible reason.&lt;/p&gt;&lt;p&gt;45.9. &lt;b&gt;Important:&lt;/b&gt; He specifically mentioned that it was a bad idea to try out microservices because you want to try out Kotlin :-P He said that conflating things in this way is a bad idea in general.&lt;/p&gt;&lt;p&gt;48.0. He talked about how to &quot;move&quot; an organization.&lt;/p&gt;&lt;p&gt;50.6. He talked about Google&#39;s &quot;Testing on the Toilet&quot;. I tried really hard to get something published in that, but I failed :-P&lt;/p&gt;&lt;p&gt;51.6. &lt;b&gt;Important:&lt;/b&gt; Don&#39;t spend a year building the perfect microservice architecture only to find out that it doesn&#39;t solve your problems.&lt;/p&gt;&lt;p&gt;52.4. You can avoid decomposing your DB for a while, but you can&#39;t delay that forever.&lt;/p&gt;&lt;p&gt;52.7. Sharing info with the rest of the org is critical.&lt;/p&gt;&lt;p&gt;53. He talked about the importance of incremental migration.&lt;/p&gt;&lt;p&gt;54.7. Don&#39;t overthink reversible decisions.&lt;/p&gt;&lt;p&gt;58. He talked about event storming.&lt;/p&gt;&lt;p&gt;59.5. The strangler fig pattern is useful. It implies calling into the monolith, and he&#39;s okay with that.&lt;/p&gt;&lt;p&gt;60.3. He said you might not want to tackle DB decomposition for the first few microservices, and that&#39;s okay.&lt;/p&gt;&lt;p&gt;63.6. He talked about the importance of cross-functional teams tackling different business verticals. I.e. don&#39;t put all your frontend people in one team, all your backend people in another team, etc. Instead, one team should have a mix of people and tackle an entire business vertical (frontend, backend, etc.).&lt;/p&gt;&lt;p&gt;64.7. &lt;b&gt;Important:&lt;/b&gt; Bold proclamations can move a company forward, but expect chaos to follow.&lt;/p&gt;&lt;p&gt;65.0. &lt;b&gt;Important:&lt;/b&gt; DevOps doesn&#39;t mean NoOps.&lt;/p&gt;&lt;p&gt;66.8. &lt;b&gt;Important:&lt;/b&gt; Expecting developers to instantly know how to do on-call is unrealistic.&lt;/p&gt;&lt;p&gt;67. &lt;b&gt;Important:&lt;/b&gt; It may make sense to have your developers handle on-call during business hours and to have your ops people handle it after hours.&lt;/p&gt;&lt;p&gt;77.0. Copy the code from your monolith into the microservice, and then worry about deleting it later.&lt;/p&gt;&lt;p&gt;77.8. &lt;b&gt;Important:&lt;/b&gt; He said that you can perhaps start by moving to a modular monolith. For instance, you can have separate jar files. He said this approach was actually recommended.&lt;/p&gt;&lt;p&gt;79. He talked about the &quot;strangler fig application&quot; pattern.&lt;/p&gt;&lt;p&gt;82.0. &lt;b&gt;Important:&lt;/b&gt; He talked more about how to call back into the monolith.&lt;/p&gt;&lt;p&gt;83.0. He did a good job describing how my previous company migrated from PHP to Python.&lt;/p&gt;&lt;p&gt;86.9. He talked about using NGINX as a proxy in front of your monolith and microservice.&lt;/p&gt;&lt;p&gt;88.5. &lt;b&gt;Important:&lt;/b&gt; He talked about doing an incremental rollout using a shared DB.&lt;/p&gt;&lt;p&gt;90. &lt;b&gt;Important:&lt;/b&gt; He talked about having a service that acts like a proxy translating from one protocol to another. He said that he had grave concerns about this approach because you ended up collecting too much business logic in the proxy. It reminded me a lot of GraphQL proxies.&lt;/p&gt;&lt;p&gt;92. He talked about service meshes.&lt;/p&gt;&lt;p&gt;93.8. He said you may want to delay the adoption of a service mesh until things had settled down.&lt;/p&gt;&lt;p&gt;97.2. He recommended the book &quot;Enterprise Integration Patterns&quot;.&lt;/p&gt;&lt;p&gt;98. He talked about various helpful approaches to UI composition such as page composition, widget-based composition, etc. You can have separate widgets on the same page served by different microservices.&lt;/p&gt;&lt;p&gt;103. He talked about &quot;micro frontends&quot;.&lt;/p&gt;&lt;p&gt;104.8. &lt;b&gt;Important:&lt;/b&gt; He introduced the &quot;branch by abstraction&quot; pattern. Create an interface. Create a front door that matches that interface. Behind that front door, it can either call the old code (which also matches that interface) or the new code (which also matches that interface) which calls out to a service. Naturally, you can throw some feature flags in there, etc.&lt;/p&gt;&lt;p&gt;105.3. Avoid long-lived branches. Rather, ship both versions of the code, and control them using a feature flag or something like that.&lt;/p&gt;&lt;p&gt;113. The Parallel Run pattern&lt;/p&gt;&lt;p&gt;115. N-Version Programming&lt;/p&gt;&lt;p&gt;117. He talked about GitHub&#39;s Scientist library which you can use to compare 2 live implementations of the same thing.&lt;/p&gt;&lt;p&gt;118.3. He introduced &quot;progressive delivery&quot;.&lt;/p&gt;&lt;p&gt;118.7 The Decorating Collaborator pattern&lt;/p&gt;&lt;p&gt;120.8 Change Data Capture (CDC)&lt;/p&gt;&lt;p&gt;123. Doing CDC with transaction logs&lt;/p&gt;&lt;p&gt;125. The challenges of using a shared DB&lt;/p&gt;&lt;p&gt;127. &lt;b&gt;Important:&lt;/b&gt; He said you should prefer to separate the DB, but if you can&#39;t, here are some coping patterns.&lt;/p&gt;&lt;p&gt;128. The Database View pattern&lt;/p&gt;&lt;p&gt;132. The Database Wrapping Service pattern&lt;/p&gt;&lt;p&gt;135. &lt;b&gt;Important:&lt;/b&gt; The Database as a Service pattern is when you maintain a well-groomed DB that&#39;s specifically meant to be consumed by clients. You&#39;ll probably want to have an internal vs. an external, read-only DB.&lt;/p&gt;&lt;p&gt;136. He talked about how to build the mapping engine for an external DB. You can use CDC, etc.&lt;/p&gt;&lt;p&gt;136.9. He mentioned Debezium for CDC.&lt;/p&gt;&lt;p&gt;137.4. He suggested that you might start with a DB view and then possibly move to DB as a service.&lt;/p&gt;&lt;p&gt;138. &lt;b&gt;Important:&lt;/b&gt; He introduced the Aggregate Exposing Monolith in which a service provides a nice interface to data that it gets by calling back into the monolith.&lt;/p&gt;&lt;p&gt;138.8. Remember that microservices encompass both behavior *and* state.&lt;/p&gt;&lt;p&gt;138.9. &lt;b&gt;Important:&lt;/b&gt; Don&#39;t just create a wrapper of a DB. A service should act like a state machine in which it controls what state transitions are possible. This was a key idea that he kept coming back to.&lt;/p&gt;&lt;p&gt;140.7. Each service takes care of its own authorization insofar as it decides which state transitions are okay.&lt;/p&gt;&lt;p&gt;141. Heh, the same section is duplicated on p. 139 and p. 141.&lt;/p&gt;&lt;p&gt;141. He talked about the Change Data Ownership pattern.&lt;/p&gt;&lt;p&gt;142. &lt;b&gt;Important:&lt;/b&gt; This is a super important picture of the Change Data Ownership pattern.&lt;/p&gt;&lt;p&gt;143.0. He talked about projecting data back into the monolith using a view.&lt;/p&gt;&lt;p&gt;144.6. He gave some sensible (but perhaps contrary to the orthodoxy) advice on how to keep data in sync for the strangler fig pattern.&lt;/p&gt;&lt;p&gt;145.0 The Synchronize Data in Application pattern&lt;/p&gt;&lt;p&gt;145. Riak was used for some nationwide Danish medical record system. It&#39;s apparently very good.&lt;/p&gt;&lt;p&gt;149. The Tracer Write pattern&lt;/p&gt;&lt;p&gt;158. Splitting apart the DB&lt;/p&gt;&lt;p&gt;160. &lt;b&gt;Important:&lt;/b&gt; Should you split apart the DB first or the code first? Each has pros and cons.&lt;/p&gt;&lt;p&gt;162.4. He mentioned using Flyway for DB migrations.&lt;/p&gt;&lt;p&gt;163.5. SchemaSpy is a tool that you can use to visualize DB table relationships.&lt;/p&gt;&lt;p&gt;164.7. He talked about another successful modular monolith that talked to multiple separate schemas.&lt;/p&gt;&lt;p&gt;165.6. &lt;b&gt;Important:&lt;/b&gt; Most people split the code first and the DB later. I really like this approach. It seems like it goes against the dogma of never having two services talking to the same database, but as long as it&#39;s a temporary part of a transition, it works really well, and I&#39;ve seen it succeed in practice! Just to spell it out (thanks Maksim Horbul!): Create a new DB user for the service, and give it read/write access to the MonoDB. Create a new service which reads and writes to the MonoDB. Replicate the tables you need from the MonoDB to a new service DB. Stop the service temporarily. Make sure the replicated tables in the MonoDB and service DB are identical. Drop replication. Configure the new service to talk to the service&#39;s DB. Restart the service.&lt;/p&gt;&lt;p&gt;166.3. Don&#39;t stop there! Finish!&lt;/p&gt;&lt;p&gt;166.5. He talked about using the monolith as a data access layer.&lt;/p&gt;&lt;p&gt;169. Multi-schema storage&lt;/p&gt;&lt;p&gt;170.5. &lt;b&gt;Important:&lt;/b&gt; Avoid splitting the code and the schema at the same time. Do one or the other first.&lt;/p&gt;&lt;p&gt;170.9. &lt;b&gt;Important:&lt;/b&gt; If you can change the monolith, split the schema first. If not, split the code first.&lt;/p&gt;&lt;p&gt;175.5. Errata: There was an error in some diagram. I just wrote, &quot;Nothing to join on.&quot;&lt;/p&gt;&lt;p&gt;176.2. He mentioned using Jaeger for distributed tracing.&lt;/p&gt;&lt;p&gt;177.5. You can just not allow deletion. Have a field for whether the row has been deleted.&lt;/p&gt;&lt;p&gt;178.3. When you pull something out of the DB, take the whole aggregate with you.&lt;/p&gt;&lt;p&gt;178.7. He covered how to deal with shared, static data like country lists.&lt;/p&gt;&lt;p&gt;182.2. &lt;b&gt;Important:&lt;/b&gt; He talked about storing static reference data (like country lists) in code as shared libraries. (I remember being criticized for doing this one time.)&lt;/p&gt;&lt;p&gt;187.2. He talked about how to deal with transactions.&lt;/p&gt;&lt;p&gt;188.5. He referred to the book &quot;Data-Intensive Applications&quot; (which my buddy Sam recommended to me).&lt;/p&gt;&lt;p&gt;190. He talked about two-phase commits.&lt;/p&gt;&lt;p&gt;193.1. &lt;b&gt;Important:&lt;/b&gt; Say no to distributed transactions.&lt;/p&gt;&lt;p&gt;193.6. He explained sagas. His explanation was better than others I&#39;ve seen.&lt;/p&gt;&lt;p&gt;201.8. &lt;b&gt;Important:&lt;/b&gt; He talked about Business Process Modelling tools. Apparently, he doesn&#39;t like them because they&#39;re not built for programmers, yet it&#39;s programmers who always end up having to use them.&lt;/p&gt;&lt;p&gt;202.5. Camunda and Zeebe are better. They&#39;re open-source orchestration frameworks targeted at microservice developers.&lt;/p&gt;&lt;p&gt;204.9. He talked about how to implement sagas.&lt;/p&gt;&lt;p&gt;205.9. He didn&#39;t know the term &quot;saga&quot; when he wrote his first microservice book. There was another book that was very influential in this space, and it didn&#39;t use the term &quot;saga&quot; either.&lt;/p&gt;&lt;p&gt;208.0. &lt;b&gt;Important:&lt;/b&gt; Microservices are a dial, not a switch. It&#39;s not about yes or no. It&#39;s about how many.&lt;/p&gt;&lt;p&gt;214.0. He talked about running two versions of a service at the same time to cope with clients that are not compatible with the new version. He said it&#39;s better to have one version of the service support both the old API and the new API.&lt;/p&gt;&lt;p&gt;215.5. It&#39;s imperative to avoid accidentally breaking a contract and that you have a plan for how to handle purposely changing an API.&lt;/p&gt;&lt;p&gt;215.7. He talked about how to deal with reporting, big-data analytics, data warehouses, etc.&lt;/p&gt;&lt;p&gt;218.8. He covered log aggregation, the ELK stack, etc. He likes Humio.&lt;/p&gt;&lt;p&gt;219.0. You should tackle log aggregation before you try to tackle microservices.&lt;/p&gt;&lt;p&gt;219.5. He talked about tracing.&lt;/p&gt;&lt;p&gt;220.6. He mentioned Jaeger again for tracing.&lt;/p&gt;&lt;p&gt;221.5. &lt;b&gt;Important:&lt;/b&gt; He talked about the importance of testing in prod with fake user data and synthetic transactions.&lt;/p&gt;&lt;p&gt;222.6. Distributed systems observability&lt;/p&gt;&lt;p&gt;222.8. He talked about the local dev experience. You&#39;ll get to a point where you can&#39;t run everything on one laptop.&lt;/p&gt;&lt;p&gt;223.8. He recommended teleprescence.io, my buddy&#39;s company :-D&lt;/p&gt;&lt;p&gt;225.1. &lt;b&gt;Important:&lt;/b&gt; He recommended that you *not* run vanilla Kubernetes. Use OpenShift or some managed solution (perhaps EKS). He&#39;s a fan of Function as a Service (i.e. Lambda).&lt;/p&gt;&lt;p&gt;225.7. &lt;b&gt;Important:&lt;/b&gt; If you can use some Function as a Service solution (i.e. Lambda), do that before trying to tackle Kubernetes. He said it&#39;s way simpler. That advice surprised me. He said don&#39;t reach for Kubernetes too soon. You can wait a while. The same goes for microservices in general.&lt;/p&gt;&lt;p&gt;226. He covered end-to-end testing.&lt;/p&gt;&lt;p&gt;227.5. He talked about Consumer-Driven Contracts (CDCs). He said they&#39;re underused, but not everyone has been successful with them. He recommended pact.io.&lt;/p&gt;&lt;p&gt;231.2. He recommended something like a tech council where you have one person from each team.&lt;/p&gt;&lt;p&gt;233. He talked about orphaned services.&lt;/p&gt;&lt;p&gt;237. He gave his closing remarks.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/7505269456500391550/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/7505269456500391550' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/7505269456500391550'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/7505269456500391550'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2022/08/books-monolith-to-microservices.html' title='Books: Monolith to Microservices: Evolutionary Patterns to Transform Your Monolith'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRyvulth9WZeEnrjWXyRdF6TY_Z2IR7mtPEEsXk0CZ7NGaOF5P2-uX44pOEyNEP1FKwHxm-B_UZ4fKPsN8htjGBhCJxF03zZQLHYZqlvZ84nAlsGCetGX7oIDnA7UvEmeDuM01dzXUkKCAnesO56ENKM2D_UUIfaD1qWRTcgrmjUV7r9nhN8k/s72-c/51QKwzDE4FL._SX218_BO1,204,203,200_QL40_FMwebp_.webp" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-8174245613572303600</id><published>2022-08-02T17:01:00.028-07:00</published><updated>2024-05-07T11:44:16.816-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="LeetCode"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python: My Favorite Python Tricks for LeetCode Questions</title><content type='html'>&lt;p&gt;I&#39;ve been spending a lot of time practicing on LeetCode recently, so I thought I&#39;d share some of my favorite intermediate-level Python tricks. I&#39;ll also cover some newer features of Python you may not have started using yet. I&#39;ll start with basic tips and then move to more advanced ones.&lt;/p&gt;
&lt;h3 id=&quot;get-help&quot;&gt;Get help()&lt;/h3&gt;
&lt;p&gt;Python&#39;s documentation is pretty great, and some of these examples are taken from there.&lt;/p&gt;
&lt;p&gt;For instance, if you just google &quot;heapq&quot;, you&#39;ll see the official docs for heapq, which are often enough.&lt;/p&gt;
&lt;p&gt;However, it&#39;s also helpful to sometimes just quickly use &lt;code&gt;help()&lt;/code&gt; in the shell. Here, I can&#39;t remember that &lt;code&gt;push()&lt;/code&gt; is actually called &lt;code&gt;append()&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;&amp;gt;&amp;gt;&amp;gt; help([])

&amp;gt;&amp;gt;&amp;gt; dir([])

&amp;gt;&amp;gt;&amp;gt; help([].append)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;enumerate&quot;&gt;enumerate()&lt;/h3&gt;
&lt;p&gt;If you need to loop over a list, you can use &lt;code&gt;enumerate()&lt;/code&gt; to get both the item as well as the index. As a mnemonic, I like to think &lt;code&gt;for (i, x) in enumerate(...)&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;for (i, x) in enumerate(some_list):
    ...
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;items&quot;&gt;items()&lt;/h3&gt;
&lt;p&gt;Similarly, you can get both the key and the value at the same time when looping over a dict using &lt;code&gt;items()&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;for (k, v) in some_dict.items():
    ...
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;-vs-get&quot;&gt;[] vs. get()&lt;/h3&gt;
&lt;p&gt;Remember, when you use &lt;code&gt;[]&lt;/code&gt; with a dict, if the value doesn&#39;t exist, you&#39;ll get a &lt;code&gt;KeyError&lt;/code&gt;. Rather than see if an item is in the dict and then look up its value, you can use &lt;code&gt;get()&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;val = some_dict.get(key)  # It defaults to None.
if val is None:
    ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly, &lt;code&gt;.setdefault()&lt;/code&gt; is sometimes helpful.&lt;/p&gt;
&lt;p&gt;Some people prefer to just use &lt;code&gt;[]&lt;/code&gt; and handle the &lt;code&gt;KeyError&lt;/code&gt; since exceptions aren&#39;t as expensive in Python as they are in other languages.&lt;/p&gt;
&lt;h3 id=&quot;range-is-smarter-than-you-think&quot;&gt;range() is smarter than you think&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;for item in range(items):
    ...
    
for index in range(len(items)):
    ...
    
# Count by 2s.
for i in range(0, 100, 2):
    ...

# Count backward from 100 to 0 inclusive.
for i in range(100, -1, -1):
    ...
    
# Okay, Mr. Smarty Pants, I&#39;m sure you knew all that, but did you know
# that you can pass a range object around, and it knows how to reverse
# itself via slice notation? :-P
r = range(100)
r = r[::-1]  # range(99, -1, -1)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;printf-debugging&quot;&gt;print(f&#39;&#39;) debugging&lt;/h3&gt;
&lt;p&gt;Have you switched to Python&#39;s new format strings yet? They&#39;re more convenient and safer (from injection vulnerabilities) than &lt;code&gt;%&lt;/code&gt; and &lt;code&gt;.format()&lt;/code&gt;. They even have a syntax for outputing the thing as well as its value:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;# Got 2+2=4
print(f&#39;Got {2+2=}&#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;for-else&quot;&gt;for else&lt;/h3&gt;
&lt;p&gt;Python has a feature that I haven&#39;t seen in other programming languages. Both &lt;code&gt;for&lt;/code&gt; and &lt;code&gt;while&lt;/code&gt; can be followed by an &lt;code&gt;else&lt;/code&gt; clause, which is useful when you&#39;re searching for something.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;for item in some_list:
    if is_what_im_looking_for(item):
        print(f&quot;Yay! It&#39;s {item}.&quot;)
        break
else:
    print(&quot;I couldn&#39;t find what I was looking for.&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;use-a-list-as-a-stack&quot;&gt;Use a list as a stack&lt;/h3&gt;
&lt;p&gt;The cost of using a list as a stack is (amortized) O(1):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;elements = []
elements.append(element)  # Not push
element = elements.pop()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that inserting something at the beginning of the list or in the middle is more expensive it has to shift everything to the right--see &lt;code&gt;deque&lt;/code&gt; below.&lt;/p&gt;
&lt;h3 id=&quot;sort-vs-sorted&quot;&gt;sort() vs. sorted()&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# sort() sorts a list in place.
my_list.sort()

# Whereas sorted() returns a sorted *copy* of an iterable:
my_sorted_list = sorted(some_iterable)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And, both of these can take a &lt;code&gt;key&lt;/code&gt; function if you need to sort objects.&lt;/p&gt;
&lt;h3 id=&quot;set-and-frozenset&quot;&gt;set and frozenset&lt;/h3&gt;
&lt;p&gt;Sets are so useful for so many problems! Just in case you didn&#39;t know some of these tricks:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;# There is now syntax for creating sets.
s = {&#39;Von&#39;}

# There are set &quot;comprehensions&quot; which are like list comprehensions, but for sets.
s2 = {f&#39;{name} the III&#39; for name in s}
{&#39;Von the III&#39;}

# If you can&#39;t remember how to use union, intersection, difference, etc.
help(set())

# If you need an immutable set, for instance, to use as a dict key, use frozenset.
frozenset((1, 2, 3))
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;deque&quot;&gt;deque&lt;/h3&gt;
&lt;p&gt;If you find yourself needing a queue or a list that you can push and pop from either side, use a deque:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;&amp;gt;&amp;gt;&amp;gt; from collections import deque
&amp;gt;&amp;gt;&amp;gt; 
&amp;gt;&amp;gt;&amp;gt; d = deque()
&amp;gt;&amp;gt;&amp;gt; d.append(3)
&amp;gt;&amp;gt;&amp;gt; d.append(4)
&amp;gt;&amp;gt;&amp;gt; d.appendleft(2)
&amp;gt;&amp;gt;&amp;gt; d.appendleft(1)
&amp;gt;&amp;gt;&amp;gt; d
deque([1, 2, 3, 4])
&amp;gt;&amp;gt;&amp;gt; d.popleft()
1
&amp;gt;&amp;gt;&amp;gt; d.pop()
4
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;using-a-stack-instead-of-recursion&quot;&gt;Using a stack instead of recursion&lt;/h3&gt;
&lt;p&gt;Instead of using recursion (which has a depth of about 1024 frames), you can use a while loop and manually manage a stack yourself. Here&#39;s a slightly contrived example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;work = [create_initial_work()]
while work:
    work_item = work.pop()
    result = process(work_item)
    if is_done(result):
        return result
    work.append(result.pieces[0])
    work.append(result.pieces[1])
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;using-yield-from&quot;&gt;Using yield from&lt;/h3&gt;
&lt;p&gt;If you don&#39;t know about yield, you can go spend some time learning about that. It&#39;s awesome.&lt;/p&gt;
&lt;p&gt;Sometimes, when you&#39;re in one generator, you need to call another generator. Python now has &lt;code&gt;yield from&lt;/code&gt; for that:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;def my_generator():
    yield 1
    yield from some_other_generator()
    yield 6
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, here&#39;s an example of backtracking:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;class Solution:
    def problem(self, digits: str) -&amp;gt; List[str]:
        def generate_possibilities(work_so_far, remaining_work):
            if not remaining_work:
                if work_so_far:
                    yield work_so_far
                return
            first_part, remaining_part = remaining_work[0], remaining_work[1:]
            for i in things_to_try:
                yield from generate_possibilities(work_so_far + i, remaining_part)
        
        output = list(generate_possibilities(no_work_so_far, its_all_remaining_work))
        return output
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is appropriate if you have less than 1000 &quot;levels&quot; but a ton of possibilities for each of those levels. This won&#39;t work if you&#39;re going to need more than 1000 layers of recursion. In that case, switch to &quot;Using a stack instead of recursion&quot;.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Updated: &lt;/b&gt;On the other hand, if you can have the recursive function append to some list of answers instead of yielding it all the way back to the caller, that&#39;s faster.&lt;/p&gt;
&lt;h3 id=&quot;pre-initialize-your-list&quot;&gt;Pre-initialize your list&lt;/h3&gt;
&lt;p&gt;If you know how long your list is going to be ahead of time, you can avoid needing to resize it multiple times by just pre-initializing it:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;dp = [None] * len(items)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;collectionscounter&quot;&gt;collections.Counter()&lt;/h3&gt;
&lt;p&gt;How many times have you used a dict to count up something? It&#39;s built-in in Python:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;&amp;gt;&amp;gt;&amp;gt; from collections import Counter
&amp;gt;&amp;gt;&amp;gt; c = Counter(&#39;abcabcabcaaa&#39;)
&amp;gt;&amp;gt;&amp;gt; c
Counter({&#39;a&#39;: 6, &#39;b&#39;: 3, &#39;c&#39;: 3})
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;defaultdict&quot;&gt;defaultdict&lt;/h3&gt;
&lt;p&gt;Similarly, there&#39;s &lt;code&gt;defaultdict&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;&amp;gt;&amp;gt;&amp;gt; from collections import defaultdict
&amp;gt;&amp;gt;&amp;gt; d = defaultdict(list)
&amp;gt;&amp;gt;&amp;gt; d[&#39;girls&#39;].append(&#39;Jocylenn&#39;)
&amp;gt;&amp;gt;&amp;gt; d[&#39;boys&#39;].append(&#39;Greggory&#39;)
&amp;gt;&amp;gt;&amp;gt; d
defaultdict(&amp;lt;class &#39;list&#39;&amp;gt;, {&#39;girls&#39;: [&#39;Jocylenn&#39;], &#39;boys&#39;: [&#39;Greggory&#39;]})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that I didn&#39;t need to set &lt;code&gt;d[&#39;girls&#39;]&lt;/code&gt; to an empty list before I started appending to it.&lt;/p&gt;
&lt;h3 id=&quot;heapq&quot;&gt;heapq&lt;/h3&gt;
&lt;p&gt;I had heard of heaps in school, but I didn&#39;t really know what they were. Well, it turns out they&#39;re pretty helpful for several of the problems, and Python has a list-based heap implementation built-in.&lt;/p&gt;
&lt;p&gt;If you don&#39;t know what a heap is, I recommend &lt;a href=&quot;https://www.youtube.com/watch?v=qXdt1AHMB2o&quot;&gt;this video&lt;/a&gt; and &lt;a href=&quot;https://www.youtube.com/watch?v=pLIajuc31qk&quot;&gt;this video&lt;/a&gt;. They&#39;ll explain what a heap is and how to implement one using a list.&lt;/p&gt;
&lt;p&gt;The heapq module is a built-in module for managing a heap. It builds on top of an existing list:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;import heapq

some_list = ...
heapq.heapify(some_list)

# The head of the heap is some_list[0].
# The len of the heap is still len(some_list).

heapq.heappush(some_list, item)
head_item = heapq.heappop(some_list)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;heapq&lt;/code&gt; module also has &lt;code&gt;nlargest&lt;/code&gt; and &lt;code&gt;nsmallest&lt;/code&gt; built-in so you don&#39;t have to implement those things yourself.&lt;/p&gt;
&lt;p&gt;Keep in mind that &lt;code&gt;heapq&lt;/code&gt; is a minheap. Let&#39;s say that what you really want is a maxheap, and you&#39;re not working with ints, you&#39;re working with objects. Here&#39;s how to tweak your data to get it to fit &lt;code&gt;heapq&lt;/code&gt;&#39;s way of thinking:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;heap = []
heapq.heappush(heap, (-obj.value, obj))

(ignored, first_obj) = heapq.heappop()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, I&#39;m using &lt;code&gt;-&lt;/code&gt; to make it a maxheap. I&#39;m wrapping things in a tuple so that it&#39;s sorted by the &lt;code&gt;obj.value&lt;/code&gt;, and I&#39;m including the &lt;code&gt;obj&lt;/code&gt; as the second value so that I can get it.&lt;/p&gt;
&lt;h3 id=&quot;use-bisect-for-binary-search&quot;&gt;Use bisect for binary search&lt;/h3&gt;
&lt;p&gt;I&#39;m sure you&#39;ve implemented binary search before. Python has it built-in. It even has keyword arguments that you can use to search in only part of the list:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;import bisect

insertion_point = bisect.bisect_left(sorted_list, some_item, lo=lo, high=high)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pay attention to the &lt;code&gt;key&lt;/code&gt; argument which is sometimes useful, but may take a little work for it to work the way you want.&lt;/p&gt;
&lt;h3 id=&quot;namedtuple-and-dataclasses&quot;&gt;namedtuple and dataclasses&lt;/h3&gt;
&lt;p&gt;Tuples are great, but it can be a pain to deal with remembering the order of the elements or unpacking just a single element in the tuple. That&#39;s where namedtuple comes in.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;&amp;gt;&amp;gt;&amp;gt; from collections import namedtuple
&amp;gt;&amp;gt;&amp;gt; Point = namedtuple(&#39;Point&#39;, [&#39;x&#39;, &#39;y&#39;])
&amp;gt;&amp;gt;&amp;gt; p = Point(5, 7)
&amp;gt;&amp;gt;&amp;gt; p
Point(x=5, y=7)
&amp;gt;&amp;gt;&amp;gt; p.x
5
&amp;gt;&amp;gt;&amp;gt; q = p._replace(x=92)
&amp;gt;&amp;gt;&amp;gt; p
Point(x=5, y=7)
&amp;gt;&amp;gt;&amp;gt; q
Point(x=92, y=7)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Keep in mind that tuples are immutable. I particularly like using namedtuples for backtracking problems. In that case, the immutability is actually a huge asset. I use a namedtuple to represent the state of the problem at each step. I have this much stuff done, this much stuff left to do, this is where I am, etc. At each step, you take the old namedtuple and create a new one in an immutable way.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Updated:&lt;/b&gt; Python 3.7 introduced dataclasses. These have multiple advantages:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;They can be mutable or immutable (although, there&#39;s a small performance penalty).&lt;/li&gt;&lt;li&gt;You can use type annotations.&lt;/li&gt;&lt;li&gt;You can add methods.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;from dataclasses import dataclass

@dataclass  # Or: @dataclass(&lt;span class=&quot;hljs-params&quot; color=&quot;var(--highlight-keyword)&quot; style=&quot;border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; white-space: inherit;&quot;&gt;frozen=&lt;span class=&quot;hljs-literal&quot; color=&quot;var(--highlight-literal)&quot; style=&quot;border: 0px; box-sizing: inherit; font-family: inherit; font-feature-settings: inherit; font-kerning: inherit; font-optical-sizing: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-variation-settings: inherit; font-weight: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;True&lt;/span&gt;&lt;/span&gt;&lt;span color=&quot;var(--highlight-keyword)&quot; style=&quot;font-family: inherit; font-size: 13px; font-style: inherit; font-variant-caps: inherit; font-variant-ligatures: inherit; font-weight: inherit; white-space: inherit;&quot;&gt;)&lt;/span&gt;
class InventoryItem:
    &quot;&quot;&quot;Class for keeping track of an item in inventory.&quot;&quot;&quot;
    name: str
    unit_price: float
    quantity_on_hand: int = 0

    def total_cost(self) -&amp;gt; float:
        return self.unit_price * self.quantity_on_hand

item = InventoryItem(name=&#39;Box&#39;, unit_price=19, quantity_on_hand=2)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;dataclasses are great when you want a little class to hold some data, but you don&#39;t want to waste much time writing one from scratch.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Updated:&lt;/b&gt;&amp;nbsp;Here&#39;s a &lt;a href=&quot;https://medium.com/@jacktator/dataclass-vs-namedtuple-vs-object-for-performance-optimization-in-python-691e234253b9&quot;&gt;comparison&lt;/a&gt; between namedtuples and dataclasses. It leads me to favor dataclasses since they have faster property access and use 30% less memory :-/ Per the Python docs, using frozen=True is slightly slower than not using it. In my (extremely unscientific) testing, using a normal class with __slots__ is faster and uses less memory than a dataclass.&lt;/p&gt;
&lt;h3 id=&quot;int-decimal-mathinf-etc&quot;&gt;int, decimal, math.inf, etc.&lt;/h3&gt;
&lt;p&gt;Thankfully, Python&#39;s int type supports arbitrarily large values by default:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;&amp;gt;&amp;gt;&amp;gt; 1 &amp;lt;&amp;lt; 128
340282366920938463463374607431768211456
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There&#39;s also the &lt;a href=&quot;https://docs.python.org/3/library/decimal.html&quot;&gt;decimal&lt;/a&gt; module if you need to work with things like money where a float isn&#39;t accurate enough or when you need a lot of decimal places of precision.&lt;/p&gt;
&lt;p&gt;Sometimes, they&#39;ll say the range is -2 ^ 32 to 2 ^ 32 - 1. You can get those values via bitshifting:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;&amp;gt;&amp;gt;&amp;gt; -(2 ** 32) == -(1 &amp;lt;&amp;lt; 32)
True
&amp;gt;&amp;gt;&amp;gt; (2 ** 32) - 1 == (1 &amp;lt;&amp;lt; 32) - 1
True
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sometimes, it&#39;s useful to initialize a variable with &lt;code&gt;math.inf&lt;/code&gt; (i.e. infinity) and then try to find new values less than that.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Updated:&lt;/b&gt; If you want to save memory by not importing the math module, just use&amp;nbsp;&lt;span style=&quot;font-family: monospace;&quot;&gt;float(&quot;inf&quot;).&lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;closures&quot;&gt;Closures&lt;/h3&gt;
&lt;p&gt;I&#39;m not sure every interviewer is going to like this, but I tend to skip the OOP stuff and use a bunch of local helper functions so that I can access things via closure:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;class Solution():  # This is what LeetCode gave me.
    def solveProblem(self, arg1, arg2):  # Why they used camelCase, I have no idea.
      
        def helper_function():
            # I have access to arg1 and arg2 via closure.
            # I don&#39;t have to store them on self or pass them around
            # explicitly.
            return arg1 + arg2
          
        counter = 0
        
        def can_mutate_counter():
            # By using nonlocal, I can even mutate counter.
            # I rarely use this approach in practice. I usually pass in it
            # as an argument and return a value.
            nonlocal counter
            counter += 1
            
       can_mutate_counter()
       return helper_function() + counter
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;match-statement&quot;&gt;match statement&lt;/h3&gt;
&lt;p&gt;Did you know Python now has a match statement?&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;# Taken from: https://learnpython.com/blog/python-match-case-statement/

&amp;gt;&amp;gt;&amp;gt; command = &#39;Hello, World!&#39;
&amp;gt;&amp;gt;&amp;gt; match command:
...     case &#39;Hello, World!&#39;:
...         print(&#39;Hello to you too!&#39;)
...     case &#39;Goodbye, World!&#39;:
...         print(&#39;See you later&#39;)
...     case other:
...         print(&#39;No match found&#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&#39;s actually much more sophisticated than a switch statement, so take a look, especially if you&#39;ve never used match in a functional language like Haskell.&lt;/p&gt;
&lt;h3 id=&quot;ordereddict&quot;&gt;OrderedDict&lt;/h3&gt;
&lt;p&gt;If you ever need to implement an LRU cache, it&#39;ll be quite helpful to have an &lt;a href=&quot;https://docs.python.org/3/library/collections.html#collections.OrderedDict&quot;&gt;OrderedDict&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Python&#39;s dicts are now ordered by default. However, the docs for OrderedDict say that there are still some cases where you might need to use OrderedDict. I can&#39;t remember. If you never need your dicts to be ordered, just read the docs and figure out if you need an OrderedDict or if you can use just a normal dict.&lt;/p&gt;
&lt;h3 id=&quot;functoolscache&quot;&gt;@functools.cache&lt;/h3&gt;
&lt;p&gt;If you need a cache, sometimes you can just wrap your code in a function and use &lt;code&gt;functools.cache&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;from functools import cache

@cache
def factorial(n):
    return n * factorial(n - 1) if n else 1
  
print(factorial(5))
...
factorial.cache_info()  # CacheInfo(hits=3, misses=8, maxsize=32, currsize=8)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;debugging-listnodes&quot;&gt;Debugging ListNodes&lt;/h3&gt;
&lt;p&gt;A lot of the problems involve a ListNode class that&#39;s provided by LeetCode. It&#39;s not very &quot;debuggable&quot;. Add this code &lt;em&gt;temporarily&lt;/em&gt; to improve that:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;def list_node_str(head):
    seen_before = set()
    pieces = []
    p = head
    while p is not None:
        if p in seen_before:
            pieces.append(f&#39;loop at {p.val}&#39;)
            break
        pieces.append(str(p.val))
        seen_before.add(p)
        p = p.next
    joined_pieces = &#39;, &#39;.join(pieces)  
    return f&#39;[{joined_pieces}]&#39;


ListNode.__str__ = list_node_str
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;saving-memory-with-the-array-module&quot;&gt;Saving memory with the array module&lt;/h3&gt;
&lt;p&gt;Sometimes you need a really long list of simple numeric (or boolean) values. The &lt;a href=&quot;https://docs.python.org/3/library/array.html&quot;&gt;array&lt;/a&gt; module can help with this, and it&#39;s an easy way to decrease your memory usage &lt;em&gt;after you&#39;ve already gotten your algorithm working&lt;/em&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;&amp;gt;&amp;gt;&amp;gt; import array
&amp;gt;&amp;gt;&amp;gt; array_of_bytes = array.array(&#39;b&#39;)
&amp;gt;&amp;gt;&amp;gt; array_of_bytes.frombytes(b&#39;\0&#39; * (array_of_bytes.itemsize * 10_000_000))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pay close attention to the type of values you configure the array to accept. Read the docs.&lt;/p&gt;
&lt;p&gt;I&#39;m sure there&#39;s a way to use individual bits for an array of booleans to save even more space, but it&#39;d probably cost more CPU, and I generally care about CPU more than memory.&lt;/p&gt;
&lt;h3 id=&quot;using-an-exception-for-the-success-case-rather-than-the-error-case&quot;&gt;Using an exception for the success case rather than the error case&lt;/h3&gt;
&lt;p&gt;A lot of Python programmers don&#39;t like this trick because it&#39;s equivalent to goto, but I still occasionally find it convenient:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;class Eureka(StopIteration):
    &quot;&quot;&quot;Eureka means &quot;I found it!&quot; &quot;&quot;&quot;
    pass

  
def do_something_else():
    some_value = 5
    raise Eureka(some_value)


def do_something():
    do_something_else()


try:
    do_something()
except Eureka as exc:
    print(f&#39;I found it: {exc.args[0]}&#39;)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;using-vs-code-etc&quot;&gt;Updated: Enums&lt;/h3&gt;&lt;div&gt;Python now has a built-in enums:&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;from enum import Enum

# Either:
class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

# Or:
Color = Enum(&#39;Color&#39;, [&#39;RED&#39;, &#39;GREEN&#39;, &#39;BLUE&#39;])&lt;/code&gt;
&lt;/pre&gt;However, in my experience, when coding for LeetCode, just having some local constants (even if the values are strings) is a tad faster and requires a tad less memory:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;pre&gt;&lt;code class=&quot;language-python&quot; lang=&quot;python&quot;&gt;RED = &quot;RED&quot;
GREEN = &quot;GREEN&quot;
BLUE = &quot;BLUE&quot;&lt;/code&gt;
&lt;/pre&gt;&lt;/div&gt;Using strings isn&#39;t actually slow if all you&#39;re doing is pointer comparisons.&lt;h3 id=&quot;using-vs-code-etc&quot;&gt;Updated: Using a profiler&lt;/h3&gt;&lt;div&gt;You&#39;ll need some sample data. Make your code crash when it sees a test case with a lot of data. Grab the data in order to get your code to run on its own. Run something like the following. It&#39;ll print out enough information to figure out how to improve your code.&lt;/div&gt;&lt;div&gt;&lt;pre&gt;import cProfile
cProfile.run(&quot;Solution().someMethod(sampleData)&quot;)
&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&quot;using-vs-code-etc&quot;&gt;Using VS Code, etc.&lt;/h3&gt;
&lt;p&gt;VS Code has a pretty nice Python extension. If you highlight the code and hit shift-enter, it&#39;ll run it in a shell. That&#39;s more convenient than just typing everything directly in the shell. Other editors have something similar, or perhaps you use a Jupyter notebook for this.&lt;/p&gt;
&lt;p&gt;Another thing that helps me is that I&#39;ll often have separate files open with separate attempts at a solution. I guess you can call this the &quot;fast&quot; approach to branching.&lt;/p&gt;
&lt;h3 id=&quot;write-english-before-python&quot;&gt;Write English before Python&lt;/h3&gt;
&lt;p&gt;One thing that helps me a lot is to write English before writing Python. Just write all your thoughts. Keep adding to your list of thoughts. Sometimes you have to start over with a new list of thoughts. Get all the thoughts out, and then pick which thoughts you want to start coding first.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Well, those are my favorite tricks off the top of my head. I&#39;ll add more if I think of any.&lt;/p&gt;
&lt;p&gt;This is just a single blog post, but if you want more, check out &lt;a href=&quot;https://pymotw.com/3/&quot;&gt;Python 3 Module of the Week&lt;/a&gt;.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/8174245613572303600/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/8174245613572303600' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/8174245613572303600'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/8174245613572303600'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2022/08/python-my-favorite-python-tricks-for.html' title='Python: My Favorite Python Tricks for LeetCode Questions'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-5526667477400556150</id><published>2022-06-13T20:17:00.009-07:00</published><updated>2023-04-25T13:10:35.381-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AppSec"/><category scheme="http://www.blogger.com/atom/ns#" term="BSidesSF"/><category scheme="http://www.blogger.com/atom/ns#" term="BSidesSF2022"/><category scheme="http://www.blogger.com/atom/ns#" term="security"/><title type='text'>Security: BSidesSF 2022</title><content type='html'>&lt;h2&gt;Opening Remarks&lt;/h2&gt;
&lt;p&gt;The theme this year is &quot;from the ground up&quot;. They&#39;re focusing on community, collaboration, and education.&lt;/p&gt;
&lt;p&gt;It&#39;s a 100% volunteer team. 25 people work year-round.&lt;/p&gt;
&lt;p&gt;They had speed mentoring sessions.&lt;/p&gt;
&lt;p&gt;They really need some new volunteers. See &lt;a href=&quot;https://bsides.sf/jobs&quot;&gt;bsides.sf/jobs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The talks will be on their YouTube channel.&lt;/p&gt;
&lt;p&gt;They have a stringent photo policy. You must have the permission of everyone in the frame, and crowd shots where you can see faces are strongly discouraged.&lt;/p&gt;
&lt;p&gt;Here is the &lt;a href=&quot;https://bsidessf.org/schedule&quot;&gt;schedule&lt;/a&gt;, and here is their &lt;a href=&quot;https://www.youtube.com/c/BSidesSFTV&quot;&gt;YouTube channel&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;[I wrote these notes by hand and then transcribed them in a single day. I didn&#39;t quite expect them to be so voluminous! Happy hacking!]&lt;/p&gt;
&lt;h2&gt;Keynote: We Need More Mediocre Security Engineers&lt;/h2&gt;
&lt;p&gt;Jackie Bow (@jbowocky) from Asana.&lt;/p&gt;
&lt;p&gt;[This was my favorite talk.]&lt;/p&gt;
&lt;p&gt;She pointed out that BSidesSF was the last in-person conference that a lot of us attended before the pandemic. That was true for her, and it was for me as well.&lt;/p&gt;
&lt;p&gt;She&#39;s held many jobs in security, including malware reverse engineering, which is one of the most hard-core jobs you can have in security.&lt;/p&gt;
&lt;p&gt;She&#39;s worked for Facebook, for the government, etc.&lt;/p&gt;
&lt;p&gt;She said that ClamAV is still the best open-source antivirus software there is.&lt;/p&gt;
&lt;p&gt;One time, she added a virus signature to ClamAV but forgot to add the trailing newline. This broke Facebook Messenger in production for 1-3 hours.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; 82% of breaches involve a human element.&lt;/p&gt;
&lt;p&gt;We expect each other to be perfect in security. We&#39;re not.&lt;/p&gt;
&lt;p&gt;She said, &quot;Have you read InfoSec Twitter? Ugh!&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Extreme expectations lead to burnout, not excellence.&lt;/p&gt;
&lt;p&gt;More != better.&lt;/p&gt;
&lt;p&gt;Burnout is in the standard classification of mental disorders. &quot;Burnout has been defined as a combination of emotional exhaustion, depersonalization, and reduced personal accomplishment caused by chronic work stress&quot; (&lt;a href=&quot;https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4459038/#:~:text=Burnout%20has%20been%20defined%20as,chronic%20work%20stress%20(1).&quot;&gt;cited&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Unfortunately, our work predisposes us to burnout, but we have to avoid burnout if we hope to do this career for a long time.&lt;/p&gt;
&lt;p&gt;Consider COVID-19, Log4J, the Colonial Pipeline hack, Solar Winds, supply chain attacks, Ukraine, etc.&lt;/p&gt;
&lt;p&gt;The Solar Winds thing shook her deeply because she really respected FireEye.&lt;/p&gt;
&lt;p&gt;There are currently 600k people in security. It&#39;s expected that there will be two million open roles. How are we going to add a million new people to the field?&lt;/p&gt;
&lt;p&gt;She referred to Stuxnet.&lt;/p&gt;
&lt;p&gt;Our current burn rate is unsustainable.&lt;/p&gt;
&lt;p&gt;We need to dismantle our concept of a security unicorn.&lt;/p&gt;
&lt;p&gt;We need to see each other as allies. We need to stop overworking. We need to change who we think is hirable.&lt;/p&gt;
&lt;p&gt;We&#39;re too elitist. That&#39;s bad.&lt;/p&gt;
&lt;p&gt;We expect people to know everything. [That&#39;s something I&#39;m struggling with as I prepare to interview.]&lt;/p&gt;
&lt;p&gt;We can&#39;t scale as solo individuals.&lt;/p&gt;
&lt;p&gt;We need to drop the l337 hacker stuff.&lt;/p&gt;
&lt;p&gt;Social isolation and loneliness [which I know all too well] increase the likelihood of early death by 25-30%. It&#39;s equivalent to 15 cigarettes a day.&lt;/p&gt;
&lt;p&gt;Elitism is the enemy of diversity.&lt;/p&gt;
&lt;p&gt;Only 24% of people in security identify as women.&lt;/p&gt;
&lt;p&gt;She used to work on reverse-engineering malware. That&#39;s one of the most technical jobs you can have in security. Now, she feels like a dinosaur because of all this SaaS software, CSRF, etc.&lt;/p&gt;
&lt;p&gt;We end up being expected to always be on.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt;&amp;nbsp;She called it the &quot;wheel of reactive hell&quot;.&lt;/p&gt;
&lt;p&gt;There&#39;s always more work to do.&lt;/p&gt;
&lt;p&gt;Glorifying overworking hurts us all.&lt;/p&gt;
&lt;p&gt;She talked about her kid asking her at 7 PM how much more work she had to do. [I literally started tearing up when she said that because the exact same thing had happened to me the day before.]&lt;/p&gt;
&lt;p&gt;How often do we get to take a vacation longer than a week?&lt;/p&gt;
&lt;p&gt;Vacations are hugely important.&lt;/p&gt;
&lt;p&gt;You can be a great security engineer and still have hobbies--even non-security ones!&lt;/p&gt;
&lt;p&gt;We need to bridge the &quot;talent gap.&quot;&lt;/p&gt;
&lt;p&gt;We&#39;re looking for unicorns. We need to stop that.&lt;/p&gt;
&lt;p&gt;We need to see degrees as a privilege.&lt;/p&gt;
&lt;p&gt;We should look at education as something that should happen once you&#39;re already in the industry.&lt;/p&gt;
&lt;p&gt;There is no agreed-upon value for boot camps or certs.&lt;/p&gt;
&lt;p&gt;We need to offer education as a benefit.&lt;/p&gt;
&lt;p&gt;We really don&#39;t know how to hire for cyber security roles.&lt;/p&gt;
&lt;p&gt;We still demand CS degrees, and that&#39;s bad.&lt;/p&gt;
&lt;p&gt;Your job should pay for you to do boot camps, certs, etc.&lt;/p&gt;
&lt;p&gt;At our current rate, we&#39;ll burn out before the pipeline fixes itself.&lt;/p&gt;
&lt;p&gt;We need to dismantle the unicorn.&lt;/p&gt;
&lt;p&gt;We need to challenge our perceptions of who belongs in this industry to achieve a more diverse workforce.&lt;/p&gt;
&lt;h2&gt;An Unlikely Friendship: Why Security Engineers and Product Managers Should Be Working Together&lt;/h2&gt;
&lt;p&gt;Leif Dreizler (@leifdreizler) and&amp;nbsp;Rachel Landers (@workingrach) from Twilio Segment.&lt;/p&gt;
&lt;p&gt;Segment was acquired by Twilio.&lt;/p&gt;
&lt;p&gt;He&#39;s an engineering manager, and she&#39;s a PM. Their team worked on building security-related features.&lt;/p&gt;
&lt;p&gt;Segment is a customer data platform.&lt;/p&gt;
&lt;p&gt;They use TypeScript and Go.&lt;/p&gt;
&lt;p&gt;Enterprise customers have very high bars. They&#39;re very demanding and noisy.&lt;/p&gt;
&lt;p&gt;They mentioned LocoMocoSec which is a security conference in Hawaii.&lt;/p&gt;
&lt;p&gt;SecEng = security engineering&lt;/p&gt;
&lt;p&gt;Netflix has a great security team. They had this idea that the paved path should lead people to do things securely.&lt;/p&gt;
&lt;p&gt;They talked about a self-service approach to security.&lt;/p&gt;
&lt;p&gt;He talked about the different sides of security. Application security was on his list.&lt;/p&gt;
&lt;p&gt;[It&#39;s amazing how similar their team is to the team I worked on at Udemy.]&lt;/p&gt;
&lt;p&gt;Their first feature was a password strength meter built using zxcvbn and&amp;nbsp;Have I Been Pwned.&lt;/p&gt;
&lt;p&gt;Next, they tackled MFA.&lt;/p&gt;
&lt;p&gt;The biggest feature they tackled was integrating with SCIM. [Our team didn&#39;t do that one. The UB team did that one.]&lt;/p&gt;
&lt;p&gt;You can use SCIM to integrate with Okta or Azure Active Directory to provision users in your app. It&#39;s a system for cross-domain identity management.&lt;/p&gt;
&lt;p&gt;PDLC = product development lifecycle. [We used the term SDLC.]&lt;/p&gt;
&lt;p&gt;Ask yourself, why is this the right time to build this feature?&lt;/p&gt;
&lt;p&gt;IdP = identity provider&lt;/p&gt;
&lt;p&gt;Okta groups were mapped to Segment groups.&lt;/p&gt;
&lt;p&gt;SDD = software design doc&lt;/p&gt;
&lt;p&gt;You should &quot;always be selling&quot;. The SDD should spend a little bit of time convincing people why it&#39;s a good idea to build this feature.&lt;/p&gt;
&lt;p&gt;The PM owns what and when.&lt;/p&gt;
&lt;p&gt;The engineering manager owns how and when it&#39;ll be done.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt;&amp;nbsp;&quot;Weeks of programming can save you days of planning.&quot;&lt;/p&gt;
&lt;p&gt;SCIM is basically CRUD for users and groups.&lt;/p&gt;
&lt;p&gt;He mentioned RFCs 7642, 7643, and 7644.&lt;/p&gt;
&lt;p&gt;When you have to implement query filtering, use a library.&lt;/p&gt;
&lt;p&gt;Read the onboarding docs for each of the IdPs.&lt;/p&gt;
&lt;p&gt;Build the integration with the IdPs.&lt;/p&gt;
&lt;p&gt;He gave Okta props for how smoothly the process went. It took OneLogin almost a year to accept their integration.&lt;/p&gt;
&lt;p&gt;Enterprise software has a bigger focus on security than consumer-facing software.&lt;/p&gt;
&lt;p&gt;1/3 of their customers who use SSO use SCIM.&lt;/p&gt;
&lt;p&gt;ARR = annual recurring revenue.&lt;/p&gt;
&lt;p&gt;The customers they have that use SCIM account for 21% of their ARR.&lt;/p&gt;
&lt;p&gt;Defaults matter a lot!&lt;/p&gt;
&lt;h2&gt;Lunch&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://first.org&quot;&gt;first.org&lt;/a&gt;&amp;nbsp;shares incident response data.&lt;/p&gt;
&lt;p&gt;I talked to some security journalists who piece together news about incidents.&lt;/p&gt;
&lt;p&gt;Boring SSL and libsodium are examples of tools that are simple, easy, and useful.&lt;/p&gt;
&lt;p&gt;OpenSSL is pointlessly and hopelessly complex.&lt;/p&gt;
&lt;p&gt;Code Red Partners is a recruiting firm that focuses on security professionals.&lt;/p&gt;
&lt;h2&gt;Embracing Risk Responsibly: Moving beyond inflexible SLAs and exception hell by treating security vulnerabilities and risk like actual debt&lt;/h2&gt;
&lt;p&gt;Eric Ellett from Segment Twilio&lt;/p&gt;
&lt;p&gt;We need to embrace innovation to get away from having a dumpster fire of a security program.&lt;/p&gt;
&lt;p&gt;Start by buying some time with solutions that are &quot;good enough&quot;.&lt;/p&gt;
&lt;p&gt;Identify and engage with critical customers (which are people inside your company that your security team has to work with).&lt;/p&gt;
&lt;p&gt;He talked about an example where the AppSec team asked a service to fix a P1 issue reported via a bug bounty program.&lt;/p&gt;
&lt;p&gt;He talked about creating metrics for closing vulns.&lt;/p&gt;
&lt;p&gt;When you&#39;re working on a v2 of your program, rebuild the foundation with data. Now you have some time to build a proper foundation.&lt;/p&gt;
&lt;p&gt;He talked about sending formal emails asking people to fix their vulns. A key part of these emails was that they had a due date based on the severity. This due date was possible to extend.&lt;/p&gt;
&lt;p&gt;Attributing vulns to teams was hard because of the constant org changes.&lt;/p&gt;
&lt;p&gt;They tied vulns to divisions and departments.&lt;/p&gt;
&lt;p&gt;They rolled the data up the org chart to enable competition across the company for who could fix their vulns the most quickly.&lt;/p&gt;
&lt;p&gt;At this point in your program, you can start experimenting strategically.&lt;/p&gt;
&lt;p&gt;There are different risk appetites in different parts of the org.&lt;/p&gt;
&lt;p&gt;He referred to Google&#39;s SRE book. He talked about SLIs, SLOs, and SLAs. In particular, he referred to chapter 3 on embracing risk.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important:&amp;nbsp;&lt;/strong&gt;&lt;i&gt;The only truly secure system is one that is powered off, cast in a block of concrete, and sealed in a lead-lined room with armed guards - and even then I have my doubts.&lt;/i&gt; -- Gene Spafford&lt;/p&gt;
&lt;p&gt;He talked about error budgets.&lt;/p&gt;
&lt;p&gt;For an SLO, he talked about uptime per quarter.&lt;/p&gt;
&lt;p&gt;Perfect security and reliability is not the goal--it&#39;s too expensive.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important:&amp;nbsp;&lt;/strong&gt;They created a debt metric: debt = (current_date - orig_date) / sla_in_days&lt;/p&gt;
&lt;p&gt;The higher the priority, the shorter the SLA in days.&lt;/p&gt;
&lt;p&gt;So, if the priority says you have to get it fixed in a day, every day you slip, you&#39;re increasing your debt by 1. However, if the priority says you have to fix it in a month, then it takes a whole month for you to increase your debt by 1.&lt;/p&gt;
&lt;p&gt;As he mentioned before, this debt can be calculated and rolled up organizationally.&lt;/p&gt;
&lt;p&gt;You can break down the debt in different ways.&lt;/p&gt;
&lt;p&gt;He mentioned Snowflake.&lt;/p&gt;
&lt;p&gt;He said that prioritizing work based on a debt metric is more helpful than prioritizing based on severity alone.&lt;/p&gt;
&lt;p&gt;They even integrated the debt metric into CI.&lt;/p&gt;
&lt;p&gt;He said that Segment&#39;s security program is further ahead than the rest of Twilio&#39;s.&lt;/p&gt;
&lt;p&gt;At Segment, they&#39;re not yet tackling the p4s and p5s. They&#39;re too noisy right now.&lt;/p&gt;
&lt;p&gt;He said that compensating controls frequently lower the CVSS which lowers the priority.&lt;/p&gt;
&lt;p&gt;He talked about using Backstage for code asset management--i.e. which team owns the code with the vuln.&lt;/p&gt;
&lt;p&gt;They&#39;re moving from VMs to k8s.&lt;/p&gt;
&lt;h2&gt;Buying Security: A Client&#39;s Guide&lt;/h2&gt;
&lt;p&gt;Rami McCarthy (@ramimacisabird)&lt;/p&gt;
&lt;p&gt;He called himself a &quot;reformed security consultant&quot;.&lt;/p&gt;
&lt;p&gt;Buying security services is hard.&lt;/p&gt;
&lt;p&gt;The security industry is a $100 billion industry.&lt;/p&gt;
&lt;p&gt;Let&#39;s talk about security assessments. This is a comprehensive guide on buying and getting value.&lt;/p&gt;
&lt;p&gt;He mentioned some survey that talked about buying and selling security.&lt;/p&gt;
&lt;p&gt;He mentioned a talk from 2011 called, &lt;a href=&quot;https://www.youtube.com/watch?v=GvX52HPAfBk&quot;&gt;Penetration Testing Considered Harmful&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Consider the question: Is a particular pentest good? The answer lies along a scale that goes from it&#39;s bad to you don&#39;t know.&lt;/p&gt;
&lt;p&gt;White box tests are now dominant. They&#39;re more efficient and more thorough.&lt;/p&gt;
&lt;p&gt;Don&#39;t compare a pentest to a bug bounty program.&lt;/p&gt;
&lt;p&gt;Don&#39;t fall for a dressed-up Nessus scan.&lt;/p&gt;
&lt;p&gt;There are different motivations for getting a security assessment. Risk reduction is the number one reason. The second most common reason is compliance.&lt;/p&gt;
&lt;p&gt;There are different types of vendors.&lt;/p&gt;
&lt;p&gt;It&#39;s hard to know if a vendor is good. Network recommendations are helpful.&lt;/p&gt;
&lt;p&gt;Be careful about how much time you give the vendor. Keep in mind Parkinson&#39;s law.&lt;/p&gt;
&lt;p&gt;Know your scope.&lt;/p&gt;
&lt;p&gt;Gather 3-5 proposals.&lt;/p&gt;
&lt;p&gt;When your goal is compliance, the pentester has to strike a balance between providing value vs. actually enabling you to pass.&lt;/p&gt;
&lt;p&gt;Your own sales clients might tell you who to use since they might have customers asking for proof of compliance via specific vendors.&lt;/p&gt;
&lt;p&gt;The vendor will help you further refine your target scope. You have to hone in on clear objectives and the length of the engagement. These will affect the cost.&lt;/p&gt;
&lt;p&gt;Surprisingly, different vendors will come back with very different quotes.&lt;/p&gt;
&lt;p&gt;&lt;i&gt;Fast, good, and cheap--pick 2.&lt;/i&gt; In security, it&#39;s more like pick 1.&lt;/p&gt;
&lt;p&gt;Be skeptical of cheap proposals and consultants.&lt;/p&gt;
&lt;p&gt;There&#39;s lots of paperwork involved: NDA, MSA, SOW, etc.&lt;/p&gt;
&lt;p&gt;Cure53 actually made their paperwork public.&lt;/p&gt;
&lt;p&gt;Show the pentesters your known risks, your threat models, etc. This will help them.&lt;/p&gt;
&lt;p&gt;Don&#39;t waste their time by leaving in obvious, known vulnerabilities, forcing them to go through your WAF (just let them through), or by giving them an incomplete environment that is missing important data to be useful.&lt;/p&gt;
&lt;p&gt;Their reports are decomposed and sent to different teams. There is usually an executive summary vs. a section with nitty, gritty details.&lt;/p&gt;
&lt;p&gt;A lot of people like getting an overall score or grade.&lt;/p&gt;
&lt;p&gt;Make sure the vendor cleans up after themselves. He saw a case where one vendor left an open shell, and then another vendor found it.&lt;/p&gt;
&lt;p&gt;Remember, no findings != no risk.&lt;/p&gt;
&lt;p&gt;Do root cause and variant analysis.&lt;/p&gt;
&lt;p&gt;Assessments are an expensive way to find vulns.&lt;/p&gt;
&lt;p&gt;For each vuln, you need to fix, mitigate, or accept the risk.&lt;/p&gt;
&lt;p&gt;Remediate the vulns. Don&#39;t just leave them there to be found by the next pentester.&lt;/p&gt;
&lt;p&gt;Do a retro after you&#39;re done.&lt;/p&gt;
&lt;p&gt;You can use canary bugs to see if they&#39;re actually doing their job.&lt;/p&gt;
&lt;p&gt;Consider your pentesting cadence: Once a year? Once every six months?&lt;/p&gt;
&lt;p&gt;Think about the ROI.&lt;/p&gt;
&lt;p&gt;Don&#39;t kill bugs. Kill bug classes.&lt;/p&gt;
&lt;h2&gt;Emerging Best Practices in Software Supply Chain Security: What We Can Learn from Google, the White House, OWASP, and Gartner&lt;/h2&gt;
&lt;p&gt;Tony Loehr from Cycode&lt;/p&gt;
&lt;p&gt;He talked about Google&#39;s SLSA and NIST&#39;s SSDF. These are AppSec frameworks.&lt;/p&gt;
&lt;p&gt;By 2025, 45% of orgs will experience an attack on their supply chain.&lt;/p&gt;
&lt;p&gt;Presidential order 14028 which talked about improving the nation&#39;s cybersecurity had some text which complained about the opaqueness of commercial software.&lt;/p&gt;
&lt;p&gt;It talked about five objectives: protect, confidentiality, identify (SBOM), rapid responses, and training.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; 80% of incidents involve a known vuln that hasn&#39;t been patched.&lt;/p&gt;
&lt;p&gt;He spoke more about Google&#39;s SLSA framework.&lt;/p&gt;
&lt;p&gt;Level 4 requires a two-person review of all changes as well as hermetic, reproducible builds.&lt;/p&gt;
&lt;p&gt;SSDF covers what. SLSA covers how. There are still some gaps.&lt;/p&gt;
&lt;p&gt;He mentioned Terraform.&lt;/p&gt;
&lt;p&gt;He mentioned least privileged access.&lt;/p&gt;
&lt;p&gt;He mentioned anomaly detection.&lt;/p&gt;
&lt;h2&gt;Avoiding insidious points of compromise in infrastructure access systems&lt;/h2&gt;
&lt;p&gt;Sharon Goldberg is the CEO/Co-Founder of BastionZero and is also a tenured professor in the Computer Science Department at Boston University.&lt;/p&gt;
&lt;p&gt;[I was very impressed by her creds. I don&#39;t want to start any rumors, but I&#39;m pretty sure I overheard that at night, she&#39;s a vigilante crime fighter, and she likes to fly fighter jets for fun :-P ]&lt;/p&gt;
&lt;p&gt;She focuses on infra-access systems.&lt;/p&gt;
&lt;p&gt;She wanted to do a detailed breakdown of some war stories.&lt;/p&gt;
&lt;p&gt;Act 1: Standing credentials, VPNs&lt;/p&gt;
&lt;p&gt;Act 2: Zero Trust&lt;/p&gt;
&lt;p&gt;Act 3: Weaknesses in Zero Trust.&lt;/p&gt;
&lt;p&gt;She started by talking about bastion hosts.&lt;/p&gt;
&lt;p&gt;She talked about Fluffy Bunni from 2001. This compromise involved a fake ssh client that stole passwords from compromised users. Even the bastion was infected. However, it wasn&#39;t able to steal ssh key passphrases.&lt;/p&gt;
&lt;p&gt;Lesson: Don&#39;t give users standing credentials, especially passwords. Use MFA.&lt;/p&gt;
&lt;p&gt;Next up, she talked about VPNs.&lt;/p&gt;
&lt;p&gt;She talked about Operation Aurora from 2009. It was a Chinese APT breaking into Akamai. There was a zero-day in IE that allowed the attacker to compromise the entire machine.&lt;/p&gt;
&lt;p&gt;Amazingly, the adversary had a very long dwell time, i.e. they went undetected for a very long time. They were able to move laterally, behind the VPN.&lt;/p&gt;
&lt;p&gt;Their goal was to get to the source code.&lt;/p&gt;
&lt;p&gt;Akamai didn&#39;t even know they were inside. Finally, Google took over some C&amp;amp;C server and told Akamai about the ongoing attack.&lt;/p&gt;
&lt;p&gt;Lesson: Don&#39;t trust people just because they&#39;re on a secured network. That&#39;s the idea behind Zero Trust.&lt;/p&gt;
&lt;p&gt;Akamai also wasn&#39;t segmented very well at the time.&lt;/p&gt;
&lt;p&gt;Lesson: Segment!&lt;/p&gt;
&lt;p&gt;Next, she talked about single-level domain administration such as Active Directory Admin Server.&lt;/p&gt;
&lt;p&gt;She talked about an article named &quot;NotPetya Ransomware&quot; from 2017 that she said was great. She called it a watering hole attack. That&#39;s where you hack some thing and then wait for people to interact with it. In this case, it was Ukrainian tax software.&lt;/p&gt;
&lt;p&gt;Once they were able to steal one credential, they were able to get to all the other machines. The result was that computers were bricked. They literally had to be thrown away.&lt;/p&gt;
&lt;p&gt;She said we too often rely on a privileged system--a system locked down with a single cred.&lt;/p&gt;
&lt;p&gt;Lesson: Vet your supply chain.&lt;/p&gt;
&lt;p&gt;Act 2: Zero Trust&lt;/p&gt;
&lt;p&gt;When it comes to remote access, don&#39;t trust the user just based on their network address. Don&#39;t rely on long-lived creds.&lt;/p&gt;
&lt;p&gt;She talked about some situation involving a certificate authority, an SSO provider, and a proxy. She talked about an x509 certificate or a SAML token.&lt;/p&gt;
&lt;p&gt;She talked about Diginotaur from 2011. She said the incident involved blindly trusting a CA. She said that in her mind this is one of the top 5 incidents of all time.&lt;/p&gt;
&lt;p&gt;Some CA was hacked. The hacker created a certificate for Google, and they used it to snoop on Google&#39;s traffic.&lt;/p&gt;
&lt;p&gt;We later created certificate transparency, etc.&lt;/p&gt;
&lt;p&gt;Next, she covered SolarWinds from 2020. She said the problem here was blindly trusting SSO too much [uh oh].&lt;/p&gt;
&lt;p&gt;She showed two architectures. In one architecture MFA would &lt;i&gt;not&lt;/i&gt;&amp;nbsp;have helped. She said if MFA was separated from the SSO provider, it&#39;d require a second point of compromise.&lt;/p&gt;
&lt;p&gt;Lesson: Users get hacked. Access systems get hacked.&lt;/p&gt;
&lt;p&gt;She recommended reading some article that talked about DigiNotar getting hacked. [Perhaps &lt;a href=&quot;https://slate.com/technology/2016/12/how-the-2011-hack-of-diginotar-changed-the-internets-infrastructure.html&quot;&gt;this one&lt;/a&gt;?]&lt;/p&gt;
&lt;h2&gt;Red Teaming macOS Environments with Hermes the Swift Messenger&lt;/h2&gt;
&lt;p&gt;Justin Bui (@slyd0g)&lt;/p&gt;
&lt;p&gt;He&#39;s a red teamer at Zoom. He&#39;s also a skateboarder.&lt;/p&gt;
&lt;p&gt;He talked about the benefits of the Swift programming language and the Mythic framework.&lt;/p&gt;
&lt;p&gt;He talked about the benefits of using Swift as a post-exploitation language. It now runs on Linux and Windows too.&lt;/p&gt;
&lt;p&gt;Swift can interoperate with C, C++, and ObjC.&lt;/p&gt;
&lt;p&gt;On macOS, Swift is not installed by default, but the libraries are.&lt;/p&gt;
&lt;p&gt;There are several languages used for post-exploitation on macOS: JXA, Python, and Golang are common.&lt;/p&gt;
&lt;p&gt;JXA has been abandoned. Apple said that Python and other scripting languages are deprecated and will be removed. [I noticed it&#39;s no longer present on macOS 12.4 Monterey.]&lt;/p&gt;
&lt;p&gt;He said Golang is fantastic. It too can interoperate with C, C++, and ObjC. It does result in big binaries, though.&lt;/p&gt;
&lt;p&gt;By using the swift command, you can circumvent the app whitelist. However, it&#39;s not installed by default.&lt;/p&gt;
&lt;p&gt;Mythic is a cross-platform, post-exploit, red teaming framework built with python3, docker, docker-compose, and a web browser UI. It has a C&amp;amp;C server.&lt;/p&gt;
&lt;p&gt;He talked about how the implant agent calls back from the victim.&lt;/p&gt;
&lt;p&gt;There are payloads to target macOS.&lt;/p&gt;
&lt;p&gt;He kept talking about LOLBins.&lt;/p&gt;
&lt;p&gt;[I didn&#39;t know what a LOLBin was. Per &lt;a href=&quot;https://www.securityhq.com/blog/security-101-lolbins-malware-exploitation/&quot;&gt;this page&lt;/a&gt;, LOLBins is the abbreviated term for Living Off the Land Binaries. Living Off the Land Binaries are binaries of a non-malicious nature, local to the operating system, that have been utilized and exploited by cyber criminals and crime groups to camouflage their malicious activity.]&lt;/p&gt;
&lt;p&gt;He said that Python and Swift are LOLBins.&lt;/p&gt;
&lt;p&gt;Hermes is a Swift payload for the Mythic framework. He&#39;s the author.&lt;/p&gt;
&lt;p&gt;The Mythic framework makes use of encrypted key exchange in order to encrypt the traffic between the victim and the C&amp;amp;C server.&lt;/p&gt;
&lt;p&gt;Hermes has various modules for post-exploitation.&lt;/p&gt;
&lt;p&gt;By using the Mythic framework, he only had to worry about writing code for the implant side.&lt;/p&gt;
&lt;p&gt;He didn&#39;t want to force developers to use Macs. He said that setting up cross-compilation was the hardest part of the project.&lt;/p&gt;
&lt;p&gt;Darling is a macOS emulation layer for Linux. It&#39;s like Wine, but for macOS. Darling relies on a Linux kernel module.&lt;/p&gt;
&lt;p&gt;He talked about the &quot;operator&quot; who was controlling the C&amp;amp;C server.&lt;/p&gt;
&lt;p&gt;Each job is a separate thread allowing you to run things in parallel.&lt;/p&gt;
&lt;p&gt;He showed Mythic&#39;s web UI. You can upload files to and download files from the victim host from your browser. It can also capture screenshots of the user&#39;s browser.&lt;/p&gt;
&lt;p&gt;It has clipboard monitoring too. Note that root doesn&#39;t have access to the clipboard [weird!]. He talked about nabbing passwords when people copy and paste them.&lt;/p&gt;
&lt;p&gt;He talked about a time when his co-worker reverse-engineered some malware to steal some techniques.&lt;/p&gt;
&lt;p&gt;plist files can be XML, JSON, or binary.&lt;/p&gt;
&lt;p&gt;He keeps focusing on using techniques to snoop on what the user is doing.&lt;/p&gt;
&lt;p&gt;Apple has an Endpoint Security Framework. 3rd-party developers got &quot;pushed out of the kernel&quot;. Because of this, hackers and security software now have equal footing.&lt;/p&gt;
&lt;p&gt;Attackers can use launch agents to achieve persistence.&lt;/p&gt;
&lt;p&gt;It reminded me of spy vs. spy.&lt;/p&gt;
&lt;h2&gt;Open Remarks for Day 2&lt;/h2&gt;
&lt;p&gt;The summary of the Code of Conduct is, &quot;Do not be an ass, or we&#39;ll kick your ass out!&quot;&lt;/p&gt;
&lt;h2&gt;Keynote: Building sustainable security programs&lt;/h2&gt;
&lt;p&gt;Astha Singhal,&amp;nbsp;Director of Security, Netflix&lt;/p&gt;
&lt;p&gt;She too talked about InfoSec burnout.&lt;/p&gt;
&lt;p&gt;This is a job where you never win.&lt;/p&gt;
&lt;p&gt;These are the contributing factors:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Constant firefighting: She referred to Log4J.&lt;/li&gt;
  &lt;li&gt;Security cynicism&lt;/li&gt;
  &lt;li&gt;Culture of catastrophizing&lt;/li&gt;
  &lt;li&gt;Possible vs. probable&lt;/li&gt;
  &lt;li&gt;Personal responsibility&lt;/li&gt;
  &lt;li&gt;Ridiculous and impossible&lt;/li&gt;
  &lt;li&gt;Ongoing conflicts with stakeholders&lt;/li&gt;
  &lt;li&gt;Changing threat landscape&lt;/li&gt;
  &lt;li&gt;We&#39;re never done&lt;/li&gt;
  &lt;li&gt;There are never enough things in the wins column: Only one thing needs to go wrong for bad things to happen.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&#39;s a lot!&lt;/p&gt;
&lt;p&gt;She talked about organizational culture.&lt;/p&gt;
&lt;p&gt;We need to disrupt security cynicism.&lt;/p&gt;
&lt;p&gt;We need to discourage heroics and instead celebrate long-term wins. Proactive investments are better.&lt;/p&gt;
&lt;p&gt;Cuture takes intentionality.&lt;/p&gt;
&lt;p&gt;Build &quot;additive&quot; teams--where each new person adds something unique to the team.&lt;/p&gt;
&lt;p&gt;At one point, all the members of her team were AppSec engineers. They&#39;ve expanded.&lt;/p&gt;
&lt;p&gt;Build an environment of empathy and collaboration.&lt;/p&gt;
&lt;p&gt;Keep in mind business enablement and customer service.&lt;/p&gt;
&lt;p&gt;Consider things from a risk perspective. Our job is to manage risk.&lt;/p&gt;
&lt;p&gt;risk = likelihood * impact&lt;/p&gt;
&lt;p&gt;Help other security engineers think about risk as well.&lt;/p&gt;
&lt;p&gt;Don&#39;t forget about probability or likelihood. Don&#39;t overfocus on things that have extremely high impact but very little likelihood.&lt;/p&gt;
&lt;p&gt;Understand your threat model and why security matters.&lt;/p&gt;
&lt;p&gt;Be rigorous about risk outcomes.&lt;/p&gt;
&lt;p&gt;Have a strategic program focus.&lt;/p&gt;
&lt;p&gt;Consider strategic vs. operational investements.&lt;/p&gt;
&lt;p&gt;Sometimes you have to make &quot;strategic bets&quot; where you choose from among a set of possibilities.&lt;/p&gt;
&lt;p&gt;Consider leverage points and efficiency.&lt;/p&gt;
&lt;p&gt;Minimize the impact to critical data assets.&lt;/p&gt;
&lt;p&gt;Achieving overall security assurance requires a balance of proactive and reactive security controls.&lt;/p&gt;
&lt;p&gt;Stakeholders and leadership have to achieve alignment. It&#39;s helpful to understand senior leadership&#39;s risk appetite.&lt;/p&gt;
&lt;p&gt;Netflix open-sourced some library for quantifying risk.&lt;/p&gt;
&lt;p&gt;You need to create shared guiding principals.&lt;/p&gt;
&lt;p&gt;You need ongoing visibility and reasonable expectations.&lt;/p&gt;
&lt;p&gt;You need to show up for the customers with reasonable expectations that are in line with your risk tolerance.&lt;/p&gt;
&lt;h2&gt;The CISO Panel Discussion&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;Tom Alcock, Partner and Founder, Code Red Partners (moderator)&lt;/li&gt;
  &lt;li&gt;Caleb Sima, Chief Security Officer, Robinhood&lt;/li&gt;
  &lt;li&gt;Fermin Serna, Chief Security Officer, Databricks&lt;/li&gt;
  &lt;li&gt;Jessica Ferguson, Chief Security Officer,&amp;nbsp;Docusign&lt;/li&gt;
&lt;/ul&gt;They started by talking about the key factors for building a security team from scratch.
&lt;p&gt;Focus on assessments, strategy, organization, finding leaders who can help, what you can build with your ICs, and execution. What are you needs, and what are your tools?&lt;/p&gt;
&lt;p&gt;&quot;I wasn&#39;t a CSO. I was essentially a recruiter.&quot;&lt;/p&gt;
&lt;p&gt;People and talent are #1.&lt;/p&gt;
&lt;p&gt;Consider your AppSec to developer ratio.&lt;/p&gt;
&lt;p&gt;The best hires are sometimes a surprise. It might just be someone who happened to be free that came in through someone&#39;s network.&lt;/p&gt;
&lt;p&gt;You can also grab people internally and grow them. This was a big focus for Ferguson. Ferguson also said &quot;You can teach security. You can&#39;t teach innate curiosity.&quot;&lt;/p&gt;
&lt;p&gt;60-70% of sourcing is internal sourcing.&lt;/p&gt;
&lt;p&gt;Sima said you need to convince the candidate that you&#39;re better than the other companies. Call them so that you can explain why you&#39;re better. Sima said that Robinhood sells to the candidate before interviewing them. They reverse the order. That hooks them. They do this even for more junior roles.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;[Sima was easy to like.]&lt;/p&gt;
&lt;p&gt;Every company is a disaster behind the scenes.&lt;/p&gt;
&lt;p&gt;Transparency is key.&lt;/p&gt;
&lt;p&gt;&quot;Sell the disaster.&quot; People want a challenge, and they want to have impact.&lt;/p&gt;
&lt;p&gt;It&#39;s important to overcommunicate, especially now that people are remote. People feel disconnected.&lt;/p&gt;
&lt;p&gt;There are over 100 people on Ferguson&#39;s team at Docusign.&lt;/p&gt;
&lt;p&gt;Remote work is good for deep dive work, but decision making quickly suffers.&lt;/p&gt;
&lt;p&gt;A good manager can hold a team together.&lt;/p&gt;
&lt;p&gt;Be intentional about building diverse teams. It helps to start with diverse panels.&lt;/p&gt;
&lt;p&gt;Ferguson loves growing non-security people and has been really successful with it.&lt;/p&gt;
&lt;p&gt;Initially, start with people who are good generally and have a certain curiosity.&lt;/p&gt;
&lt;p&gt;You need someone to tie all the things and people together.&lt;/p&gt;
&lt;p&gt;As a manager, don&#39;t be a hero. Talk to people. Get advice.&lt;/p&gt;
&lt;p&gt;Someone gave a plug for the CSO at Lyft.&lt;/p&gt;
&lt;p&gt;The recession is an opportunity.&lt;/p&gt;
&lt;p&gt;Don&#39;t try to make security the top priority at the company, but it should be in the top 3 or the top 5.&lt;/p&gt;
&lt;p&gt;The recession offers an opportunity to hire people who are being laid off.&lt;/p&gt;
&lt;p&gt;If you can&#39;t hire, focus on retaining your people.&lt;/p&gt;
&lt;p&gt;Security is important, but running a business is more important.&lt;/p&gt;
&lt;p&gt;If you want to go into security but feel you don&#39;t know enough, you have a skill set that can grow. Don&#39;t get hung up on what you don&#39;t know.&lt;/p&gt;
&lt;p&gt;Someone brought up IR, forensics, managing an investigation, etc.&lt;/p&gt;
&lt;p&gt;Serna said that soft skills are really important. Even how you write an email is really important. You can build bridges or burn bridges.&lt;/p&gt;
&lt;p&gt;It&#39;s nice to have a little bit of passion for the field.&lt;/p&gt;
&lt;p&gt;It&#39;s impressive to see how attackers work.&lt;/p&gt;
&lt;p&gt;Serna said &quot;Don&#39;t be a jerk. It doesn&#39;t cost you anything to be nice.&quot;&lt;/p&gt;
&lt;h2&gt;Rise of the Vermilion: Cross-Platform Cobalt Strike Beacon Targeting Linux and Windows&lt;/h2&gt;
&lt;p&gt;Avigayil Mechtinger (@AbbyMCH)&amp;nbsp;and Ryan Robinson (@MhicRoibin), security researchers from Intezer&lt;/p&gt;
&lt;p&gt;Cobalt Strike is &quot;Software for Adversary Simulations and Red Team Operations&quot;. It&#39;s very popular.&lt;/p&gt;
&lt;p&gt;It&#39;s a malware framework.&lt;/p&gt;
&lt;p&gt;There are different components involved: a C&amp;amp;C server, a stager, a backdoor, a team server, a client.&lt;/p&gt;
&lt;p&gt;It&#39;s hard to detect and easy to configure.&lt;/p&gt;
&lt;p&gt;There are many possible payloads.&lt;/p&gt;
&lt;p&gt;When it&#39;s detected, it&#39;s hard to attribute to a particular attacker.&lt;/p&gt;
&lt;p&gt;It&#39;s meant for red teams, but adversaries use it too. Adversaries will often rely on a cracked version of it. It&#39;s even used by some nation states.&lt;/p&gt;
&lt;p&gt;Geacon is a golang beacon for Linux.&lt;/p&gt;
&lt;p&gt;Only 2% of desktop hosts use Linux, but 90% of hosts in the cloud use Linux.&lt;/p&gt;
&lt;p&gt;There are several categories of malware on Linux: coin miners, botnets, ransomware, backdoors, etc.&lt;/p&gt;
&lt;p&gt;Backdoors are often from nation states such as Russia, North Korea, and China, and they&#39;re targetted in nature.&lt;/p&gt;
&lt;p&gt;They started talking about the rise of Vermilion.&lt;/p&gt;
&lt;p&gt;They do malware analysis. The malware they were analyzing was 94% never-before-seen code and 3% code from Cobalt Strike. That&#39;s weird because this was Linux malware, but the Cobalt Strike malware hadn&#39;t been officially ported to Linux. There was network-related stuff in the code.&lt;/p&gt;
&lt;p&gt;Virus Total reported that none of the virus scanners were catching this malware.&lt;/p&gt;
&lt;p&gt;The name of the binary was nowhere to be seen on Google.&lt;/p&gt;
&lt;p&gt;They called the malware Vermilion.&lt;/p&gt;
&lt;p&gt;It was an elf file. There were strings in the code that would be used if the malware ran on Windows. That&#39;s pretty weird for an elf file which runs on Linux.&lt;/p&gt;
&lt;p&gt;It made use of RSA for encryption.&lt;/p&gt;
&lt;p&gt;The malware fingerprints the machine it&#39;s running on.&lt;/p&gt;
&lt;p&gt;The code runs a C&amp;amp;C loop. They analyzed the commands.&lt;/p&gt;
&lt;p&gt;There&#39;s a Windows version too. Apparently, the Windows version was known as of 2019, but here it is running on Linux.&lt;/p&gt;
&lt;p&gt;They partnered with McAfee.&lt;/p&gt;
&lt;p&gt;The malware was actively targeting high-profile companies.&lt;/p&gt;
&lt;p&gt;There weren&#39;t many samples of victims.&lt;/p&gt;
&lt;p&gt;There was a backdoor, written-from-scratch, which ran on Windows and Linux hosts. It was found in live attacks.&lt;/p&gt;
&lt;p&gt;It was probably from a nation state.&lt;/p&gt;
&lt;p&gt;When running on Linux, the malware flew under the radar.&lt;/p&gt;
&lt;p&gt;It&#39;s a misconception that Linux people think they don&#39;t need antivirus software.&lt;/p&gt;
&lt;p&gt;Mirai is one of the most popular botnets, and it&#39;s not recognized by Virus Total.&lt;/p&gt;
&lt;p&gt;As an industry, we should spend more time detecting Linux malware.&lt;/p&gt;
&lt;p&gt;Vermilion Strike for Windows can be detected in memory, or you can detect the stager.&lt;/p&gt;
&lt;p&gt;They predict that the prevalence of cross-platform malware will continue in the future.&lt;/p&gt;
&lt;h2&gt;Got popcorn? What’s on the Vuln Channel tonight?&lt;/h2&gt;
&lt;p&gt;Rob Jerdonek and&amp;nbsp;Lily Chau from the trust engineering team at Roku&lt;/p&gt;
&lt;p&gt;Apparently, trust team = security team&lt;/p&gt;
&lt;p&gt;They wanted to build static code scanning tools that were as easy to use as watching a movie.&lt;/p&gt;
&lt;p&gt;They mentioned CI/CD integration with Jenkins, k8s, bots that scanned things, a DB, a dashboard, an integration layer, and viewer tools.&lt;/p&gt;
&lt;p&gt;They have a web-based UI for users to view actionable vulnerability data.&lt;/p&gt;
&lt;p&gt;They integrated with Slack.&lt;/p&gt;
&lt;p&gt;They called their work the &quot;Trusty Code Scanning Framework&quot; (TCSF).&lt;/p&gt;
&lt;p&gt;It&#39;s written in Go, Python, and JavaScript, and it uses Docker.&lt;/p&gt;
&lt;p&gt;They integrate with lots of existing code scanning tools such as Semgrep, OSS-Index, npm-audit, Bandit, tfsec, Trivy, Gitleaks, Retire.js, and dependency-check.&lt;/p&gt;
&lt;p&gt;They use one container to discover which other scanners should run. The scanners run in parallel.&lt;/p&gt;
&lt;p&gt;One of the scanners recommends that you use defusedxml for more secure XML parsing in Python.&lt;/p&gt;
&lt;p&gt;They make use of ELK for the DB and dashboards.&lt;/p&gt;
&lt;p&gt;They&#39;re working on building SBOMS.&lt;/p&gt;
&lt;p&gt;They don&#39;t yet block merges.&lt;/p&gt;
&lt;p&gt;Sadly, it&#39;s not yet open source.&lt;/p&gt;
&lt;p&gt;They said they need to reduce the false positives.&lt;/p&gt;
&lt;p&gt;Their main point is that it was really useful for them to build this tool to bring together multiple code scanning tools.&lt;/p&gt;
&lt;h2&gt;Hacker TikTok: Community, Creativity, and Controversy&lt;/h2&gt;
&lt;p&gt;This was a panel discussion about posting security-focused content on TikTok.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Kyle Tobener (moderator)&lt;/li&gt;
  &lt;li&gt;MakeItHackin&lt;/li&gt;
  &lt;li&gt;shenetworks&lt;/li&gt;
  &lt;li&gt;Kylie Robison&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;They showed example TikTok videos:&lt;/p&gt;
&lt;p&gt;You can wrap something in aluminum foil in order to foil an RFID scanner.&lt;/p&gt;
&lt;p&gt;If you use &quot;www.nytimes.com.&quot; (i.e. add a period at the end), you can circumvent their paywall. They have since fixed that vuln. This was used as a response to the prompt, &quot;Show me you&#39;re a hacker without telling me you&#39;re a hacker.&quot;&lt;/p&gt;
&lt;p&gt;TikTok originally had a lot of dancing content.&lt;/p&gt;
&lt;p&gt;Stuff on TikTok goes viral. It&#39;s easy to grow an audience.&lt;/p&gt;
&lt;p&gt;Some guy had cancer, and [somehow, I don&#39;t remember] TikTok helped.&lt;/p&gt;
&lt;p&gt;There&#39;s a great community on TikTok.&lt;/p&gt;
&lt;p&gt;However, it&#39;s a grind to make content consistently.&lt;/p&gt;
&lt;p&gt;You can record and edit in the app, but some people prefer to edit their content outside the app.&lt;/p&gt;
&lt;p&gt;One of panelists tried to produce two pieces of content a day. Another one of them recommended you do it whenever it makes you happy.&lt;/p&gt;
&lt;p&gt;Keep in mind that 33% of your audience is under 19.&lt;/p&gt;
&lt;p&gt;One of the memes was &quot;stuff you know that feels illegal to know&quot;. There was lots of stuff from Defcon.&lt;/p&gt;
&lt;p&gt;TikTok&#39;s recommendation algorithm is &lt;i&gt;so&lt;/i&gt;&amp;nbsp;good! It&#39;s really easy to rabbit hole.&lt;/p&gt;
&lt;p&gt;TikTok definitely has a culture.&lt;/p&gt;
&lt;p&gt;Multiple of the panelists said that TikTok has removed some of their videos showing exploits. That was really frustrating. One of them compared their work to lock picking--just because you learn the art of lockpicking doesn&#39;t mean you plan on doing illegal things. TikTok removed some videos that weren&#39;t even very concrete and specific.&lt;/p&gt;
&lt;p&gt;It&#39;s already hard to show an exploit in 20 seconds. Having TikTok occasionally remove videos adds to the frustration.&lt;/p&gt;
&lt;p&gt;NY Times eventually fixed the &quot;www.nytimes.com.&quot; vuln, but TikTok actually took down the video for 6 days.&lt;/p&gt;
&lt;p&gt;Some women don&#39;t want to get into tech because they have heard so many bad things.&lt;/p&gt;
&lt;p&gt;In one quarter, TikTok removed 90 million videos. Half of those were by automated means. 5% were false positives. Moderation at scale is tough.&lt;/p&gt;
&lt;p&gt;If you show a terminal, they&#39;re more likely to take down your video.&lt;/p&gt;
&lt;p&gt;It&#39;s a problem that some people try to act like gatekeepers who act elitist toward people trying to get into the security industry. We need more people.&lt;/p&gt;
&lt;p&gt;TikTok videos get so many comments, and they&#39;re so unmoderated.&lt;/p&gt;
&lt;p&gt;TikTok is great for building a huge audience of people that you wouldn&#39;t be able to reach on other platforms.&lt;/p&gt;
&lt;p&gt;The panelists enjoyed being creators. Their work on TikTok wasn&#39;t necessarily connected to their day jobs.&lt;/p&gt;
&lt;p&gt;TikTok gives you so much exposure to stuff you&#39;ve never seen before.&lt;/p&gt;
&lt;p&gt;Your communication style is important. Tell a story.&lt;/p&gt;
&lt;p&gt;It&#39;s super easy to get started. You can get started with just your phone and the built-in editor.&lt;/p&gt;
&lt;p&gt;Someone in the audience brought up the &quot;elephant in the room&quot; that we&#39;re security people, and TikTok is partly owned by China.&lt;/p&gt;
&lt;p&gt;It&#39;s true, but it&#39;s &lt;i&gt;such&lt;/i&gt;&amp;nbsp;a great platform.&lt;/p&gt;
&lt;p&gt;One of the panelists did some investigation and found that someone had spent hundreds of thousands of dollars on anti-TikTok campaigns, so keep that in mind.&lt;/p&gt;
&lt;p&gt;TikTok is actually very transparent. It&#39;s not available in China, and they don&#39;t have any servers in China.&lt;/p&gt;
&lt;p&gt;One of the panelists said she was less concerned about China and more concerned about power plants.&lt;/p&gt;
&lt;p&gt;She said that people have ulterior motives for hating on TikTok.&lt;/p&gt;
&lt;p&gt;One of the panelists said that 70% of his viewers were male and 30% were female.&lt;/p&gt;
&lt;p&gt;It&#39;s weird. TikTok knows that he&#39;s male, but when he signed up, he never told them his sex. How do they know?&lt;/p&gt;
&lt;p&gt;It&#39;s a formidable platform. It&#39;s not going away.&lt;/p&gt;
&lt;p&gt;The content is limited to 10 minutes. They weren&#39;t the first short-form video content platform.&lt;/p&gt;
&lt;p&gt;One of the panelists said he limits his content to one minute. With good editing, you can cover a lot of content in one minute.&lt;/p&gt;
&lt;p&gt;When people watch your content on TikTok, they&#39;re searching for specific content. So, it wouldn&#39;t make sense to put a tutorial there.&lt;/p&gt;
&lt;p&gt;Some of the panelists take sponsorships. One of them used it to pay down her student loans.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/5526667477400556150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/5526667477400556150' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/5526667477400556150'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/5526667477400556150'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2022/06/security-bsidessf-2022.html' title='Security: BSidesSF 2022'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-107868319072764489</id><published>2021-11-22T16:08:00.002-08:00</published><updated>2021-11-22T16:09:36.823-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="CS"/><title type='text'>Computer Science: Heisenberg Uncertainty Principle</title><content type='html'>My buddy, Hy Carrel, joked that the Heisenberg Uncertainty Principle as applied to queues suggests that the more sure you want to be that an item in a queue is going to get processed, the less sure you can be of how long it&#39;ll take :-P</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/107868319072764489/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/107868319072764489' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/107868319072764489'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/107868319072764489'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2021/11/computer-science-heisenberg-uncertainty.html' title='Computer Science: Heisenberg Uncertainty Principle'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-1060038853515902815</id><published>2021-10-27T15:08:00.001-07:00</published><updated>2021-10-27T15:11:42.956-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="pyweek"/><title type='text'>Python: PyWeek 32: Lil Miss Vampire</title><content type='html'>&lt;p&gt;TL;DR A world that scrolls infinitely in any direction, an RPG-like UI, and simple, real-time fighting.&lt;/p&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY3ckq612CpjC35bgdoW1pPIjVAjp0uLjoH9lSZYRUC6qs6s7ka2qNY-kNC3PT7IUfftDBLi9VDcz06n6O5eWJ15FlJCR3KZ1f04xpuaD-rUXRNNSxLDs3mHeXDjHkJpDwvLfYig/s0/world_view.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; data-original-height=&quot;621&quot; data-original-width=&quot;799&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY3ckq612CpjC35bgdoW1pPIjVAjp0uLjoH9lSZYRUC6qs6s7ka2qNY-kNC3PT7IUfftDBLi9VDcz06n6O5eWJ15FlJCR3KZ1f04xpuaD-rUXRNNSxLDs3mHeXDjHkJpDwvLfYig/s0/world_view.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-RXAnmhXvqXGC1eXM50IbiSjZ38LsMTh1uqDhx5sWfdka5Vv1JHREHHL2_Z4Bkd2dEBkoG5ujUo7y3wYCN0RjxqGuSiwcJ5NQFXDfL3L-YNnsT0hAM8qTiHNOA5hlXQb0L0kKAw/s0/battle_view.png&quot; style=&quot;display: block; padding: 1em 0; text-align: center; &quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; data-original-height=&quot;621&quot; data-original-width=&quot;798&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-RXAnmhXvqXGC1eXM50IbiSjZ38LsMTh1uqDhx5sWfdka5Vv1JHREHHL2_Z4Bkd2dEBkoG5ujUo7y3wYCN0RjxqGuSiwcJ5NQFXDfL3L-YNnsT0hAM8qTiHNOA5hlXQb0L0kKAw/s0/battle_view.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

&lt;iframe allowfullscreen=&#39;allowfullscreen&#39; webkitallowfullscreen=&#39;webkitallowfullscreen&#39; mozallowfullscreen=&#39;mozallowfullscreen&#39; width=&#39;798&#39; height=&#39;621&#39; src=&#39;https://www.blogger.com/video.g?token=AD6v5dy6iLjDcFCjRKAjMjIq9bnvINnZCOtq0-MSuyVgNFDMDqMDs5RrMLdH4EYjwty-Gop9Fr7HIGeALwo&#39; class=&#39;b-hbp-video b-uploaded&#39; frameborder=&#39;0&#39;&gt;&lt;/iframe&gt;

&lt;p&gt;My younger kids and I built this &lt;a href=&quot;https://pyweek.org/e/jjinux-pyweek32/&quot;&gt;entry for PyWeek 32&lt;/a&gt; based on the theme &quot;Neverending&quot;.&lt;/p&gt;

&lt;p&gt;The key innovations are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It has a neverending world. As the player walks along, it picks up tiles and places new ones invisibly. It uses an LRUDict to remember the last million tiles you&#39;ve seen. This matches real life in that if you go back to a place after 20 years, it&#39;ll look different than when you first saw it.&lt;/li&gt;
&lt;li&gt;The user interface was inspired by Super Mario RPG, but the fighting mechanics are purposely realtime. It&#39;s a lot like if you were playing Street Fighter, but all you were allowed to do was use a fast punch, a slow punch, or block. It&#39;s a little bit like roshambo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The code is pretty pleasant. I made use of lots of new features in the latest Python, and I built a pretty decent developer experience.&lt;/li&gt;
&lt;li&gt;It&#39;s built on the excellent arcade library which has exceptionally good documentation, tutorials, and examples.&lt;/li&gt;
&lt;li&gt;I used type annotations everywhere, and I enforced them via mypy. I made extensive use of `typing.NamedTuple` which gives it a nice, immutable, well-typed flavor.&lt;/li&gt;
&lt;li&gt;I used black to format the code during check-in.&lt;/li&gt;
&lt;li&gt;There are extensive unit tests for the models. And there are git hooks to keep everything sane.&lt;/li&gt;
&lt;li&gt;Running `make iterate` will reformat the code, run mypy to enforce types, run the unit tests, and then launch the game.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here&#39;s the &lt;a href=&quot;https://github.com/jjinux/pyweek32-neverending/blob/master/README.md&quot;&gt;GitHub page&lt;/a&gt; with more details.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/1060038853515902815/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/1060038853515902815' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/1060038853515902815'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/1060038853515902815'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2021/10/python-pyweek-32-lil-miss-vampire.html' title='Python: PyWeek 32: Lil Miss Vampire'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY3ckq612CpjC35bgdoW1pPIjVAjp0uLjoH9lSZYRUC6qs6s7ka2qNY-kNC3PT7IUfftDBLi9VDcz06n6O5eWJ15FlJCR3KZ1f04xpuaD-rUXRNNSxLDs3mHeXDjHkJpDwvLfYig/s72-c/world_view.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-8883144696844476696</id><published>2021-09-27T17:34:00.011-07:00</published><updated>2021-09-27T19:24:44.970-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="security"/><title type='text'>Security: What Percentage of Passwords are Pure ASCII?</title><content type='html'>&lt;p&gt;I was wondering what percentage of passwords are pure ASCII. Hence, I threw together some code:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/usr/bin/env python3

PASSWORD_LIST = &quot;example.txt&quot;

num_pure_ascii = 0
num_iso_8859_1_not_ascii = 0
num_passwords = 0
with open(PASSWORD_LIST, mode=&quot;rb&quot;) as f:
    for line in f:
        password = line.rstrip(b&quot;\n&quot;)
        num_passwords += 1
        
        try:
            password.decode(&#39;ASCII&#39;)
            num_pure_ascii += 1
            print(&quot;Pure ASCII:&quot;, password, flush=True)
            
        except UnicodeDecodeError:
            try:
                password.decode(&#39;UTF-8&#39;).encode(&#39;ISO-8859-1&#39;)
                num_iso_8859_1_not_ascii += 1
                print(&quot;ISO-8859-1 (but not pure ASCII):&quot;, password, flush=True)

            except (UnicodeEncodeError, UnicodeDecodeError):
                print(&quot;Not encodable into ASCII or ISO-8859-1:&quot;, password, flush=True)

    percentage_pure_ascii = (100 * num_pure_ascii) / num_passwords        
    percentage_iso_8859_1_not_ascii = (100 * num_iso_8859_1_not_ascii) / num_passwords
    print(&quot;Num passwords:&quot;, num_passwords)
    print(&quot;Percentage that are pure ASCII:&quot;, percentage_pure_ascii)
    print(&quot;Percentage that are not pure ASCII but can be encoded into ISO-8859-1:&quot;, percentage_iso_8859_1_not_ascii)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using the largest password list from Metasploit, &lt;code&gt;/usr/share/wordlists/metasploit/password.lst&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Num passwords: 88397&lt;/li&gt;
  &lt;li&gt;Percentage that are pure ASCII: 99.65%&lt;/li&gt;
  &lt;li&gt;Percentage that are not pure ASCII but can be encoded into ISO-8859-1: 0.0%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using the top 100,000 passwords according to &lt;a href=&quot;https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10-million-password-list-top-1000000.txt&quot;&gt;https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10-million-password-list-top-1000000.txt&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Num passwords: 999998&lt;/li&gt;
  &lt;li&gt;Percentage that are pure ASCII: 99.9998%&lt;/li&gt;
  &lt;li&gt;Percentage that are not pure ASCII but can be encoded into ISO-8859-1: 0.0002%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;https://crackstation.net/crackstation-wordlist-password-cracking-dictionary.htm&quot;&gt;CrackStation&#39;s Password Cracking Dictionary&lt;/a&gt; (human passwords only):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Num passwords: 63,941,069&lt;/li&gt;
  &lt;li&gt;Percentage that are pure ASCII: 99.93%&lt;/li&gt;
  &lt;li&gt;Percentage that are not pure ASCII but can be encoded into ISO-8859-1: 0.0259%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The results seem suspicious, so I wonder if I&#39;m doing something wrong. I really expected more passwords would contain things like ñ and í, which my code would report as &quot;not pure ASCII but can be encoded into ISO-8859-1&quot;.&lt;/p&gt;

&lt;p&gt;Feel free to try it on your own password list and report the results below.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/8883144696844476696/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/8883144696844476696' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/8883144696844476696'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/8883144696844476696'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2021/09/security-what-percentage-of-passwords.html' title='Security: What Percentage of Passwords are Pure ASCII?'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-501828418799432830</id><published>2021-08-07T15:05:00.004-07:00</published><updated>2021-08-07T15:05:50.741-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="typescript"/><title type='text'>Type Annotations T-Shirt</title><content type='html'>&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEAiM-ehs5HH_jnZVQ48ARR-NO97Gmn7QK5fftzwsNJZb3vVAl4WY6PRwjNP-INPI1TTuVTbwa7eeHdA1kBmrSu-4av1UU-fIJobGdI7w2nYH31UWsovZ8PZ1GACm1yq1PhY0xEQ/s2048/IMG_6714.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1539&quot; data-original-width=&quot;2048&quot; height=&quot;480&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEAiM-ehs5HH_jnZVQ48ARR-NO97Gmn7QK5fftzwsNJZb3vVAl4WY6PRwjNP-INPI1TTuVTbwa7eeHdA1kBmrSu-4av1UU-fIJobGdI7w2nYH31UWsovZ8PZ1GACm1yq1PhY0xEQ/w640-h480/IMG_6714.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/501828418799432830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/501828418799432830' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/501828418799432830'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/501828418799432830'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2021/08/type-annotations-t-shirt.html' title='Type Annotations T-Shirt'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEAiM-ehs5HH_jnZVQ48ARR-NO97Gmn7QK5fftzwsNJZb3vVAl4WY6PRwjNP-INPI1TTuVTbwa7eeHdA1kBmrSu-4av1UU-fIJobGdI7w2nYH31UWsovZ8PZ1GACm1yq1PhY0xEQ/s72-w640-h480-c/IMG_6714.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-570029428563335149</id><published>2021-07-31T10:52:00.000-07:00</published><updated>2021-07-31T10:52:03.273-07:00</updated><title type='text'>A Space Engine</title><content type='html'>&lt;p&gt;&amp;nbsp;(I&#39;m talking about stuff I don&#39;t understand, so feel free to ignore me.)&lt;/p&gt;&lt;p&gt;Space isn&#39;t entirely empty. There are a few hydrogen atoms hanging out here and there.&lt;/p&gt;&lt;p&gt;Imagine if a spacecraft was flying really fast, and it was collecting those tiny few. It could either use a massive funnel at the front of it, or it could use something electromagnetic. Once it collects them, it could use fusion to release energy. Then, on the other side of the spacecraft, it could shoot out the output as hard as possible.&amp;nbsp;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/570029428563335149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/570029428563335149' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/570029428563335149'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/570029428563335149'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2021/07/a-space-engine.html' title='A Space Engine'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-11788780.post-4636826048876441006</id><published>2021-05-15T14:11:00.005-07:00</published><updated>2021-05-15T14:29:53.129-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Linux"/><category scheme="http://www.blogger.com/atom/ns#" term="macOS"/><category scheme="http://www.blogger.com/atom/ns#" term="unix"/><title type='text'>Add Another Entry to the UNIX Haters&#39; Handbook</title><content type='html'>&lt;p&gt;I was using the command line to quickly build out a file hierarchy. I wrote something that looked basically like:&lt;/p&gt;

&lt;pre&gt;mkdir -p &quot;~/dir/a b/c d&quot;&lt;/pre&gt;

&lt;p&gt;I meant for &lt;code&gt;dir&lt;/code&gt; to be in my home directory. I should have put the &lt;code&gt;~/&lt;/code&gt; outside the doublequotes. Hence, it actually ended up creating a directory called &lt;code&gt;~&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I thought, &quot;Well that was dumb. Let me delete that and start over...&quot; So I wrote:&lt;/p&gt;

&lt;pre&gt;rm -rf ~&lt;/pre&gt;

&lt;p&gt;As you can imagine, that started recursively deleting things from my home directory. I should have put the &lt;code&gt;~&lt;/code&gt; in double quotes or written &lt;code&gt;./~&lt;/code&gt;.&lt;/p&gt;
  
&lt;p&gt;I hit control-c once I started seeing strange errors, but I was a bit late. It started deleting things all over the place. It complained that it couldn&#39;t delete a bunch of things in &lt;code&gt;~/Library&lt;/code&gt;, but it did end up deleting a bunch of other things there. Apps started acting strangely or crashing. It deleted my Google Drive settings, but not the files themselves. I was really worried that it&#39;d delete the files and synchronize the deletions to the server, but it didn&#39;t. Thankfully, it didn&#39;t delete any of my VMs. That would have been painful.&lt;/p&gt;

&lt;p&gt;I eventually just created a new user, switched to that user, moved my stuff out of the way, deleted and recreated my original user, and rebuilt things from scratch using my notes. I tend to log everything I do when setting up a machine. All of my stuff is in the cloud, so I don&#39;t really worry about backups.&lt;/p&gt;

&lt;p&gt;BTW, if you haven&#39;t read the &lt;a href=&quot;https://web.mit.edu/~simsong/www/ugh.pdf&quot;&gt;UNIX Haters Handbook&lt;/a&gt;, it&#39;s a lot of fun. My buddy, Travis, put it perfectly when he said, &quot;I love the UNIX command line, but sometimes it&#39;s a bit like juggling chainsaws.&quot;&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='https://www.jjinux.com/feeds/4636826048876441006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment/fullpage/post/11788780/4636826048876441006' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/4636826048876441006'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/11788780/posts/default/4636826048876441006'/><link rel='alternate' type='text/html' href='https://www.jjinux.com/2021/05/add-another-entry-to-unix-haters.html' title='Add Another Entry to the UNIX Haters&#39; Handbook'/><author><name>jjinux</name><uri>http://www.blogger.com/profile/03270879497119114175</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd77nhvLhiaGcWLz4oEuntnmwyP09xsoqajQsHlwcYnfbQAsXOhXFV4VxoZPFJbGgSXUo6v2uw3WWDn47iv8NpuAqlOL71HOsY3yvyFGKxEBDWzY2y0hJalFJ2fu18ZQ/s220/jj_google_headshot.jpeg'/></author><thr:total>1</thr:total></entry></feed>