<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: José Miguel Moreno</title>
    <description>The latest articles on DEV Community by José Miguel Moreno (@josemmo).</description>
    <link>https://dev.to/josemmo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F176887%2Ffe368ad1-f482-4ab4-864f-6cc7dd9fc7a2.png</url>
      <title>DEV Community: José Miguel Moreno</title>
      <link>https://dev.to/josemmo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/josemmo"/>
    <language>en</language>
    <item>
      <title>How To Disable Bluetooth on Android TV</title>
      <dc:creator>José Miguel Moreno</dc:creator>
      <pubDate>Sun, 28 Jan 2024 10:04:53 +0000</pubDate>
      <link>https://dev.to/josemmo/how-to-disable-bluetooth-on-android-tv-1k6m</link>
      <guid>https://dev.to/josemmo/how-to-disable-bluetooth-on-android-tv-1k6m</guid>
      <description>&lt;p&gt;Modern (and not-so-modern) Android TVs often come with built-in Bluetooth for connecting other smart devices, such as voice-enabled remotes. This is nice.&lt;/p&gt;

&lt;p&gt;However, for reasons beyond my understanding, Google and most TV manufacturers decided to leave Bluetooth discoverability always enabled on the device with &lt;strong&gt;no option to turn it off&lt;/strong&gt;, resulting in annoying neighbors spamming consent pairing dialogs on the TV whenever they want. This is not nice.&lt;/p&gt;

&lt;p&gt;The sensible solution would be for manufacturers to add an option to disable Bluetooth in the TV settings, but unfortunately that's not how modern software development works.&lt;/p&gt;

&lt;p&gt;Since this is not an isolated problem, other people have come up with alternative solutions that involve installing an app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/AndroidTV/comments/6dwczn/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/AndroidTV/comments/6dwczn/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/AndroidTV/comments/tdfh0e/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/AndroidTV/comments/tdfh0e/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://forum.lowyat.net/topic/5196128" rel="noopener noreferrer"&gt;https://forum.lowyat.net/topic/5196128&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, my Android TV does not support that app (thanks, market fragmentation!), so here's my solution to disable Bluetooth:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enable USB Debugging on your TV &lt;a href="https://developer.android.com/studio/debug/dev-options" rel="noopener noreferrer"&gt;just like any other Android device&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Connect to the TV through the network: &lt;code&gt;adb connect &amp;lt;tv-ip-address&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;adb shell svc bluetooth disable&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  2025 Update
&lt;/h2&gt;

&lt;p&gt;I came across another &lt;a href="https://www.reddit.com/r/AndroidTV/comments/10mj162/comment/j647qh3/" rel="noopener noreferrer"&gt;Reddit comment&lt;/a&gt; that suggests turning off Bluetooth altogether:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adb shell cmd package disable-user com.android.bluetooth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Strange as it may sound, it actually works.&lt;/p&gt;

</description>
      <category>android</category>
    </item>
    <item>
      <title>CrowdNotifier explained: tracing COVID-19 contacts with privacy in mind</title>
      <dc:creator>José Miguel Moreno</dc:creator>
      <pubDate>Sun, 21 Feb 2021 13:19:13 +0000</pubDate>
      <link>https://dev.to/josemmo/crowdnotifier-explained-tracing-covid-19-contacts-with-privacy-in-mind-14j7</link>
      <guid>https://dev.to/josemmo/crowdnotifier-explained-tracing-covid-19-contacts-with-privacy-in-mind-14j7</guid>
      <description>&lt;p&gt;CrowdNotifier is a secure, decentralized system for notifiying individuals that have been in contact with SARS-CoV-2-positive people in public locations, such as bars, restaurants, venues and other places that can be considered potential sources of contagion.&lt;/p&gt;

&lt;p&gt;This article aims to demistify this technology and explain &lt;strong&gt;how it works&lt;/strong&gt; and &lt;strong&gt;how does it preserve the privacy&lt;/strong&gt; of its users.&lt;/p&gt;

&lt;h1&gt;
  
  
  Overview
&lt;/h1&gt;

