<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Sainsmograf]]></title>
  <link href="https://www.sainsmograf.com/atom.xml" rel="self"/>
  <link href="https://www.sainsmograf.com/"/>
  <updated>2024-03-03T12:11:40.571527</updated>
  <id>https://www.sainsmograf.com/</id>
  <author>
    <name><![CDATA[Arif Widi Nugroho]]></name>
    
  </author>
  <generator uri="https://www.sainsmograf.com/">Sainsmograf Static Generator</generator>

  
  
  <entry>
    <title type="html"><![CDATA[Cryptography Primer]]></title>
    <link href="https://www.sainsmograf.com/blog/2020/05/25/setting-up-automatic-daily-database-backup-on-kubernetes/"/>
    <updated>2020-05-25T10:19:29.430441</updated>
    <id>https://www.sainsmograf.com/blog/2020/05/25/setting-up-automatic-daily-database-backup-on-kubernetes/</id>
    <content type="html"><![CDATA[
      <h1>Setting Up Automatic Daily Database Backup on Kubernetes (Updated: 2024-03-03)</h1>
<p>Kubernetes has been supporting <a href="https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/">StatefulSets</a> for a while now, so it's a no brainer to deploy a database app in a Kubernetes cluster. Statefulset allows your pods to maintain sticky, persistent IDs, as well as persistent storage, making it ideal for database apps. Still, even with persistent storage, you should always configure automatic offsite backup when deploying a database app on a Kubernetes cluster. This would ensure your data survives any disaster that might befall your new shiny cluster.</p>
<p>Automatic offsite backups can be a hassle, but it doesn't have to be. In this post, I'm going to setup an automatic daily backup on a MySQL pod into a Backblaze B2 bucket.</p>
<h2>Step 1: Automatically Dump All Databases into a Persistent Volume</h2>
<p>I want to dump all databases inside a MySQL pod into a persistent volume. Each database will be dumped into a separate file (so I can load them individually as needed later) on a persistent volume which will be uploaded into a Backblaze B2 bucket later. I'll use Kubernetes' new <a href="https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/">CronJob</a> workload to schedule a daily database dump job.</p>
<p>It's quite annoying to set this up over and over again, so I packed a small MySQL backup script into a container (<code>arifwn/container-backup:mysql</code>) suitable for use inside a Kubernetes' CronJob workload. This docker image can be used to backup a specific database or all databases. The source code is availabe on my github repo here: <a href="https://github.com/arifwn/container-backup">https://github.com/arifwn/container-backup</a>.</p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">batch/v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">CronJob</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">backup-all-mysql80-db</span>
<span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">backups</span>
<span class="nt">spec</span><span class="p">:</span>
<span class="w">  </span><span class="nt">concurrencyPolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Forbid</span>
<span class="w">  </span><span class="nt">failedJobsHistoryLimit</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w">  </span><span class="nt">jobTemplate</span><span class="p">:</span>
<span class="w">    </span><span class="nt">spec</span><span class="p">:</span>
<span class="w">      </span><span class="nt">backoffLimit</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">3</span>
<span class="w">      </span><span class="nt">completions</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w">      </span><span class="nt">template</span><span class="p">:</span>
<span class="w">        </span><span class="nt">spec</span><span class="p">:</span>
<span class="w">          </span><span class="nt">containers</span><span class="p">:</span>
<span class="w">          </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">env</span><span class="p">:</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">DBNAME</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ALL</span><span class="w"> </span><span class="c1"># specify a specific database name here, or ALL to backup all databases</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">HOST</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mysql80.mysql.svc.cluster.local</span><span class="w"> </span><span class="c1"># your MySQL host</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">USER</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">root</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">PASSWORD</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">absolutelysecret</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">PORT</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;3306&quot;</span>
<span class="w">            </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">arifwn/container-backup:mysql80</span>
<span class="w">            </span><span class="nt">imagePullPolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">IfNotPresent</span>
<span class="w">            </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">backup-all-mysql80-db</span>
<span class="w">            </span><span class="nt">volumeMounts</span><span class="p">:</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">mountPath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/dump</span>
<span class="w">              </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mysql80-backup-volume-all</span>
<span class="w">              </span><span class="nt">subPath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mysql80</span>
<span class="w">          </span><span class="nt">volumes</span><span class="p">:</span>
<span class="w">          </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mysql80-backup-volume-all</span>
<span class="w">            </span><span class="nt">persistentVolumeClaim</span><span class="p">:</span>
<span class="w">              </span><span class="nt">claimName</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">backup-storage-pv-claim</span>
<span class="w">  </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0 2 * * *</span>
<span class="w">  </span><span class="nt">successfulJobsHistoryLimit</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">3</span>
</code></pre></div></td></tr></table></div>

<p>This will create a new <code>CronJob</code> workload entry on the Kubernetes cluster that run every 2:00 AM everyday. I also mounted a persistent volume (created beforehand) that will be used to store the resulting <code>.sql</code> dumps. We'll mount this volume in another <code>CronJob</code> entry to upload the content to Backblaze B2 later.</p>
<p>Using PostgreSQL? No problem!</p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">batch/v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">CronJob</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">backup-all-postgres16-db</span>
<span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">backups</span>
<span class="nt">spec</span><span class="p">:</span>
<span class="w">  </span><span class="nt">concurrencyPolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Forbid</span>
<span class="w">  </span><span class="nt">failedJobsHistoryLimit</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w">  </span><span class="nt">jobTemplate</span><span class="p">:</span>
<span class="w">    </span><span class="nt">spec</span><span class="p">:</span>
<span class="w">      </span><span class="nt">backoffLimit</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">3</span>
<span class="w">      </span><span class="nt">completions</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w">      </span><span class="nt">template</span><span class="p">:</span>
<span class="w">        </span><span class="nt">spec</span><span class="p">:</span>
<span class="w">          </span><span class="nt">containers</span><span class="p">:</span>
<span class="w">          </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">env</span><span class="p">:</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">DBNAME</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ALL</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">HOST</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">postgres16.database.svc.cluster.local</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">PASSWORD</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">absolutelysecret</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">PORT</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;5432&quot;</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">USER</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">postgres</span>
<span class="w">            </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">arifwn/container-backup:postgresql-16</span>
<span class="w">            </span><span class="nt">imagePullPolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">IfNotPresent</span>
<span class="w">            </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">backup-all-postgres16-db</span>
<span class="w">            </span><span class="nt">volumeMounts</span><span class="p">:</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">mountPath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/dump</span>
<span class="w">              </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">postgres16-backup-volume-all</span>
<span class="w">              </span><span class="nt">subPath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">postgres16</span>
<span class="w">          </span><span class="nt">volumes</span><span class="p">:</span>
<span class="w">          </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">postgres16-backup-volume-all</span>
<span class="w">            </span><span class="nt">persistentVolumeClaim</span><span class="p">:</span>
<span class="w">              </span><span class="nt">claimName</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">backup-storage-pv-claim</span>
<span class="w">  </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0 2 * * *</span>
<span class="w">  </span><span class="nt">successfulJobsHistoryLimit</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">3</span>
</code></pre></div></td></tr></table></div>

<h2>Step 2: Upload to a Backblaze B2 Bucket</h2>
<p>Next is uploading the <code>.sql</code> files generated from the last step into a Backblaze B2 bucket. <a href="https://www.backblaze.com/b2/cloud-storage.html">Backblaze B2</a> is a (very) cheap cloud storage service ($0.006/GB/Mo) from Backblaze with free ingress bandwidth cost, perfect for storing large backup data offsite. Egress is also cheap (free up to 3x monthly storage, then $0.01/GB) and very fast, unlike some other cheap cloud backup solution (e.g. AWS Glacier).</p>
<p>I also packed my trusty B2 backup script into a docker image (<code>arifwn/container-backup:b2</code>). This image will compress each top-level folder in the mounted volume into a <code>.tar.gz</code> archive and upload it into the specified B2 bucket. The image will also perform daily cleanup on the target bucket so only the last 7 daily backups, the last 8 weekly backups, and the last 12 monthly backups retained. The source code is availabe on my github repo here: <a href="https://github.com/arifwn/container-backup">https://github.com/arifwn/container-backup</a>.</p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">batch/v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">CronJob</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">backblaze-backup</span>
<span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">backups</span>
<span class="nt">spec</span><span class="p">:</span>
<span class="w">  </span><span class="nt">concurrencyPolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Forbid</span>
<span class="w">  </span><span class="nt">failedJobsHistoryLimit</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w">  </span><span class="nt">jobTemplate</span><span class="p">:</span>
<span class="w">    </span><span class="nt">spec</span><span class="p">:</span>
<span class="w">      </span><span class="nt">backoffLimit</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">3</span>
<span class="w">      </span><span class="nt">completions</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w">      </span><span class="nt">template</span><span class="p">:</span>
<span class="w">        </span><span class="nt">spec</span><span class="p">:</span>
<span class="w">          </span><span class="nt">containers</span><span class="p">:</span>
<span class="w">          </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">env</span><span class="p">:</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">B2_ACCOUNT_ID</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">accountid</span><span class="w"> </span><span class="c1"># replace with your B2 account id</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">B2_API_KEY</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">secretkey</span><span class="w"> </span><span class="c1"># replace with your B2 API Key</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">BUCKET_NAME</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mysql-backup</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">SOURCE_DIR</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/source/</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">SYSTEM_NAME</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">My Cluster</span>
<span class="w">            </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">arifwn/container-backup:b2</span>
<span class="w">            </span><span class="nt">imagePullPolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">IfNotPresent</span>
<span class="w">            </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">backblaze-backup</span>
<span class="w">            </span><span class="nt">resources</span><span class="p">:</span>
<span class="w">              </span><span class="nt">limits</span><span class="p">:</span>
<span class="w">                </span><span class="nt">cpu</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;100m&quot;</span><span class="w"> </span><span class="c1"># don&#39;t use too much cpu to avoid starving the node</span>
<span class="w">            </span><span class="nt">volumeMounts</span><span class="p">:</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">mountPath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/source</span>
<span class="w">              </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">source-data-volume</span>
<span class="w">          </span><span class="nt">volumes</span><span class="p">:</span>
<span class="w">          </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">source-data-volume</span>
<span class="w">            </span><span class="nt">persistentVolumeClaim</span><span class="p">:</span>
<span class="w">              </span><span class="nt">claimName</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">backup-storage-pv-claim</span>
<span class="w">  </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">30 2 * * *</span>
<span class="w">  </span><span class="nt">successfulJobsHistoryLimit</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">3</span>
</code></pre></div></td></tr></table></div>

<p>This will create a new <code>CronJob</code> workload entry on the Kubernetes cluster that run every 2:30 AM everyday (plenty of time for the database dump cron to complete). The cron will compress all data found inside the mounted volume (each top-level folder will be compressed into a separate <code>.tar.gz</code> archive), upload them into a B2 bucket, and remove any old backup archives except the last 7 daily backups, the last 8 weekly backups, and the last 12 monthly backups.</p>
<p>And that's it! The database is now backed up automatically every night to a B2 bucket. It only take minutes to setup and you can sleep soundly at night knowing your data is safe from random cluster failure. Don't forget to setup <code>CronJob</code> failure alert so you'll get notified when uploads failed (the B2 backup image will return with non-zero exit code on failure).</p>
<h2>Step 3 (Optional): Upload to an Offsite Server with RSync</h2>
<p>You can't have enough backup these days. While having copies of your data on B2 is great for your peace of mind, having yet another copy safely stored in another backup provider is great for redundancy. <a href="https://rsync.net/">RSync.net</a> is a great backup provider and supports automatic daily snapshots so you can go back in time to retrieve previous version of your file. All you need to do is generating a new ssh key and <a href="https://www.rsync.net/resources/howto/ssh_keys.html">upload them to your rsync.net server</a>, then use those keys on the config below.</p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">batch/v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">CronJob</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">rsync-backup</span>
<span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">backups</span>
<span class="nt">spec</span><span class="p">:</span>
<span class="w">  </span><span class="nt">concurrencyPolicy</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">Forbid</span>
<span class="w">  </span><span class="nt">failedJobsHistoryLimit</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w">  </span><span class="nt">jobTemplate</span><span class="p">:</span>
<span class="w">    </span><span class="nt">spec</span><span class="p">:</span>
<span class="w">      </span><span class="nt">backoffLimit</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">3</span>
<span class="w">      </span><span class="nt">completions</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1</span>
<span class="w">      </span><span class="nt">template</span><span class="p">:</span>
<span class="w">        </span><span class="nt">spec</span><span class="p">:</span>
<span class="w">          </span><span class="nt">containers</span><span class="p">:</span>
<span class="w">          </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">env</span><span class="p">:</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TARGET</span>
<span class="w">              </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">youraccount@yourhost.rsync.net:your-target-path</span><span class="w"> </span><span class="c1"># replace with your rsync.net account name</span>
<span class="w">            </span><span class="nt">envFrom</span><span class="p">:</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">configMapRef</span><span class="p">:</span>
<span class="w">              </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">rsync-backup-base-env-config</span>
<span class="w">            </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">arifwn/container-backup:rsync</span>
<span class="w">            </span><span class="nt">imagePullPolicy</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;IfNotPresent&quot;</span>
<span class="w">            </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">rsync-backup</span>
<span class="w">            </span><span class="nt">resources</span><span class="p">:</span>
<span class="w">              </span><span class="nt">limits</span><span class="p">:</span>
<span class="w">                </span><span class="nt">cpu</span><span class="p">:</span><span class="w"> </span><span class="s">&quot;100m&quot;</span><span class="w"> </span><span class="c1"># don&#39;t use too much cpu to avoid starving the node</span>
<span class="w">            </span><span class="nt">volumeMounts</span><span class="p">:</span>
<span class="w">            </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">mountPath</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/source</span>
<span class="w">              </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">source-data-volume</span>
<span class="w">          </span><span class="nt">volumes</span><span class="p">:</span>
<span class="w">          </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">source-data-volume</span>
<span class="w">            </span><span class="nt">persistentVolumeClaim</span><span class="p">:</span>
<span class="w">              </span><span class="nt">claimName</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">backup-storage-pv-claim</span>
<span class="w">  </span><span class="nt">schedule</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">30 2 * * *</span>
<span class="w">  </span><span class="nt">successfulJobsHistoryLimit</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">3</span>
<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ConfigMap</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">rsync-backup-base-env-config</span>
<span class="w">  </span><span class="nt">labels</span><span class="p">:</span>
<span class="w">    </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">rsync-backup</span>
<span class="nt">data</span><span class="p">:</span>
<span class="w">  </span><span class="nt">PRIVATE_KEY</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span>
<span class="w">    </span><span class="no">-----BEGIN RSA PRIVATE KEY-----</span>
<span class="w">    </span><span class="no">Your SSH Private Key</span>
<span class="w">    </span><span class="no">-----END RSA PRIVATE KEY-----</span>
<span class="w">  </span><span class="nt">PUBLIC_KEY</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">|</span>
<span class="w">    </span><span class="no">Your SSH Public Key</span>
</code></pre></div></td></tr></table></div>

<p>Note that you don't have to use RSync.net, any host with ssh access will do.</p>
    ]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Cryptography Primer]]></title>
    <link href="https://www.sainsmograf.com/blog/2017/01/15/introducing-tiny-suspender-a-tab-suspension-extension-for-chrome/"/>
    <updated>2017-01-15T18:39:27.232323</updated>
    <id>https://www.sainsmograf.com/blog/2017/01/15/introducing-tiny-suspender-a-tab-suspension-extension-for-chrome/</id>
    <content type="html"><![CDATA[
      <h1>Introducing Tiny Suspender: A Tab Suspension Extension for Chrome</h1>
<p><i>TL;DR Download it here: <a href="https://chrome.google.com/webstore/detail/tiny-suspender/bbomjaikkcabgmfaomdichgcodnaeecf">https://chrome.google.com/webstore/detail/tiny-suspender/bbomjaikkcabgmfaomdichgcodnaeecf</a> </i></p>
<p>If you use Chrome as your primary browser, you probably aware of its memory and resource hogging nature. Every time you open a new tab, a new process get spawned that dedicated only for that tab. It's great from reliability and security stand point, but not so great when you try to cut down resource consumption which can be critical if you're on battery power (since higher resource usage typically translate to higher power consumption).</p>
<p>The Chrome dev team has performed various optimization with great results. Chrome hogs less resources now, which is great for casual users. But for users who open dozens and dozens of tabs at the same time (even hundreds!), this improvement is not enough. That's why we rely on tab suspender extensions such as The Great Suspender to reduce Chrome's CPU and memory usage when it has so many background tabs.</p>
<p>I've been using The Great Suspender for a while, and it actually works great. One day, I decided I want to build a suspender extension on my own, and the result is <a href="https://chrome.google.com/webstore/detail/tiny-suspender/bbomjaikkcabgmfaomdichgcodnaeecf">Tiny Suspender</a>. It actually has been released in Chrome Web Store for a while now. It even gather ~250 users so far. Thanks to feedbacks from those brave users (they're essentially alpha-testing the extension on their own!), Tiny Suspender finally has all features I ever want. In fact, without those users I probably would leave Tiny Suspender in barely usable state (since it was good enough for my own use). Thanks a lot guys!</p>
<h3>So what's so special about Tiny Suspender?</h3>
<p>Usual features you would expect from a suspender plugin:</p>
<ul>
<li>
<p>Automatic and manual tab suspension: Automatically suspend background tabs, or manually suspend the tabs yourself</p>
</li>
<li>
<p>Form Detection: Tiny Suspender will also try to detect active form to avoid automatically suspending page with unsubmitted form</p>
</li>
<li>
<p>Audio Detection (optional): prevent autosuspending tab that plays music in the background.</p>
</li>
<li>
<p>Snooze: Temporarily prevent autosuspension on a specific tab</p>
</li>
<li>
<p>Whitelist: Excludes specifics domains, pages, tabs or pinned tabs.</p>
</li>
<li>
<p>Keyboard Shortcuts: Suspend tabs without moving your hand away from your keyboard.</p>
</li>
</ul>
<p>Tiny Suspender also includes an experimental feature: suspending background tabs using <a href="https://developers.google.com/web/updates/2015/09/tab-discarding">Chrome Tab Discard API</a>. This experimental feature must be enabled from Tiny Suspender settings and can only works on background tabs, but it's very promising. It can restore the state of suspended page quite reliably, including form state and scroll position. But it does has its share of annoyance (which is why I disable it by default), such as it would reloads all suspended tabs if you ever restart your browser and restore your last browsing session.</p>
<p>My goal for Tiny Suspender is to keep it true to its name: tiny. I won't add any dependencies if I can help it to keep the code size (and extension memory footprint) minimal. But of course I'm open to suggestions. In fact, several of current Tiny Suspender's features are there thanks to users' suggestions. Shoot me an email if you have any suggestion or bug report!</p>
<p>Extension page: <a href="https://chrome.google.com/webstore/detail/tiny-suspender/bbomjaikkcabgmfaomdichgcodnaeecf">https://chrome.google.com/webstore/detail/tiny-suspender/bbomjaikkcabgmfaomdichgcodnaeecf</a></p>
<p>Repository: <a href="https://github.com/arifwn/TinySuspender">https://github.com/arifwn/TinySuspender</a></p>
    ]]></content>
  </entry>
  
  
  
  
  
  <entry>
    <title type="html"><![CDATA[Cryptography Primer]]></title>
    <link href="https://www.sainsmograf.com/blog/2013/07/15/cryptography-primer/"/>
    <updated>2013-07-15T20:37:00</updated>
    <id>https://www.sainsmograf.com/blog/2013/07/15/cryptography-primer/</id>
    <content type="html"><![CDATA[
      <p>The uproar caused by recent leak from <a href="https://en.wikipedia.org/wiki/Edward_Snowden">Edward Snowden</a> still hasn't receded yet. There are various stances about privacy and government snooping floating around in the internet. Some say they have <a href="https://twitter.com/_nothingtohide">nothing to hide</a>. Others argue if the government can snoop you, and black-hat hackers can snoop the government, then we're royally screwed because anybody with money can pay the black-hats (or, gasp!, pay some corrupt government officials) to get data about anybody.</p>
<p>Politics aside, security must be taken seriously everytime we use internet. In this post I would like to talk about the basic of security in general computing today.</p>
<ul>
<li><a href="http://xkcd.com/1269/">http://xkcd.com/1269/</a></li>
</ul>
<h2>Basic Cryptography</h2>
<p>In general, cryptography is used to transform a string of text into a convoluted gibberish that do not have any resemblance to the original text whatsoever to a person without access to its encryption key. That original string of text is called plaintext, and the resulting gibberish is called <a href="https://en.wikipedia.org/wiki/Ciphertext">cyphertext</a>.</p>
<p>Based on the keys used for the encryption, there are two type of encryption: symmetric-key and asymmetric-key encryption. </p>
<h3>Symmetric-Key Encryption</h3>
<p>In symmetric-key encryption, the key that uses to encrypt the plaintext into cyphertext can be used to reverse the operation. Decrypting the resulting cyphertext using the same key will yield the same plain text. So, if two people can share an encryption key, they can communicate securely using that key. A simple example is sharing an encrypted rar file with your partner, your partner must know your encryption key (the password) in order to decrypt the rar file. So, you can go meet your partner and tell him your password.</p>
<p>What if it's impossible for you to meet your partner physically?  Supposedly, the secrecy of the data you want to transmit is very important and the balance of the world would be disrupted if it compromised. How can you tell him your password with a strong guarantee that nobody snoop it in between the transit? Using email? Email is generally transmitted in plain text, anybody in the network between you and your partner can read it. Using google chat? Then google can read it whenever it please. Using text message? Then the cellphone operator can read it. Also, <a href="http://arstechnica.com/gadgets/2010/12/15-phone-3-minutes-all-thats-needed-to-eavesdrop-on-gsm-call/">gsm security is considered broken</a> and anyone with the right equipment can intercept your message. It's time to use an asymmetric-key encryption.</p>
<h3>Asymmetric-Key Encryption</h3>
<p>In asymmetric-key encryption, you have two keys instead of one: the private keys (which you should guard with your life) and the public key (which you should share to anyone and their pets). So, why does it require two keys?</p>
<p>Anybody who know your public key can encrypt a plaintext that only you can decrypt (using your private key). Consider our example above (in which you need to transmit a super secret data to your partner). You can encrypt the password with your partner's public key, and send him the resulting cyphertext. Using his private key, he'll decrypt the cyphertext and get the password. Then you can send him your password protected rar archive to him.</p>
<p>Wait, why use rar? Why not simply encrypt the data using the public key instead?</p>
<p>Well, actually you can use anything that properly encrypt the data. <a href="http://www.7-zip.org/">7-zip</a> support AES encryption (one of the commonly used symmetric-key encryption) too, just like rar. The reason why we didn't encrypt the whole data (presumably we have 1.3GB of it for the example) using the asymmetric-key encryption is it's really slow compared to the symmetric-key encryption. It is much more efficient (and faster) to encrypt the data using symmetric-key encryption and send the key/password through asymmetric-key encryption instead of encrypting the data wholesale using asymmetric-key encryption. Over time, the latest advances in cryptography will make the asymmetric-key encryption as fast as the symmetric-key encryption.</p>
<h2>Can We Break The Encryption?</h2>
<h3>Random Number Generator</h3>
<p>Cryptography relies heavily on random numbers. For example, you don't want your keys to be easily guessable by anyone, you want it sufficiently random that the odds of successfully guessing your key is so low nobody even try to guess it (that's why you should favor randomly generated key over simple memorable string).</p>
<p>But how do we obtain a truly random number from inside a computer? A computer by itself cannot generate a truly random number. A computer is a state machine, so in theory, if you know the machine state at the time the secret random number generated, you might be able to guess that number.</p>
<p>A simple way to generate random numbers is the <a href="https://en.wikipedia.org/wiki/Middle-square_method">Middle Square Method</a>. First, pick a starting 5-digits value as a seed, for example: 12345. Next, compute the square of it: 12345 * 12345 = 152399025. Next, pick the middle five digits from the result: 23990. That's our random number. To get the next random number, just repeat the process using the previously generated number as the new seed: 23990 * 23990 = 575520100 -&gt; 55201, and so on.</p>
<p>Notice that the value of generated random number depend on the previous number. If you know the original number that used as the seed, you can easily predict the random number generated using this method. This random number generator is called Pseudo-Random Number Generator (PRNG) because it doesn't actually generate truly random numbers. Note that the Middle Square method is very simple and not used in modern system anymore, but the concept is still the same: pseudo-random number generator depends on seed number and internal states to generate a number. If the seed and the internal states is known, then the anyone can easily predict the next random number. (in Middle Square method, there is only one internal state variable and it's always set to the previously generated number).</p>
<p>A pseudo-random number generator that can generate truly unpredictable random number is called Cryptographicaly Secure Pseudo-Random Number Generator (CSPRNG). One requirement for CSPRNG is nobody should be able to predict the next number by analyzing the previous numbers. Since we can predict the next number generated by the Middle Square method from the previous numbers, we can clearly see that the Middle Square method is not cryptographically secure and should not be used in real life applications.</p>
<p>Cryptographicaly Secure Pseudo-Random Number Generator must be fed with multiple sources of randomness to ensure its unpredictability. That source of randomness could be a network interface, human input, hard-drive needle position, ambient city noise, or even <a href="http://phys.org/news1147.html">cosmic rays</a>. The more sources of randomness available, the better.</p>
<p>Starting from the Ivy Bridge processors, Intel includes an on-chip random number generator along with a new instruction to make uses of it, <a href="http://en.wikipedia.org/wiki/RDRAND">RDRAND</a>. It can generate a random bit for each clock cycle. Modern operating systems use the instruction as additional source of randomness for their built-in random number generator.</p>
<p>There are <a href="https://news.ycombinator.com/item?id=6038473">concerns regarding the use of RDRAND in linux kernel</a>. Since RDRAND uses an on-chip random number generator, somebody at processor manufacturing plant could replace the chip with the one with faulty random number generator, which would potentially compromise security on linux system.</p>
<p>Should we worry that an exploit to random number generator could compromise our security? Probably not, but keep it in mind though.</p>
<p>Recently, <a href="http://forum.ovh.com/showthread.php?t=88277">a bitcoin exchange got hacked</a> because the attacker could take advantage of its dedicated server provider's password reset link. Apparently, the password reset link was not random enough and can be guessed by attacker.</p>
<p>Tips: if your application is running under Linux, always use /dev/urandom to get your random numbers. Many people don't like it because it's slow, but keep in mind that /dev/urandom is cryptographically secure. If you're getting the random numbers from a built-in function on your programming language/library/framework of choice, be sure to check the documentation to see if it's cryptographically secure. Not all languages/frameworks pull the random number from /dev/urandom.</p>
<p>See also:</p>
<ul>
<li><a href="http://www.slideshare.net/astamos/bh-slides">The Factoring Dead: Preparing for the Cryptopocalypse</a></li>
<li><a href="http://arstechnica.com/security/2013/08/crytpo-experts-issue-a-call-to-arms-to-avert-the-cryptopocalypse/">Crypto experts issue a call to arms to avert the cryptopocalypse</a></li>
<li><a href="http://valerieaurora.org/monkey.html">The code monkey's guide to cryptographic hashes for content-based addressing</a></li>
<li><a href="http://www.moserware.com/2009/09/stick-figure-guide-to-advanced.html">A Stick Figure Guide to the Advanced Encryption Standard (AES)</a></li>
<li><a href="http://www.random.org/">random.org</a></li>
<li><a href="https://www.schneier.com/blog/archives/2008/05/random_number_b.html">Random Number Bug in Debian Linux</a></li>
<li><a href="http://www.change.org/en-GB/petitions/linus-torvalds-remove-rdrand-from-dev-random-4/responses/9066">Petition to Linus Torvalds: Remove RdRand from /dev/random</a>, <a href="https://news.ycombinator.com/item?id=6359892">discussion</a></li>
<li><a href="http://blog.cloudflare.com/why-randomness-matters">Why secure systems require random numbers</a></li>
<li><a href="http://www.matasano.com/articles/javascript-cryptography/">Javascript Cryptography Considered Harmful</a></li>
</ul>
<h3>Quantum Computing</h3>
<p><a href="http://www.mat.ucm.es/catedramdeguzman/old/01historias/haciaelfuturo/Burgos090900/quantumcomputingSciAmer/0698gershenfeld.html">Quantum computing</a> has gain a lot of buzz recently, especially those <a href="http://en.wikipedia.org/wiki/D-Wave_Systems">D-Wave</a> stuff. But what is quantum computing and what is the implication for our daily (internet) life?</p>
<h4>Quantum Superposition</h4>
<p>Remember Schrödinger cat? It's often used to illustrate quantum superposition. The cat is in the box, with poison and radioactive trigger that have 50/50 chance of releasing the poison to the poor cat. In the end, is the cat alive or dead? Not that simple. The poor cat is in a superposition of state and both alive and dead. The moment we take a peek to see how the poor cat's doing, the quantum superposition collapsed and the cat falls into one of the two possible state: alive or dead.</p>
<p>That cat analogy doesn't make any sense, right? How could the cat both alive and dead at the same time before we take a look at it? But it highlights an important feature of quantum superposition: the quantum superposition state collapse into in one of the possible states the moment we measure it.</p>
<h4>Qubit</h4>
<p>Ok, the quantum superposition is neat because it can represent multiple states simultaneously. But what's that got to do with quantum computing?</p>
<p>The building block of traditional computing, as we all know very well, is <em>bit</em>. A bit can represent two states: either 1 or 0. In quantum computing, the building block is <em>qubit</em> (quantum bit). Because qubit has quantum superposition property, it can be in multiple states at the same time; it can contain both 1 and 0 until the moment you try to measure it, at which point it would collapse into either 1 or 0. This is indeed truly mind blowing.</p>
<p>Each qubit can have both 0 and 1 simultaneously, and each state has its own probability coefficient. To describe a qubit, we would need two numbers to store probability coefficients for 0 and 1. To describe two qubits, we would need 4 numbers, and so on in n^2 relation. This illustrates the strength of quantum computer: we would need a traditional computer capable to store 2^100 numbers to represent a 100 qubits quantum computer. That means we need millions of <a href="http://en.wikipedia.org/wiki/Yotta-">yottabyte</a> just to represent a mere 100 qubits quantum computer!</p>
<h4>Quantum Teleportation</h4>
<p>Another bizzare phenomenon is quantum teleportation. After a pair of particles interact with each other and separated, if one particle has its state changed, the other would have its state changed too, no matter what distance they are separated. It is as if the particles can sense what happen to its pal and react accordingly, just like in horror movies.</p>
<p>Again, what's that got to do with quantum computing?</p>
<p>In 1994, a researcher from AT&amp;T, Peter W. Shor found a way to use quantum teleportation to find prime factors of an integer. It turns out to be much faster than any traditional computer can compute. It is now known as <a href="http://en.wikipedia.org/wiki/Shor's_algorithm">Shor's Algorithm</a>.</p>
<p>In asymmetric-key encryption, the public and private keys must be somehow related for the encryption algorithm to work. Therefore, the private keys can be recovered with some forms of factorization from the public key, except doing so is computationally hard, and even virtually impossible (takes too much time, like <em>billions</em> of years) if the key is sufficiently long.</p>
<p>With a sufficiently big quantum computer, factoring private key from public key is feasible using Shor's algorithm. The task that could takes billions of years now can be accomplished in a couple years, for instance. That's why <a href="http://pqcrypto.org/">cryptography researchers now scramble to produce new cryptography algorithms and methods</a> in the event that quantum computer is finally big enough to pose a threat for cryptography world. </p>
<h2>Forward Secrecy</h2>
<p>Later</p>
<h2>Securing Email</h2>
<p>There is no doubt that email plays an important role in our internet life. We can't even register for a new account on many website without email! But how does email really work actually?</p>
<h3>Simple Mail Transfer Protocol</h3>
<p>The SMTP (Simple Mail Transfer Protocol) is used by email servers to exchange emails to each other. In fact, OSX and most linux distributions ship with <code>sendmail</code>, an email transport agent. If you're on a Mac or Linux, open a terminal and type the following code to send yourself an email (replace my email address with yours):</p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="c1"># Sending an Email From Command Line Interface Using Unix Sendmail</span>
sendmail<span class="w"> </span>arif@sainsmograf.com<span class="w"> </span><span class="s">&lt;&lt; EOF</span>
<span class="s">Hello, just a test email from command line!</span>
<span class="s">EOF</span>
</code></pre></div></td></tr></table></div>