&lt;p&gt;In summary, the CrowdNotifier presence-tracing system involves three parties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Visitors&lt;/strong&gt; 🧑: individuals that visit a location at a given point in time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Locations&lt;/strong&gt; 📍: the places visitors stop by.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Health Authority&lt;/strong&gt; 🚑: typically, a single governmental agency that will be responsible for determining whether a person has the COVID-19 disease.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When visitors come into a location, they use an app implementing the CrowdNotifier system to &lt;strong&gt;scan a QR code&lt;/strong&gt; provided by the location owner. When they leave, they &lt;strong&gt;check out tapping a notification&lt;/strong&gt; left by the app on their phone.&lt;/p&gt;

&lt;p&gt;Location owners can generate these QR codes using a web application.&lt;/p&gt;

&lt;p&gt;If the Health Authority concludes the location has been visited by an infected person at a given point in time, other visitors who were there during the same overlapping timespan &lt;strong&gt;will be notified through the app&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The security, trust and privacy of the system rely on &lt;a href="https://en.wikipedia.org/wiki/Symmetric-key_algorithm"&gt;symmetric&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Public-key_cryptography"&gt;asymmetric&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Identity-based_encryption"&gt;IBE&lt;/a&gt; cryptography.&lt;/p&gt;

&lt;p&gt;Now let's see how this process actually works!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;IMPORTANT! This article oversimplifies IBE by omitting some encryption/decryption and key derivation aspects to make it easier to understand. Cryptographers be warned.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Step 1: QR codes generation
&lt;/h1&gt;

&lt;p&gt;Location owners need to generate two different QR codes: one for the entry (which is public) and another for the trace (which is private).&lt;/p&gt;

&lt;p&gt;The entry code is placed at the entrance (or entrances) of the location and is the one scanned by visitors when they come in.&lt;/p&gt;

&lt;p&gt;Both codes are generated &lt;strong&gt;offline&lt;/strong&gt; (this means on the client side, without any party except the location owner knowing any secret key-generation material).&lt;/p&gt;

&lt;p&gt;The generation process is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Generate two sets of IBE master keys (one for the Location and another for the Health Authority). These sets are made of a &lt;strong&gt;Master Public Key&lt;/strong&gt; (MPK) which is known and a &lt;strong&gt;Master Secret Key&lt;/strong&gt; (MSK) that needs to remaing private.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;(mpkL, mskL)(mpkHA, mskHA)
(mpk_L,\, msk_L) \newline
(mpk_{HA},\, msk_{HA})
&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathdefault"&gt;m&lt;/span&gt;&lt;span class="mord mathdefault"&gt;p&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathdefault"&gt;k&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;L&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathdefault"&gt;m&lt;/span&gt;&lt;span class="mord mathdefault"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathdefault"&gt;k&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;L&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace newline"&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathdefault"&gt;m&lt;/span&gt;&lt;span class="mord mathdefault"&gt;p&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathdefault"&gt;k&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;H&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathdefault"&gt;m&lt;/span&gt;&lt;span class="mord mathdefault"&gt;s&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathdefault"&gt;k&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathdefault mtight"&gt;H&lt;/span&gt;&lt;span class="mord mathdefault mtight"&gt;A&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;MPKs are used to encrypt messages and MSKs can &lt;strong&gt;derive decryption keys&lt;/strong&gt;. If you know the Master Secret Key, then you can decrypt any message (this is partly true, but for the moment just roll with it).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Generate the entry QR code. This one contains some public information about the location (i.e. name), both Master Public Keys and a random symmetric key (notifyKey) which is generated on-the-fly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qGHEdIjt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/65n38v2uddwqmrxp7x3e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qGHEdIjt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/65n38v2uddwqmrxp7x3e.png" alt="Entry QR code"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Generate the trace QR code. It must be kept secret for now as it contains both Master &lt;u&gt;Secret&lt;/u&gt; Keys.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RwCZwJKH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ru9xe064m091i54t7f6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RwCZwJKH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ru9xe064m091i54t7f6.png" alt="Trace QR code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One important detail is the Health Authority's MSK is encrypted using public key cryptography with the HA's asymmetric public key, thus ensuring &lt;strong&gt;only the HA can decrypt it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As you may have already guessed, we need to know the HA's public key in advance (pkHA).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Step 2: Record visited locations
&lt;/h1&gt;

&lt;p&gt;This is the part when it starts to get interesting!&lt;/p&gt;

&lt;p&gt;The history of visited locations is stored &lt;strong&gt;only&lt;/strong&gt; on the phone of its corresponding visitor and it keeps track of the past 10 days.&lt;/p&gt;

&lt;p&gt;Even if the visitor's phone gets hacked no one can know were he/she has been as this information is both hashed and encrypted 🤯. The most an attacker can do is know someone has been in contact with a SARS-CoV-2-positive.&lt;/p&gt;

&lt;p&gt;When visitors enter a location they scan the entry QR code to get all the data it contains, and when they leave, the phone app stores a record &lt;strong&gt;for each hour interval&lt;/strong&gt; they have been at the place.&lt;/p&gt;

&lt;p&gt;For example, if a visitor enters at 6:36 pm and leaves at 8:01 pm, inmediately after tapping the "leave" button on their phone, the CrowdNotifier app will generate three messages (6pm, 7pm and 8pm) containing the same information &lt;strong&gt;but encrypted with a different key&lt;/strong&gt; for each hour.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u3swLGqA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vcj7d9ze5anuagq3axld.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u3swLGqA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vcj7d9ze5anuagq3axld.png" alt="Entering/leaving a location"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see in the figure above, to generate a record we follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Generate an ID needed for the IBE encryption process. This ID is the result of hashing the location info with the UNIX timestamp of the given hour.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;"Derive" IBE encryption keys using mpkL, mpkHA and the previous ID (not exactly what happens, but close enough).&lt;/p&gt;

&lt;p&gt;These Partial Secret Keys (PSK) are what CrowdNotifier calls  "pre-tracing keys".&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a message consisting of the arrival and departure times and the location's notifyKey. Then encrypt it with the material we obtained in the previous step.&lt;/p&gt;

&lt;p&gt;One awesome thing about IBE cryptography is that mhour can only be decrypted if you have the generated ID and &lt;strong&gt;both mskL and mskHA&lt;/strong&gt;, so cooperation between the location owner an the Health Authority is required.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember! Master Public Keys are used to encrypt and Master &lt;u&gt;Secret&lt;/u&gt; Keys to decrypt.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Store the encrypted message in the visitor's phone.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Step 3: Notifying positives
&lt;/h1&gt;

&lt;p&gt;When the Health Autority detects an infected person, it requests the Location owner the notifyKey, encrypted mskHA and the location PSKs for a given time interval, tipically from the arrival to the departure of the COVID-19 subject.&lt;/p&gt;

&lt;p&gt;To obtain the requested information, the Location owner scans the trace QR code that has been kept private until this very moment and derives all location PSKs for the appropiate time interval using their MSK (mskL).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lo3mZCYb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tvgkl73qybtao205h6e8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lo3mZCYb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tvgkl73qybtao205h6e8.png" alt="Location owners sends data to Health Authority"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Health Authority receives this information and verifies it. If it passes verification, a set of notification messages are generated and &lt;strong&gt;published to a public server&lt;/strong&gt; (in most cases managed by the HA) where visitors' apps periodically connect to in order to check whether they have been in contact with an infected person.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HNbFKuxP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uroliqhf70lgdtebyelz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HNbFKuxP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uroliqhf70lgdtebyelz.png" alt="Health Authority upload process"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These notification messages contain both Partial &lt;u&gt;Secret&lt;/u&gt; Keys as the two are needed to decrypt the messages stored in the visitors' phones.&lt;/p&gt;

&lt;p&gt;Also, the &lt;strong&gt;notifyKey is not sent&lt;/strong&gt; but instead is used to encrypt a random plaintext that is added to the notification.&lt;/p&gt;

&lt;h1&gt;
  
  
  Step 4: Alerting visitors
&lt;/h1&gt;

&lt;p&gt;This is the last step of the CrowdNotifier workflow.&lt;/p&gt;