<p>Soon, you'll receive an email from <code>&lt;username&gt;@&lt;hostname&gt;</code> (example: arif@arifs-macbook-pro.local). If the command run successfully but you never receive any email, chance that:</p>
<ul>
<li>Your ISP block communication to port 25 to stop <a href="https://en.wikipedia.org/wiki/Spambot">spambots</a></li>
<li>Your email provider (gmail, yahoo, etc) ban your ip range (possibly due to spambots, damn spambots!)</li>
</ul>
<p>If you did receive the email, you might not be able to reply to it unless you have configured your hostname properly.</p>
<p>In the above example, my computer act as an email server and communicate directly to sainsmograf.com's mail server. Note the <em>email server</em> part. If you're using Outlook or Thunderbird to connect to smtp server, your computer act as a <em>user</em> of that server. Here, <code>sendmail</code> act as an email server delivering email from its user (me) to another email server (sainsmograf.com).</p>
<h3>Can Somebody Snoop My Email?</h3>
<p>By default, <code>sendmail</code> uses unencrypted protocol. The email sent using the <code>sendmail</code> command in the previous section is not encrypted, and anybody between you and your destination server can easily read your email. The good news is, sendmail does support SSL and can encrypt your email messages during transmission. However, sendmail's SSL encryption won't protect your email if the recipient access his mailbox via unencrypted connection (for example, plain old POP3 without SSL).</p>
<p>You may need to encrypt your email message yourself to guarantee that nobody snoop your email, but how?</p>
<h3>Pretty Good Privacy (PGP)</h3>
<p>A popular way to encrypt your email messages is using PGP. A widely used implementation of PGP is GNU Privacy Guard (GnuPG, or GPG). <a href="http://www.wired.com/threatlevel/2013/06/signed-bda0df3c/">If somebody asks you to use PGP/GPG</a>, don't be confused. What he means is you should use GnuPG to exchange PGP-encrypted message with him.</p>
<p>After getting GPG installed (<a href="https://gpgtools.org/">OSX</a>, <a href="https://help.ubuntu.com/community/GnuPrivacyGuardHowto">Linux</a>, <a href="http://gpg4win.org/">Windows</a>), lets use it to encrypt our email!</p>
<h4>Generate Private/Public Keys Pair</h4>
<p>PGP uses asymmetric encryption (discussed above), so the first logical step to encrypt your email is generating your public and private keys. Run the following command from your terminal to generate your keys pair:</p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="c1"># Generate Private/Public Keys Pair</span>
gpg<span class="w"> </span>--gen-key
</code></pre></div></td></tr></table></div>

<p>You'll see the following output:</p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div><pre><span></span><code>gpg (GnuPG) 1.4.13; Copyright (C) 2012 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection?
</code></pre></div></td></tr></table></div>

<p>Select the default by entering <code>1</code>. You'll be prompted another questions. Just answer them accordingly. Eventually, GPG will ask you to create a passphrase:</p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span></pre></div></td><td class="code"><div><pre><span></span><code>gpg (GnuPG) 1.4.13; Copyright (C) 2012 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
      &lt;n&gt;  = key expires in n days
      &lt;n&gt;w = key expires in n weeks
      &lt;n&gt;m = key expires in n months
      &lt;n&gt;y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
    &quot;Heinrich Heine (Der Dichter) &lt;heinrichh@duesseldorf.de&gt;&quot;

Real name: Arif Widi Nugroho
Email address: arif@sainsmograf.com
Comment:
You selected this USER-ID:
    &quot;Arif Widi Nugroho &lt;arif@sainsmograf.com&gt;&quot;

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
You need a Passphrase to protect your secret key.
</code></pre></div></td></tr></table></div>

<p>Now, enter a long passphrass, but don't forget it! If you forgot your passphrase, there is no way to recover it and you can never decrypt all messages that has been encrypted with your pulic key. Consider using a good password manager to store your complicated passphrase.</p>
<p>Now that you have your own private and public keys, you should share your public key to everyone! To print your public key, use this command (replace my email address with yours):</p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="c1"># Print PGP Public Key</span>
gpg<span class="w"> </span>-a<span class="w"> </span>--export<span class="w"> </span>arif@sainsmograf.com
</code></pre></div></td></tr></table></div>