&lt;p&gt;After notification messages have been published to the public server, the smartphone app &lt;strong&gt;downloads them&lt;/strong&gt; to check if the visitor has been in the same location at an overlapping time with a positive contact.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vsU16bkR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4724k30q3r1t104x4nvd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vsU16bkR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4724k30q3r1t104x4nvd.png" alt="Verification process on visitor's phone"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For every notification, the app extracts the PSKs and tries to decrypt every message stored in device that was previously recorded in Step 2.&lt;/p&gt;

&lt;p&gt;If the time intervals overlap and the random value from the notification can be decrypted using the notifyKey obtained after decrypting the message, then an alert is shown to the user (visitor).&lt;/p&gt;

&lt;p&gt;If the app cannot decrypt any stored message with any of the PSKs provided in the notification messages, then everything is fine: the user has not been in contact with an infected person.&lt;/p&gt;




&lt;p&gt;And that's basically how CrowdNotifier works!&lt;/p&gt;

&lt;p&gt;If you want to learn more or dig deeper into the cryptography behind this technology, check out the &lt;a href="https://github.com/CrowdNotifier/documents"&gt;White Paper&lt;/a&gt; from their official Github repository.&lt;/p&gt;

</description>
      <category>security</category>
      <category>privacy</category>
      <category>cryptography</category>
      <category>covid19</category>
    </item>
    <item>
      <title>Technical Analysis of All European Contact Tracing Apps (COVID-19)</title>
      <dc:creator>José Miguel Moreno</dc:creator>
      <pubDate>Sat, 07 Nov 2020 12:30:52 +0000</pubDate>
      <link>https://dev.to/josemmo/technical-analysis-of-all-european-contact-tracing-apps-covid-19-1558</link>
      <guid>https://dev.to/josemmo/technical-analysis-of-all-european-contact-tracing-apps-covid-19-1558</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is an ongoing article. It is intended to serve as reference for researchers and may be subject to modifications.&lt;/p&gt;

&lt;p&gt;TL;DR: If you're looking for the Google Sheets file containing all the European API endpoints, it's on &lt;a href="https://docs.google.com/spreadsheets/d/1nzLXzjPIDvON6NZgPK3AQhlgiGdrEh86JW4_uRdJLN8/edit#gid=0&amp;amp;fvid=479035305" rel="noopener noreferrer"&gt;this link&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As the COVID-19 global pandemic worsened, different countries began looking for ways to trace the spread of the infection in an effort to cut the transmission as soon as it was detected.&lt;/p&gt;

&lt;p&gt;The result of this effort were &lt;strong&gt;Contact Tracing Apps&lt;/strong&gt;, simple yet effective applications that broadcast and listen to specially crafted Bluetooth Low Energy (BLE) beacons to determine whether a person has been in close contact and for how low with someone infected.&lt;/p&gt;

&lt;p&gt;Without a doubt, the universal specification for exchanging this BLE messages has been and still is GAEN (&lt;strong&gt;Google/Apple Exposure Notification&lt;/strong&gt;), yet each country or region chooses a different approach for all the other aspects of the app, such as notifying COVID-19 positives and verifying exposures.&lt;/p&gt;

&lt;p&gt;And so, here we are now. Almost every country in Europe has its own Contact Tracing App with its own respective backend servers that have their own different implementation and that, in the majority of cases, are not compatible with one another.&lt;/p&gt;

&lt;p&gt;The purpose of this brief article is &lt;strong&gt;to put together all the technical information I've been collecting&lt;/strong&gt; about these apps and to serve as documentation for other researchers.&lt;/p&gt;

&lt;h1&gt;
  
  
  App classification
&lt;/h1&gt;

&lt;p&gt;At the time of writing, there are 21 European countries using Contact Tracing Apps (CTAs) in production.&lt;/p&gt;

&lt;p&gt;They can be classified mainly by the license of their source code and the backend implementation they are using.&lt;/p&gt;

&lt;h2&gt;
  
  
  By source code license
&lt;/h2&gt;

&lt;p&gt;Although the vast majority of CTAs are open-source, there are &lt;strong&gt;3 (dis)honorable mentions&lt;/strong&gt; of countries with no intention in publicly releasing the source code of their apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://virusradar.hu/" rel="noopener noreferrer"&gt;VirusRadar&lt;/a&gt; (Hungary): Not only is closed source, but it is also centralized and requires users to register with a phone number and other identification details to start using it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://koronastop.lrv.lt/" rel="noopener noreferrer"&gt;Korona Stop LT&lt;/a&gt; (Lithuania): The latest app of this kind to have been released in Europe. It is based on Corona-Warn-App (provided under the Apache-2.0 License), so maybe they intent to release the source code soon, who knows.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://smittestop.dk/" rel="noopener noreferrer"&gt;Smittestop&lt;/a&gt; (Denmark): Built on Xamarin, is more difficult to decompile than other apps and also requires user registration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  By backend implementation
&lt;/h2&gt;

&lt;p&gt;Most apps have their own implementation for their backend servers. Of the ones that are based on a common specification or library, DP-3T and CWA have an almost equal market share.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3020ft7xpotspobdfd27.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3020ft7xpotspobdfd27.png" alt="Pie chart of CTAs classified by backend implementation"&gt;&lt;/a&gt;&lt;/p&gt;
CTAs classified by backend implementation



&lt;p&gt;&lt;a href="https://github.com/DP-3T/documents" rel="noopener noreferrer"&gt;DP-3T&lt;/a&gt; (short for Decentralized Privacy-Preserving Proximity Tracing) is developed mainly by the &lt;a href="https://www.epfl.ch/" rel="noopener noreferrer"&gt;EPFL&lt;/a&gt; in Switzerland and has also had great influence in the GAEN protocol.&lt;br&gt;
Apart from the one from its home country, the CTAs from Estonia, Malta, Portugal and Spain use this implementation too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/corona-warn-app" rel="noopener noreferrer"&gt;CWA&lt;/a&gt; gets its name from the German CTA (Corona-Warn-App). The source code of the entire infrastructure of this app is available on GitHub, as is the case with DP-3T. Belgium, Germany, Lithuania and Slovenia have chosen this implementation.&lt;/p&gt;

&lt;p&gt;Despite not being an actual open-source implementation as with the previous cases, some Eastern countries use &lt;a href="https://aws.amazon.com/s3/" rel="noopener noreferrer"&gt;S3 buckets&lt;/a&gt; to host their TEKs (Temporary Exposure Keys) for app clients to download them.&lt;br&gt;
These countries are Czechia, Latvia and Poland.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other implementations
&lt;/h3&gt;

&lt;p&gt;In the "other" category, it's worth mentioning the apps from Ireland and France (COVID Tracker and TousAntiCovid, respectively).&lt;/p&gt;

&lt;p&gt;COVID Tracker is based on the &lt;a href="https://github.com/covidgreen" rel="noopener noreferrer"&gt;COVID Green&lt;/a&gt; project from the LFPH (Linux Foundation Public Health). It does not require user registration, but enforced OAuth Bearer authentication in all requests to the backend.&lt;/p&gt;