<p>And the result:</p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span>
<span class="normal">52</span></pre></div></td><td class="code"><div><pre><span></span><code>-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.13 (Darwin)

mQINBFHw6YUBEAC0hmxW63ESb+YwatEVTeSOTkHjYp7G2S2gjmItVOuZ+N8us59N
uMH1M1g71GNcztYIXzQIoKITiLxLfP0+mPf0j2vzuoYY9AAsQgsr0fYPTDvJUz2c
xseZ0BROm2wfGF3U54bGroQOCqXMQXV/5ln45ie/NqzZRWmF4xpKJ4dPN1GXFphz
SKw5uQkFC5JcmoPCzU7xsEdLspSNhL98a1rvLD0QVXMxVGM/NSkhJYaYidChdsiM
UMQ9AWge6PSDE/A9ZnZC+BvInYzJ3MoYHOcZxGk1fttUY1JKQvLCodSuCt9MKD+7
gnXOea4a2VaEQE3rfsa9CuGVz/r1o54hOnYMzNex3z3VaZX1hAV6pmwfl/CKVggY
R401xJDYAUjmWGSeheqfon9rdw9hDitleaekq0j0wfpJ+EoMEohVsDKrf8TvcRrO
IYt1CAjjI/cqbuIm3bfr8T6wT59H879ss3v0ibNmD4mf9/+IR23Xj/g1nA6aMjX3
62psBNOvFB6pP59GMtDD93Zze6FMBzPRGqsB0YR6Gp3gkdpFBFHgj3vwaYC+bWJ8
LmYJrPTivVEAWZ4I2tRyrkdJzIiRlNnAXCmJTcaMhkASfnjgNJWloGDk/o1SqOhe
F9w2M9iGY/xdz5j1gRkdDSvPr7AGC5r4Vb26ZNdszZ7ZRF5gekF5k21dZQARAQAB
tChBcmlmIFdpZGkgTnVncm9obyA8YXJpZkBzYWluc21vZ3JhZi5jb20+iQI4BBMB
AgAiBQJR8OmFAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRBmmK8D5X4F
BzsyD/9NbYNxz93oW1ujMY3z/er6zhohQqOE5Wl8H4lEz5X/l/8iACM/n5n9RNEF
eAeXbQQFk5+szaE4njK5gGVVUN+WGQ1zH1Hd0NY/6/d/N1vhQiYYg4VeeGvcFBAS
+CuNs4YOa7nM4YUrSKXGQ8pARakICmw03LYhbhCgcIGuRInoLoWnGCqi+OOjBcli
MAEG/7Rb2aNWyjKw/Oyj4X7y3O0MP5nv0a9MHPum5HEbiW6O7ElM6UWHP3pO7rpW
i301yoo8nej1IClmpF+ufH/+vveyG6UNpnzTGj3h+G8t6P6bPeq4vMKIxrskcxGt
HhJfk1EQdHUfZMDYTSHjanCbyMYSo5fbjVVCnJrqO4nHUp9ngbMZMBgi2uROFG8H
3/dKt7cQdd0VFvmUntS2A93M0G7mwwYV2O37jOkVTi1F5Br9anLcnb3FE5CXfqxr
8Fd77Pjhv/sGOIAkxqdldc+grL5OJp76DChWS41cMaZ46BUfN3JgDh8rSqA/A5v+
RkIKpSWYPx6K4EOfGfnr6WnL1oJdcLjIgSab093+7qDYWv2/3B2BsoOTOX5MuZZi
ELcniDJFYSW8aW6TbiKP1x8BkXPynxh9fErz27ciLPx2xtzQEEbiMXjAhvyuRH2o
AJJ2ogzGtOlPwZBvLRDIHDznvxaMx8agp5uyX1+j0SFgpuguHbkCDQRR8OmFARAA
18sCfZrkTLJs2wYgDkVU49pnlKcpZXl4yyoKKZ/AuHBkd1tFQGwCDMFefpxeECKC
6aonQoGrVNIOvR4n2bBdePEvkmQ1Y5xVvfOoPWTdgg6rUqpdpU/vV5b5BNrU63n+
CRdODLdMg67Av7diZlp15PcjiKkkyQ2VTfTgDgWiSyYnKyvZoNnI4mMopEtl3tjh
Vze4TuGI/7UJdh06Gh8AW2WB0wJjr6d0zFsKjQWE5pJELxVBy+E3IO2KpIjLZp2P
N7AWZOpw4CbjFV9pQMaGe6bDPPtnk9D95WQt1AzWkuOA+kMuwlyc5zTutxatDXqt
yfILGESi+l4VkGVJq3wnVDPkjCXsIPk7OJ83GCh28PfPz+o7DM2gNQ0bsP/A2d1w
9Lwhsb1tTjWtVGxP38a/lbTRfbHx+Zy7ZX4INS7R2rbQZmW4Lv59Y6FSFRE3zlII
lOEGW2Wm19S7ORl3ISLRENqYI9b/J/wA0AT1I1vOzTjsHXzZPAs2poHkb7XU8KEX
Rzn0PKpRj4lvxZWpMMNpU17JIwrymb3z64WZBjU1R7hErneSDuVsQj9aT590MVNV
Jupggd/Brs+xeivV6T7wRaMYQWI5TAUenjmy5Q4LxhiLQySpxGvuvx/bxaS1zg3E
nKyvtJzKcWOLzT0V7gLFRKoQ9jIwkl+hpJNVnpTEncsAEQEAAYkCHwQYAQIACQUC
UfDphQIbDAAKCRBmmK8D5X4FB5eiD/4w60Ag7zkZQbnfPyKuxZrejYl2YiLuHlTT
1UdsP6BsyQ4iysOEloW0Vq06tjKj5ahIvRUo5UF2h4ehOnUNbXTFgPegiCEaG0m9
hEvIE9ZWsJqkgUfC5Inq+066AQMJa0PeA8kaSxc5FriMiq7UWuT4ungN8KlqKhaS
Vw5LM5kHEfn0WzHbnvPcq39eAUjkEbVjbN1V5LfDOrV3HM8VKe4OWvSpD1h5tawW
mfUc3jND2RfkiH/r8dY0j5SjggdXAqK14DJL339+Y/r0SpclP7owwBo4xpNabqkF
8D+nwA4hIhgw0XV2BE2MbCe0QIij2S+08/YAoW8X0FKxsQY8UbHHKsIZdFh2jr3Z
SQekkpZqHKUC9CzmBEb5gg434A4NTUdeg9EURg1tBulED66q8NxPQgUU5Qu0ggSZ
hqhth5Cr5WQKxrGJ2x3+0MEmJbL2TKutBSk0qU9gau5sKesCRK8/l6Uxax8NDPZd
O/sirv7X3uL0FN6jnxSMrA/Qj9Vn5QkV+BFdMdOQ0xDdWrZZRoWgWoiNFRVraILM
FXSLslU/Zns4Qu1oEhpvzzT5wW5xkbPhaY+XuQ4Qfl+y/mcHCdQFPfwh+Y81n/Di
uMvB7IUohi8q5z0XUqoyMkP1MccMq4qzoMcSJzHAx3Nju/aBNzS03CTFXDVYIO0g
TN4ixRhleA==
=dEg9
-----END PGP PUBLIC KEY BLOCK-----
</code></pre></div></td></tr></table></div>