&lt;p&gt;TousAntiCovid (previously known as StopCovid) is based on &lt;a href="https://gitlab.inria.fr/stopcovid19/robert-client-api-spec" rel="noopener noreferrer"&gt;ROBust and privacy-presERving proximity Tracing&lt;/a&gt; or ROBERT for short because the French Government cannot help itself when naming things using fake acronyms.&lt;br&gt;
This is one of the most concering Contact Tracing implementations, as it is fully centralized (the server is the one that verifies exposures, not the clients) and it even enforces user registration.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;Although there is clearly fragmentation in the European Contact Tracing App ecosystem, it is not that big of a deal as all countries except from France and Hungary have taken a decentralized approach that works by &lt;strong&gt;hosting TEK batches&lt;/strong&gt; in their backends and letting clients &lt;strong&gt;download them to verify exposures&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As these TEKs are in the GAEN protocol format, it means all decentralized apps should hypothetically be able to exchange their batches. This looks like the next reasonable step forward and hopefully it becomes a reality with the &lt;a href="https://github.com/eu-federation-gateway-service/efgs-federation-gateway" rel="noopener noreferrer"&gt;EU Federation Gateway Service&lt;/a&gt; initiative that some CTAs are already using.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.google.com/spreadsheets/d/1nzLXzjPIDvON6NZgPK3AQhlgiGdrEh86JW4_uRdJLN8/edit#gid=0&amp;amp;fvid=479035305" rel="noopener noreferrer"&gt;Summary of European Contact Tracing Apps 🔥&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ec.europa.eu/info/live-work-travel-eu/health/coronavirus-response/travel-during-coronavirus-pandemic/mobile-contact-tracing-apps-eu-member-states_en" rel="noopener noreferrer"&gt;Mobile contact tracing apps in EU Member States&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/android/exposure-notifications/apps" rel="noopener noreferrer"&gt;Publicly-available Exposure Notifications apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/DP-3T" rel="noopener noreferrer"&gt;Decentralized Privacy-Preserving Proximity Tracing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/corona-warn-app" rel="noopener noreferrer"&gt;Corona-Warn-App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitlab.inria.fr/stopcovid19/robert-client-api-spec" rel="noopener noreferrer"&gt;ROBust and privacy-presERving proximity Tracing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;blockquote&gt;
&lt;p&gt;Found a misspell, have a correction or additional information? Let me known and I'll be glad to fix it! 🙂&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>security</category>
    </item>
    <item>
      <title>From Ubuntu to Debian without any external storage device</title>
      <dc:creator>José Miguel Moreno</dc:creator>
      <pubDate>Fri, 27 Mar 2020 14:02:01 +0000</pubDate>
      <link>https://dev.to/josemmo/from-ubuntu-to-debian-without-any-external-storage-device-58o8</link>
      <guid>https://dev.to/josemmo/from-ubuntu-to-debian-without-any-external-storage-device-58o8</guid>
      <description>&lt;p&gt;Say you have a machine, probably a virtualized one, running Ubuntu or any other similar GNU/Linux distribution. The thing is, you don't want to run Ubuntu anymore on that particular machine and you decide to nuke the entire disk and install Debian 10.&lt;/p&gt;

&lt;p&gt;But, and here's the catch, &lt;strong&gt;you're not able to plug any bootable USB stick&lt;/strong&gt; or mount a CD/DVD! Also, your BIOS/UEFI doesn't support network booting (because of course not) and you're running extremely low on storage space.&lt;/p&gt;

&lt;p&gt;You may be asking: "How the f$%&amp;amp;! did you manage to get into such troublesome situation?" and "Is it really possible to overwrite the OS at this point?". Well, as you might have probably guessed by the title of this post, it is!&lt;/p&gt;

&lt;h2&gt;
  
  
  My current (hypothetical) situation
&lt;/h2&gt;

&lt;p&gt;So, let's recap. I have a virtual machine that...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Has no working USB ports&lt;/li&gt;
&lt;li&gt;Has no CD/DVD drive&lt;/li&gt;
&lt;li&gt;Has a limited BIOS with no support for network booting&lt;/li&gt;
&lt;li&gt;Has less than 100 MB of disk space left&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I cannot burn the Debian Installer to a USB drive&lt;/li&gt;
&lt;li&gt;I cannot mount the Debian Installer ISO&lt;/li&gt;
&lt;li&gt;I cannot use the Debian Installer via Network Boot&lt;/li&gt;
&lt;li&gt;I cannot create a partition to copy the Debian Installer to and boot from there&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The (surprisingly easy) solution
&lt;/h2&gt;

&lt;p&gt;Believe or not, there's still a way to install Debian on this crappy machine. You just need three things: "mini.iso", GRUB2 and at least 100 MB of RAM. And that's all.&lt;/p&gt;

&lt;p&gt;First of all, you need to download the "mini.iso" file from the Debian Network Installer. This ISO is a 40 MB, minimal bootable system that can install Debian providing you have a working Internet connection.&lt;/p&gt;