<p>There, you have my public key. Save that key into a file called <code>public.key</code> and import that public key using the following command:</p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="c1"># Importing a Public Key</span>
gpg<span class="w"> </span>--import<span class="w"> </span>public.key
</code></pre></div></td></tr></table></div>

<p>Now it's time to send myself a secret email! To encrypt a message, first, save the message inside a file called <code>plain.txt</code>. Encrypt the file using the following command: </p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="c1"># Encrypt a Message</span>
gpg<span class="w"> </span>-a<span class="w"> </span>-e<span class="w"> </span>-u<span class="w"> </span>sender@example.com<span class="w"> </span>-r<span class="w"> </span>recipient@example.com<span class="w"> </span>plain.txt
</code></pre></div></td></tr></table></div>

<p>Replace <code>sender@example.com</code> with your email message and <code>recipient@example.com</code> with your recipient. Make sure to import your recipient's public key first!</p>
<p>The encrypted message would be stored inside <code>plain.txt.asc</code> file:</p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span></pre></div></td><td class="code"><div><pre><span></span><code># Encrypted Message

-----BEGIN PGP MESSAGE-----
Version: GnuPG v1.4.13 (Darwin)

hQIMA1wNV+AyV/2aAQ/8Dzd4h2MnY/ZNH2HO4aUUTGbgZfLWrWg1VJOKeldXw5GY
5FkAuywDfCMha9/GH3UHh9vLYjmCHsjf4BeMgA5Z5Z3Hzwp/+kI0Nv+N07L5+UVG
qIdXKjKuc/lBgB5NOrz8Q+7SSBbvQgKgywravwDxtzt/lhCI0J5SjUo9X8ehuH4q
qDB+yZtrGYKdw1Ww4JIgRhV+Lsbjt2jhB2s62RirotyX6sKKVn0EfATcdNKBOuWW
F6pLP7h0AqW0PCq3HGG8hnGeIu7Kef5xCIuJQCb7rgs0TP09NAP5fugMK5I74S2P
DYrQh66mGDrelud3jFq1vKguqOOSrEw5SEnRSG3TeUbjHPxMenvVYkxwhL7p0sK0
1il3s7PMrDuqFEu7SrTRUDUTgbJtrV0hgJKWi0x/6SFKOzodvW8ka5MzIpqKj3KC
jf48s4xfd67uofol79cUuVr4zwWbe6RpDEmRt1JS3hxXTWa0dQN2WNCic0OFRXHt
UQGKJoV2I1U2nEc2DjZNca4f9zuPvjyxCT8gp11E6HJ31WRbln5qixF7W3RA148x
3SC7ThZp687bMGxUTUQimpy4FkrWtvQzYfoILAlJbmFiOUB1ww6q8fWMf3mV4e1n
h1K2bpb4Syu2eeflgUxNdeLfjBmNJgMIGgsHMRspTAVqHo+KJzb1JanvuyVPCcPS
XAGb2WhILc/NRNKodV8LZsqBK6nxCCQM+3mooLUl5KoccG5VVealdf5epN7sbnjg
QlH+2rQjLwGGZH76bDBNhblC2M8tAUxU3BNUd/ax9EspN16IpHgWXNGNvUyh
=rJyP
-----END PGP MESSAGE-----
</code></pre></div></td></tr></table></div>

<p>Now send that file via email to your recipient. Here is how to send the encrypted message using <code>sendmail</code>:</p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="c1"># Send The Encrypted Message Using Sendmail</span>
cat<span class="w"> </span>plain.txt.asc<span class="w"> </span><span class="p">|</span><span class="w"> </span>sendmail<span class="w"> </span>arif@sainsmograf.com
</code></pre></div></td></tr></table></div>

<p><img alt="An Encrypted Email!" src="https://lh6.googleusercontent.com/-OX554vlxHAA/UfD3nvJBfSI/AAAAAAAAACw/nRf9kju8m8c/d/Screen+Shot+2013-07-25+at+5.01.40+PM.png" title="An Encrypted Email!" /></p>
<p>To decrypt the message, save the message content into a file called <code>cipher.txt</code> and run:</p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="c1"># Decrypting a PGP Message</span>
gpg<span class="w"> </span>-d<span class="w"> </span>cipher.txt
</code></pre></div></td></tr></table></div>

<p>It would print out the decrypted message:</p>
<div class="codehilite"><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><code>gpg: encrypted with 4096-bit RSA key, ID 3257FD9A, created 2013-07-25
      &quot;Arif Widi Nugroho &lt;arif@sainsmograf.com&gt;&quot;
This is a secret email!
</code></pre></div></td></tr></table></div>