&lt;p&gt;You can download the latest version of this file from the official Debian Project page using &lt;a href="https://cdimage.debian.org/debian/dists/stable/main/installer-amd64/current/images/netboot/mini.iso"&gt;this link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DPaeaKTc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/ijinAtJ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DPaeaKTc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/ijinAtJ.png" alt="The Debian Mini ISO file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now copy that file to &lt;code&gt;/boot&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;~$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo cp &lt;/span&gt;debian.iso /boot/debian.iso
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We'll use GRUB to &lt;strong&gt;dump that ISO to RAM and then boot to it&lt;/strong&gt;. In order to achieve it, modify the &lt;code&gt;/etc/grub.d/40_custom&lt;/code&gt; configuration file to add the following menu entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;menuentry "debian-installer" {
  set isofile='/boot/debian.iso'
  loopback loop $isofile
  linux (loop)/linux priority=low toram vga=788 ---
  initrd (loop)/initrd.gz
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You may also need to modify the &lt;code&gt;/etc/default/grub&lt;/code&gt; file to display the entry selection menu at boot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#GRUB_HIDDEN_TIMEOUT=0 # &amp;lt;--- Make sure this is commented
GRUB_TIMEOUT_STYLE=menu
GRUB_TIMEOUT=10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Lastly, call &lt;code&gt;update-grub&lt;/code&gt; to apply the changes you've just made:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;~$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;update-grub
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At this point, you should be able to reboot the VM and get the following screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GdUuPO6n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/3nI1k5G.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GdUuPO6n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/3nI1k5G.png" alt="GRUB selection menu"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only thing left to do is boot to "debian-installer" and follow the steps until you finish installing Debian.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>devops</category>
      <category>ubuntu</category>
    </item>
    <item>
      <title>Docker + VMware on Windows: the easy way</title>
      <dc:creator>José Miguel Moreno</dc:creator>
      <pubDate>Sun, 17 Nov 2019 12:54:39 +0000</pubDate>
      <link>https://dev.to/josemmo/docker-vmware-on-windows-the-easy-way-498k</link>
      <guid>https://dev.to/josemmo/docker-vmware-on-windows-the-easy-way-498k</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;August 2020 Update&lt;/strong&gt;: now that VMware Workstation can run with Hyper-V installed, there's a better alternative to running Docker on Windows 10. Check out &lt;a href="https://docs.docker.com/docker-for-windows/wsl/"&gt;this guide&lt;/a&gt; for more information.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Docker is one of the most useful tools for a developer nowadays, but setting it up on a Windows machine can be really painful, specially if you don't want to enable Hyper-V and prefer to use another hypervisor such as VMware Workstation.&lt;/p&gt;

&lt;p&gt;Fortunately, there's an "easy" way to do exactly that with &lt;a href="https://chocolatey.org/"&gt;Chocolatey&lt;/a&gt;, the self-proclaimed package manager for Windows. Let's get started!&lt;/p&gt;

&lt;p&gt;First of all, we need to open a Powershell window with administrative privileges and run the following command to install the Docker CLI and the VMware Docker machine driver:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PS&amp;gt; choco install docker-cli docker-machine-vmware
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As Docker is runtime-agnostic, we can create a custom Docker machine running inside a VMware VM instead of using Hyper-V and then connect that instance to the Docker CLI. Let's create the Docker machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PS&amp;gt; docker-machine create --driver=vmware default
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This command will take a few minutes. After it's done, make sure it was successful by listing the available Docker machines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PS&amp;gt; docker-machine ls

NAME      ACTIVE   DRIVER   STATE     URL                          SWARM   DOCKER     ERRORS
default   -        vmware   Running   tcp://192.168.142.136:2376           v19.03.5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Great, we're almost done! The final step is to tell the CLI to use this machine for any Docker-related commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PS&amp;gt; docker-machine env | Invoke-Expression
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And that's it! Docker running on Windows using VMware Workstation instead of Hyper-V. Keep in mind you'll need to start the Docker machine and connect it to Docker CLI every time you boot your device:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PS&amp;gt; docker-machine start default; docker-machine env | Invoke-Expression
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;p&gt;Last but not least, here are some relevant URLs you can visit to learn more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/machine-drivers/docker-machine-driver-vmware"&gt;Docker machine VMware driver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/machine/get-started/"&gt;Docker machines documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>windows</category>
    </item>
  </channel>
</rss>