<p>You can encrypt binary data too, or use it to encrypt your off-site backup data. Check the man page (<code>man gpg</code>) or consult the following resource:</p>
<ul>
<li><a href="http://irtfweb.ifa.hawaii.edu/~lockhart/gpg/">GPG Cheat Sheet</a></li>
<li><a href="http://www.robertsosinski.com/2008/02/18/working-with-pgp-and-mac-os-x/">Working with PGP and Mac OS X</a></li>
</ul>
<p>That's just an overview of how PGP works. If you use an email client or install an email client plugin that support PGP, after creating your public/private keys pair, the process is mostly automatic. No need to go back and forth to the command line interface!</p>
<p><img alt="Sending An Encrypted Email With OSX Mail App + GPGTools" src="https://lh4.googleusercontent.com/-50Khh48XTNY/UfU1QpkjNWI/AAAAAAAAAD4/Ej3sEP0yAsI/w652-h418-no/OSX+Mail+App+%252B+GPGTools.png" title="Sending An Encrypted Email With OSX Mail App + GPGTools" /></p>
<h3>S/MIME (Secure/Multipurpose Internet Mail Extensions)</h3>
<p>Almost the same with PGP, except you don't generate your public/private keys pair yourself. Instead, you obtain them in the form of digital certificate from a certificate authority.</p>
<p>When you send an email signed with S/MIME, your recipient will automatically get your public key. Also, if you obtain your certificate from trusted authority, such as VeriSign, your recipient's email client will automatically validate your message with no manual process involve. Also, unlike PGP, most email clients support S/MIME.</p>
<p>Simply obtain a certificate from a trusted certificate authority, install it, and ready to go! The drawback is you need to pay to get a certificate. <a href="http://www.symantec.com/verisign/digital-id?tid=gnps">You can get a certificate with one year validity from VeriSign here (about $20)</a>.</p>
<ul>
<li><a href="http://arstechnica.com/apple/2011/10/secure-your-e-mail-under-mac-os-x-and-ios-5-with-smime/">S/MIME Guide</a></li>
<li><a href="http://www.comodo.com/home/email-security/free-email-certificate.php">Free S/MIME Certificate - not trusted by many email clients</a></li>
</ul>
<p>Next:</p>
<h2>Verifying Website Security</h2>
<p>Is the website you visit frequently actually secure? Are you sure the website you visit is actually the real website, not some hacker rig impersonating the real website?</p>
<ul>
<li><a href="https://www.eff.org/pages/tor-and-https">EFF has a nice diagram about connection privacy</a>. Lets discuss it!</li>
<li>Anything without HTTPS is insecure. Don't submit important information over plain http!</li>
</ul>
<h2>How SSL (HTTPS) Works</h2>
<ul>
<li>Initial handshake uses asymmetric encryption to exchange symmetric keys. Therefore HTTPS requires two roundtrip to server. SPDY protocol solve this (but chrome-only).</li>
<li>Validation: The connection might be encrypted, but how can you be sure that the guys on the other side of the cable are not an imposter? Someone I trusted should confirm that I'm indeed not talking to a fake imposter.</li>
<li><a href="https://community.qualys.com/blogs/securitylabs/2013/06/25/ssl-labs-deploying-forward-secrecy">Forward Secrecy</a></li>
</ul>
<h2>Deep Net</h2>
<ul>
<li>We need to go <a href="https://www.torproject.org/">deeper</a>.</li>
</ul>
    ]]></content>
  </entry>
  
  
  
  <entry>
    <title type="html"><![CDATA[Cryptography Primer]]></title>
    <link href="https://www.sainsmograf.com/blog/2013/07/15/hello-world/"/>
    <updated>2013-07-15T19:46:00</updated>
    <id>https://www.sainsmograf.com/blog/2013/07/15/hello-world/</id>
    <content type="html"><![CDATA[
      <p>First Post!</p>
    ]]></content>
  </entry>
  
  

</feed>