Musings of a *Nix Nerd

This post has been long in coming. For those who haven't read the previous posts in this series, below are links to bring you up to speed.

In Part 1, we covered the basic mathematical information and technical information required to understand and begin to implement your own cryptography. Part 1: HERE

In Part 2, we set up a Cryptographically Secure Pseudo-Random Number Generator to be used by our cryptographic algorithms. Part 2: HERE

If you're stuck, the previous posts may help with bringing you up to speed. Now, let's add in the hashing algorithm!

Hashing? What's that?

A Hashing Algorithm is this carefully crafted program that takes a string as an input, performs a bunch of cryptographic functions on it, and spits out a fixed-length string that appears to be random. However, if you compute the hash again with the same string, you will achieve the same output.

A sample hashing function could be a simple XOR operator. You take random bytes to produce “entropy” for the hashing function, saving the information somewhere. Then you could just XOR the string with the saved random bytes, chopping the hash off at a fixed length. This is known to be highly insecure as performing an XOR against itself is effectively an inverse operation and will undo the work of creating a hash.

Since we are simply using a hashing function on our CSPRNG to produce more useful randomness (effectively increasing the efficiency), we can afford to use a hashing algorithm that has been compromised as there's no user data flowing through it.

Wait, Compromised?

Yes. Remember that we're simply using SHA512 to produce more bytes of pseudorandom information that our cryptographic system can utilize, by feeding it small amounts of pseudorandom characters (characters are actually integers from 0-255 in C).

Due to this, performance matters more than security. SHA512 isn't the most performant, but it's high bit modulus means that the algorithm will have some level of security as well. However, the REAL security will come from our encrypted asymmetric keys. Some argue that this is entirely unnecessary and in the final version of this program, we may even eliminate this bit of code if deemed not necessary.

The Implementation

For our hashing algorithm, we are going to borrow the Free Software Foundation's implementation of SHA512 and take a look at a sample implementation by ggaarder on GitHub, located here.

We notice that SHA512 uses 64 bit integers, and for compatibility, a custom headerfile was included to allow other architectures to process 64 bit numbers as if they were uint64_t (Thanks, Paul Eggert for your contribution to Open Source Software!).

Along with these two things, sample usage of the program is provided:

#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
#include "sha512.h"

#define F "sha512.c"
#define F1 "sha512.cp"

void psum(char *out)
    char *p;
    for (p = out; p < out+64; p += 8) {
        // 8 byte is 64 bit
        printf("%lx", *(uint64_t*)p);

int main(void)
    FILE *fp = fopen(F, "rb");
    char out[64];
    sha512_stream(fp, out);
    fp = fopen(F1, "rb");
    sha512_stream(fp, out);

As we can see, this code involved the opening of the file SHA512.c in binary read-only mode, computing a sha512 stream using the contents of the file pointer and assigning it to a char array of size 64. the psum() function allows the printing of the array to standard output. So if we integrated this with our CSPRNG (so we can produce pseudorandom characters), we would need to make our CSPRNG produce pseudorandom strings and then use those for SHA512.

We would need to do something like this:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <stdint.h>
#include <string.h>

#include "duthomhas/csprng.h"

#define MESSAGE "message.txt"

extern int csprng_get(CSPRNG, void* dest, unsigned long long size);
extern CSPRNG csprng_destroy(CSPRNG);

// Our implementation of the CSPRNG
void * randstuff(void * x) {
  CSPRNG rng = csprng_create( rng ); // create CSPRNG
  if (!rng) { 
    //if the CSPRNG fails to load
    fprintf( stderr, "%s\n", "No CSPRNG! Crap." );
    exit(1); //crash and return an error

  csprng_get(rng, &x, sizeof(x)); // use CSPRNG
  rng = csprng_destroy(rng); // destroy the CSPRNG

  return x;

// Print out Hash
void psum(char *out) {
    char *p;
    for (p = out; p < out+64; p += 8) {
        // 8 byte is 64 bit
        printf("%lx", *(uint64_t*)p);

// Main function
int main(void) {
  char rand[64]; //To be filled with random garbage
  char hash[64]; //To hold the hash
  int errchk;
  FILE * fp;

  // Wipe the values in allocated memory before assignment.
  memset(rand, '\0', sizeof(rand));
  memset(hash, '\0', sizeof(hash));

  strcpy(rand, randstuff(rand)); // assign randstuff to rand.


  fp = fopen(MESSAGE, "w+"); // open message.txt for writing
  for (int i=0; i<(sizeof(rand)/sizeof(char)); i++) { 
    //loop through each item in rand, creating a tempfile
    //with pseudorandom content.
    fprintf(fp, "%c", rand[i]);


  fp = fopen(MESSAGE, "rb"); // Open file called message.txt 
  sha512_stream(fp, out);


  errchk = remove(MESSAGE);

  if(errchk != 0) {
    printf("Error deleting entropy file. CSPRNG may be compromised.\n");

  return 0;

Note that this code doesn't have error checking, and it's just the raw algorithm. We will fix that in a coming post.

To explain what was added, we utilized the same CSPRNG code from before and assigned it to an array called rand. Since the SHA512 calculation requires a FILE data type (an Input/Output stream), we need to write the contents of rand to a temporary text file character by character. In doing so, we can calculate the SHA512 hash of the randomness, print it to standard output courtesy of the psum() function, and then remove the temporary file by calling the remove() funtion.

In the future, it might be smart to create a second temporary file to write the SHA512 hash to and delete the first, but time will tell if we need to make this change.

With this code tested and working, we can proceed onward to the design and implementation of our Elliptic Curve Diffie Hellman Algorithm to allow for asymmetric encryption!


I was reading old blog posts and realized I didn't touch on a CRITICAL piece of the puzzle to understanding computing... How your device actually works. This post aims to remediate this and provide a “one-stop” guide from understanding the low-level circuitry to how that allows people to program on their devices.

No computers were harmed in the making of this post. No, seriously.

The Electronics

Everything in a computer is a 1 or a 0. Many people call this true or false, or even on or off. Whatever you may call it, it's the basis for boolean (digital) logic. When you use a series of true or false statements, you are making use of the binary number system. Instead of having a 10's, 100's, 1000's etc place there's powers of 2. so 11111111 would equal 255, because 1+2+4+8+16+32+64+128=255. This is similar to how we would calculate what 255 equals- 200 + 50 + 5 = 255.

Now, we can use logic gates to perform mathematical operations on binary numbers. AND ('+' sign), OR ('–' sign), XOR ('+' sign with a circle around it), NOT ('!' mark), and NAND are the building blocks. Each one have unique properties, some are self-explanatory. If you feed 2 binary digits as input to each logic gate, it will spit out an output. 1 AND 0 will produce 1, but so will 1 OR 0... Huh? This is because you can have more than 2 inputs. Digital logic aside, we can pair these together to design different electronic components.

For our sample computer architecture, we will use a modified Von Neumann architecture, adapted so it's more in line with modern computers.


Every computer has multiple different kinds of memory, EEPROM, PROM, EPROM, DRAM, SRAM, NAND Flash and so on. What the heck is all this stuff?

Let's start by explaining that ever computer needs various types of storage. First off, we need Random-Access Memory (RAM) to temporarily hold results of various calculations to allow for calculations to run smoothly. The two main types of these are DRAM (Dynamic RAM) and SRAM (Static RAM). DRAM loses it's contents upon loss of power, while SRAM retains it until it regains power.

DRAM An actual 16 bit DRAM chip sample pinout.

RAM sticks are EXTREMELY fast but aren't good for extreme long-term storage, like our computer's BIOS and bootloader (the little screen that pops up when you press the power button). To achieve this, various ROM (Read-Only Memory) chips are available. Electrically Erasable Programmable ROM (EEPROM) chips, Programmmable ROM (PROM), and so forth are available for this purpose.

But what about user files? Enter NAND Flash and Spinning Disk Drives. NAND Flash (guess what it's made of?) is the new kid on the block, with it's own unique technologies that make it extremely fast and useful for storing user data, generally functioning like SRAM but not deleting data after power cycles. Spinning Disk Drives are still commonly found in enterprise areas and surveillance due to cheap pricing, and they use mechanical disks with magnetic “tracks” in concentric rings to store data, with a read/write head to manipulate the info.

The Processing Units

Every Computer has a CPU, though ones with graphical displays also have a GPU (which can be treated as a task-specific CPU for intents and purposes). In the old days, the CPU only consisted of one component: the processor. It left out other critical components like the system clock as it was often soldered onto the mainboard (motherboard).

The CPU (Central Processing Unit) is another chip, designed out of a series of logic gates, that takes a series of inputs (by giving power to various combinations of pins on the CPU) and spits out calculations based on them, effectively allowing it to perform multiplication, addition, addition, and so forth. When paired with a real-time system clock, the CPU becomes able to execute operations in sequence- forming machine code as we know it. Now, some modern CPU designs opt to include the system clock into the CPU itself and some don't nowadays, it's just an important thing to understand how it works.

CPU A CPU and it's pins.

A CPU contains it's own “memory”, called registers, that allow for the temporary storage of small amounts of data for faster processing, as registers are the fastest places to store data on any system.

The Graphics Processing Unit, or GPU, functions just like a CPU. Modern graphics cards have their own special RAM connected to the GPU, while some other pins are connected to various chips that control different devices such as an HDMI slot for a monitor, with a ROM chip connected to the GPU that has firmware to power the device.

All of these things get connected together and powered to produce a fully working computer architecture.

The Code

The Assembler

If you asked someone to write a large program in machine code, they'd most likely either run away, laugh at you or ask you if you are crazy. This is simply due to the fact that Machine Code is ENTIRELY in Binary (although it can be expressed as hexadecimal). As a workaround, developers create Assembler Languages, which are effectively a simple translation of the arcane machine language operations from binary to things humans recognize. For example,

10001111 10001111 10011110

might look like this in an Assembly language:


According to our sample machine language and Assembly instruction, we'd be moving the value at register 1 to register 2.


As one might imagine, Assembly language is still tedious and it would be tough to implement an Operating System like the ones that exist today. In order to be able to achieve feats like this, it must be possible to write code in a much more human-readable language and let the computer translate it into Machine Code.

Enter Compilers. They basically analyze text through a set of rules and then based on these rules output and optimize machine code for a given architecture. This allows the implementation of various programming languages like C, C++, and Java to exist.

To implement an Operating System, a developer would need to flash the ROM with a Basic Input/Output System (BIOS), and then write code for a bootloader to boot the system. The developer may then produce a kernel to load the firmware for all connected devices and operate the low-level parts of the system that the user doesn't see. Lastly, the developer is able to create various bits of software to run on this machination, eventually resulting in a full-fledged Operating System.

Hopefully this guide proves to be handy and provides a useful resource for any budding developer interested in electronics or computing.


For those who are unfamiliar with FreeBSD, it's a unique system that feels distinctly like the UNIX of old- because it is. Last post, we installed FreeBSD, got connected and installed some software. You might have even gotten a desktop working on your own, because it feels so much like Linux. However, the stock install is a bit RAM hungry and we aim to improve that.

Kernel? What's a Kernel?

Like Linux, FreeBSD (and Windows and MacOS) all have an underlying Kernel. This is basically a loose term that describes all the underlying components that the user doesn't see day-to-day when utilizing an Operating System, such as firmware and drivers being loaded, support for multithreading, filesystem support, and so on. Because BSD has so much support for strange devices- like VAX machines of old- it's expected of users who wish to optimize their systems to purge unneeded support from their system.

Getting Started

Of course, you'll need a FreeBSD installation with the source code to follow along... :) However, we'll need some more details about our target system that we'll be rolling a custom Kernel for. So let's whip out a notepad or text editor and our trusty command line. The trusty dmesg command will come in handy, but it produces way too much output, so we can filter that with grep by doing something like dmesg | grep <search term>.

The laptop I did this on was an unmodded Thinkpad T460. I knew that it came with Intel Wireless, an Intel CPU, an SSD, and Intel Integrated Graphics, for starters. But what model?

So I ran dmesg | grep Wireless and got the following output:

iwm0: <Intel(R) Dual Band Wireless AC 8260> mem 0xredacted at device redacted

Note that I have censored the last bit of output for privacy, but it contains memory address and what part of the PCI bus it's connected to.

I took note of this and did similar commands to gather info on my hardware.

Backing Up

Since we're replacing our kernel, we want a backup of the last known good one. In FreeBSD, the current running kernel is located at /boot/kernel. So let's make a copy in /boot, so we can continue to use it if things go south!

Running cp -a /boot/kernel /boot/kernel.good will do the trick for this.

Config Time!

Now we get to prep our Kernel config file. To do so, cd /sys will take you to the /sys directory, where you'll see a few architecture names as directories: x86, x64, arm, etc. My ThinkPad T460 is a 64 bit x64 processor, so I ran cd x64.

Now, there's a folder in this directory called conf. That's where the config files are located- so cd conf and then run ls to view the available config files to start from.

Instead of altering the config files directly, it may be wise to make a copy of one. I picked the GENERIC config file and copied it into one in the same directory, naming it T460 (no file extensions!!!)

With this done, open the freshly copied config file in the text editor of your choice. In this config file, there's lots of comments, specifying what each option will compile into the kernel. Removing the line will remove the feature from your compiled kernel. Since my ThinkPad doesn't have a floppy disk or RAID controller that's easy enough to remove those. I know that I have Intel Wired and Wireless connections, so I can remove all support for other network cards if I so choose.

ATCHUNG! Read what each option enables support for before deleting the line, and make sure you're not removing things that are critical to the function of your hardware!

Once satisfied, save the new config and quit.

Updating the Source

First things first, we need to install and set up subversion (SVN) on FreeBSD to get the latest copy of the FreeBSD source tree. In order to install SVN and get it ready to rock, we just need to run pkg install ca_root_nss subversion.

Now with SVN installed, let's fetch a copy of the latest source tree. If you already have the source code installed, run svn update /usr/src/. If not, we need to fetch a copy by running svn checkout https://svn.freebsd.org/base/releng/12.1 /usr/src/ (replace the 12.1 with the version number of FreeBSD you installed.)

Awesome! We're ready to compile the kernel!

Compiling the Kernel

With your freshly updated copy of the FreeBSD source code, cd /usr/src to get into the source code. Since our config file is prepped, all you have to run is make KERNCONF=CONFIG buildkernel– swap out the word CONFIG for your kernel config name. This will take a bit to compile, so grab a coffee or something while waiting. When it finishes, you run make KERNCONF=CONFIG installkernel, again swapping out the word CONFIG for your actual config filename. When finished, reboot your system and test it out!


In the bootloader, you can switch back to the old kernel to resolve the issues in your config and re-attempt compiling the kernel until satisfied.

What Are The Benefits of Doing This?

On my ThinkPad T460, the stock system used about 1.7 gb of RAM. After the custom kernel, it's now using 800 Mb of RAM- to lower the usage even further, some tunable “knobs” in /etc/rc.conf, /etc/loader.conf and /etc/sysctl.conf prove useful as well.

Another interesting thing to note is that this Kernel config can be used to rebuild the ENTIRE SYSTEM as well, using the make KERNCONF=CONFIG buildworld and make KERNCONF=CONFIG installworld commands too.

Until next time!


Most would agree that IT and Computer geeks have an intense passion for Open Source Software and quality code. Due to this, Linux is a staple in the tech community... But is it the only option? Enter FreeBSD, an Operating System whose roots trace all the way back to the original UNIX. Buckle up, and prepare for an introduction to FreeBSD and setting it up yourself.

Wait, Slow Down. What's FreeBSD?

Back in the 1970s and 1980s, AT&T Bell Labs invented UNIX and would go on to sell commercial copies of said Operating System to various colleges. The awesome thing was that AT&T shipped source code bundled right in! One of these places was the University of California at Berkeley, who aptly wrote more tools for UNIX such as vi and the original Berkeley Fast Filesystem (what most Linux/UNIX Filesystems are based on nowadays). Eventually UC Berkeley went on to redistribute their own variant of UNIX called BSD, setting up a hotline at 1-800-ITS-UNIX. This ROYALLY pissed off AT&T and they sued for copyright infringement. For reference, around this time Linus Torvalds was beginning the Linux Kernel development.

Needless to say, UC Berkeley won the case almost totally- so much so that AT&T only kept copyright to 3-4 files of the entire UNIX system. This enabled the release of i386BSD, which spawned the FreeBSD, NetBSD and OpenBSD projects. Their licenses are all very close to the original license of the code which is extremely permissive and allows the user to do almost anything except take credit for the work, sue the developer and remove the license.

Cool! Let's Install It!

Awesome! At this time of writing, the latest stable version of FreeBSD is 12.1. If you browse to the FreeBSD Site, you'll notice a big “Download Now” button. For this series of blog posts, we'll install 12.1 because stability matters for a daily-driver laptop. Pick the correct CPU architecture and you'll be taken to a web open directory. There are multiple images available for download, generally DVD1 and memstick images have all installation files embedded into the image so no network connection is needed to install the system.

Now that the image is downloaded, pick an installation medium. For usb, you would insert a thumb drive and type sudo dd if=/path/to/FREEBSDIMAGE of=/dev/sdX status=progress, where the “if” argument is the location of your downloaded FreeBSD installer image and the “of” argument is the name of your drive under Linux.

After this is done, let's yank out our computer and boot into the installer! On most laptops, there is a key combination to enter the BIOS, like spamming F12 or delete on boot. Once you've done this, allow USB booting, disable secure boot, and configure your flash drive to boot first. With the flash drive plugged in, you should be greeted by a FreeBSD bootloader, waiting a moment will take you to a graphical menu that looks like this:

FreeBSDInstaller The FreeBSD Installer

Select your responses with the arrow keys, and press enter to continue.

FreeBSDInstaller2 In prompts like this one, you'll need to use the space bar to alter selections.

The menu is very simple and easy to go through... Once you arrive at what disk format to use, the most common option FreeBSD users select is entire-disk ZFS.


Remember to select your disks in the ZFS Pool! The original option is stripe/0 disks, but you still need to go into it's submenu and select a disk even if you don't want to use the mirroring abilities of ZFS. There is an option to enable encryption, enabling it will provide a prompt later for your disk encryption password. If you're content with the settings, continue on.

After this, you'll be greeted by a menu of what packages you'd like to install, selectable by spacebar and arrow keys. Pressing enter will allow you to continue to the installation. Once complete, the interface will drop to a shell for you to set the root user password. Once that's done, the installer will take you back to the UI and offer to create a user account (DO THIS!), where you drop back to the shell to create it. Lastly, there will be system hardening options that you can optionally check. If you're concerned with privacy, it is recommended to enable all of them. Finally, it will provide an option to exit the installer and reboot.

Welcome To FreeBSD!

On fresh installation, FreeBSD is extremely plain and doesn't even have a desktop. Our first priority is to connect to the internet, so we can update our system. Running the ifconfig command will list all devices that are recognized by FreeBSD. If your network card isn't recognized, you will want to search to see if it's supported. If so, there's probably a kernel module that hasn't been loaded for it. To remedy this, a simple kldload xxx (where xxx is the name of the kernel module corresponding to your device driver) will enable your hardware. If this works, you can make this change permanent by editing /etc/rc.conf. FreeBSD makes use of wpa_supplicant and ifconfig to connect- more comprehensive guides on getting connected can be found here:

Wireless Networking in FreeBSD Networking in FreeBSD

Once connected, updating the system and fetching a few apps to get started with configuration is critical. There's three ways a user can install software on FreeBSD: compiling from source by hand, compiling from source through the ports collection (automatically), or using the pkg package manager which feels very much like apt.

Set up the FreeBSD ports tree by running portsnap fetch extract. If you ever wish to use it, cd into /usr/ports and find the proper directory of the application you wish to install. Then type make clean install.

As for pkg, let's update, upgrade and install vim:

pkg update
pkg upgrade
pkg install vim

Once all the software required for a desktop or whatever use case is necessary, setup is just like any *nix-based system.

So What Makes FreeBSD Different???

FreeBSD has a bunch of unique development tools, such as dtrace, for programming and understanding how the Operating System works and programming good, solid code. On top of that, it comes with pf instead of iptables, which is the de-facto standard on many enterprise networking devices such as Cisco or Palo Alto (they actually ship with FreeBSD installed). The entire Operating System source code can be found in /usr/src, and you can recompile the entire OS with a one-line terminal command. FreeBSD and similar systems are known for having the best TCP/IP networking stack in the world, so much so that even Microsoft still uses FreeBSD code for driving the internet on Windows to this very day.

Be sure to stick around for the next post, where we'll compile a custom kernel on FreeBSD!


On Monday, June 22, 2020, Apple's renowned (infamous?) World-Wide Developer Conference took place. As usual, the announcement of new devices took place- along with a shocker that has the potential to kill off software ecosystems and shut down development efforts.

Okay, Okay. What The Heck Happened?

According to MacWorld and video of the actual conference, Apple plans to swap their CPUs with a new, custom in-house one... The same processor line found on the iPhones and iPads! These Processors are based on ARM CPU technology, but due to Apple's walled-garden stance they modified the design.

ARM and a Leg

In order to avoid this turning into a complaining rant, let's balance this out by first mentioning the benefits ARM provides:

  • ARM is based on a RISC architecture, allowing for lower power usage and improved performance (provided the software is properly written)
  • ARM is less expensive than Intel or AMD CPUs, theoretically reducing the cost of production.
  • ARM is found in tons of Internet-Of-Things and mobile devices, especially smartphones.

The Catch

Although these are amazing benefits and worth considering the switch in laptops and mobile devices, Apple isn't following the standard design. For all users may know, the machine language may differ from the original CPU. If so, it's impossible to write C/C++ or compile ANY third-party code without an Apple-supplied compiler. On top of this, hackers and developers have been struggling for YEARS to get Linux working on the iPhone and iPad and have always had hangups on the CPU and the hardware in the device that locks them out.

Since the new Macs will be using this same line of chips, running anything other than software condoned by Apple will be impossible. To further compound the issue, Apple has agreements with the U.S. Federal Trade Commission to ban the import of components for their devices. On top of this, Apple intentionally opted to solder the hard drive to the motherboard and removed the data recovery pins- now the only way to protect your info on Mac is to buy their services or get a backup drive.

The Problem

This activity poses several ethical and financial dilemmas for a potential buyer, seeking a new laptop or computer.

“We're Sorry It's Broken. Feel Free to Buy A New Mac!”

How many times have you heard this at the Apple store or a computer shop? Did you know that the majority of times a computer breaks, the repair normally will not cost more than $50-100 USD? By making devices impossible to repair, there's actual justification in making this claim. But then if it's impossible to fix or even recover your data, why buy it?

No Schematics For You!

Most people can agree that we all disagree on many things. However, most can all agree that major companies are not worthy of our trust in light of recent scandals. When a major laptop manufacturer like Apple switches to a custom in-house CPU, it becomes impossible to audit it's security without attempting to hack it and play the role of the “bad guy”.

Lockdown and Lock out

Apple has always been a “Walled-Garden” ecosystem in their systems, but allowed third party apps to run. Due to this new CPU, all third party software is entirely dependent on whether or not Apple chooses to release compilers for their architecture. Even so, will they apply licenses to the compilers? Will they be compliant with current Operating Systems standards? Nobody knows, and there's potential for the death of third-party apps on the new platform. At the very least, all third party software would have to be recompiled (or rebuilt) to be compatible with the new architecture. For some maintainers, they may never even bother and third party support will dwindle.


As we all know, companies are driven by profit and go back on their decisions if it means a lack of sales. This means that if users don't support their actions, then DON'T BUY THE PRODUCT!

On top of this, hacking and research communities should pick up the new Macs as they arrive, and deduce how everything works, inventing ways to enable compatibility with other software and (maybe?) hardware on these new devices.

Lastly, if this bothers you, spread the word and explain it to others so they understand the importance of having the ability to fix your own belongings.


Sine waves... GASP!!! This is the voodoo magic of the world of wireless technology. Not really, but it is mathematical, and really fascinating and I can't stop geeking out about it.

So why is this so important? As it turns out these basic physics allow WiFi, AM/FM Radio, GPS, CB Radio, Bluetooth, headphones and more to interact with the world around us. Without further ado, onward forth!

What's Your Sine?

So a sine wave is literally just a measurement of frequency and amplitude, plotted on a graph. Frequency is measured in hertz (Hz), where 1 Hz is one repetition per second. Amplitude is measured in decibels- think of volume control versus pitch when listening to music. The legal maximum output of a US FM Radio Station is 80 DBm, the power of the Sun when measured is approximately 306 DBm, and the average conversation is about 50-65 DBm. When plotted on a line graph, one might get a signal that looks like this:

SineWave1 Assuming this signal repeats 1 milion times a second, we could say it operates at 1 MHz (1 Megahertz)

Amplitude Modulation, or AM, is when the DBm is altered to produce a data stream. The benefit of this is that it has extremely long range, but is very susceptible to interference from natural sources like lightning.

Frequency Modulation, or FM, is when the Hz is altered to produce a data stream. The range isn't as good as AM but requires intentional attacks (such as jamming) to interfere with the signal.

Prepare The Phase Ray Generator!!!

Only half kidding, phase in a signal is where the signal starts and how it's transmitting. For example, you can have a 1 Hz signal that has different peaks and valleys when graphed compared to someone else's.

SineWave2 Sine Waves have different degrees of phase, totalling to 360 like a circle. Above, the wave has been split into 90 degree chunks.

Enter phase shifting. This is commonly found in wireless networking protocols found in WiFi such as WPA and WPA2, in encrypted communications networks, and even in mobile phones. To phase shift a signal, all one needs to do is take a chunk from the beginning of the signal and slap it on the end, using the degrees measurement of the sine wave. a 180 degree phase shift would cause a complete inversion of the wave, shown here:


Phase Lock is used in encrypted communications by having both devices phase shifting until they reach the same phase. These devices can then exchange cryptographic keys and communicate, hop to a different frequency and exchange there or end the transmission if something's wrong.

Why You Gotta Be So Noisy, Bro?

Noise is when a transmission experiences interference, making the sine wave (when graphed) look all jagged and strange. Noise Cancellation is the application of various filters to weed out the garbage. “Active Noise Cancellation Technology” dates back to the 1980s-1990s, where Adaptive Filters (the predecessor to Machine Learning/AI) found use in the detection of data that didn't belong on the sine wave, and it would “smooth” out the transmission and reduce noise.

Since then, this technology has improved and can be found in headphones, music players and more.


Packetizing something is basically when one treats the peaks of a sine wave as a binary “1” and the valleys as a binary “0”. Depending on the amount of time spent in the “1” or “0” state, we can transmit multiple of the same value (allowing us to transmit a stream of data). Due to this, we can send bits and bytes to other devices. But how on earth are we supposed to understand what's being sent?

Enter network protocols. The most popular one to exist is the TCP/IP standard, responsible for how the Internet behaves. In this, there is documentation on SPECIFICALLY how long each “packet” of traffic should be, and what should be contained inside. (Spoiler: it's basically destination and source info, the data, and a checksum to validate the info)

I haven't been entirely honest with you guys... This is actually what's taught in calculus as well as physics in colleges and universities. However, it's funny that it's so easy to understand and so amazing to see how it all works! Side note: the RTL-SDR is a great way to experiment with this, and I will most likely be writing a post on using it in the future.

Until next time!


If you had a laptop in the 2000s or earlier, chances are that you'll remember the ThinkPads of old- the practically indestructible devices, with awesome keyboards and easy to customize. They were (and still are) widely seen as the go-to laptop for productivity due to it's utilitarian design choices. Fast forward in time, IBM sold the designs and schematics to Lenovo and the ThinkPad of old is no more... or is it?

The ThinkPad T430 is the first ThinkPad to have island-style chiclet keyboards, and to be the first in a long line of devices to ignore the tried-and-true design of 20 years. However, it's fully compatible with the T420 Keyboard, which provides the old keyboard design.

Things You'll Need

Below is a list of required items for this mod: – A T430 Thinkpad (of course!) – A working T420 keyboard for installation – A large white towel – A set of precision screwdrivers – Wire cutters – A file – needle-nose pliers


Take a white bath towel and spread it over my desk. This provides a nice, white surface to be able to see screws and helps prevent damage of components from unexpected dropping. Once that is done, put the ThinkPad (ThonkPad?) on the towel and open the lid of the device and flip it over, screen facing down. Lastly, pull out the tools and have them at the ready.

Violating The Keyboard

Wait, What? Yes, you heard correctly- it's time to take the wire cutters to the T420 keyboard. But hold on! Let's take care to tweak the right things.

So there are 4 tabs in the bottom stock T430 keyboard, and the T420 has 5 of them. Remove the one in the center, under the mouse buttons and file it smooth:

Deleting Center Tab Take this slowly! Don't destroy your mouse buttons!

With this completed, now the existing tabs at the bottom of the keyboard need to be modified to accomodate the ThinkPad chassis:


KeyboardMod3 You will need your needlenose pliers and the file to obtain this shape.

With this all done, put the keyboard to the side and let's crack open the laptop.

Death To Ye Olde Keyboard!!!

Thinking ahead, we will want to temporarily remove the laptop's palmrest along with the keyboard. To do this, COMPLETELY open your laptop and flip it over, so it lies flat, and remove the battery. Then, use your precision screwdriver set to remove middle panel in the back and the usb port cover in the bottom right corner. Remember to save these screws, as they will be necessary for reassembly.

Now, we need to remove the screws that keep the chassis held together:

KeyboardMod4 The screws circled in red underneath the middle cover can be thrown away or reused, as reinstalling them will kill your classic keyboard. Otherwise, save the screws.

Now, flip the laptop over so the screen faces up and is fully opened to 180 degrees. Use a flathead screwdriver and pry the bottom of the installed keyboard forward. Once that is accomplished, there should be enough space to pry up on it, allowing you to remove the chiclet keyboard. It will be attached to the motherboard with a ribbon cable, you will need to detach this as well.

Now use the smallest flathead screwdriver (or a guitar pick if you care about avoiding scratching the plastic) and pry the palmrest away from the device. The touchpad is also connected to the motherboard via a ribbon cable and this will need to be reconnected upon assembly. Once this is removed, the palmrest will look something like this:


Das Keyboard

Now it is possible to take the classic keyboard and install it into the palmrest, taking time to ensure a proper fit. Once this is accomplished, connect the touchpad and keyboard back into the motherboard. Now, reattach the palmrest to the laptop, making sure to apply pressure to the edges of the device. You should hear “click” sounds where you reconnect it. Don't worry, this is normal.

Finally, flip the laptop over one last time and reinsert the chassis screws. Lastly, reattach the USB port covers and the cover for the center, screwing them back in. Now re-insert the battery and flip the laptop right-side up.



The keyboard should work, but some keys will be swapped out of place and it won't behave 100% properly. It should be bearable for day-to-day use.

However, if you want to get it working fully, you can install the thinkpad-ec mod, found here: https://github.com/hamishcoleman/thinkpad-ec


Hey guys, so I was doing some work with RHEL the other day and bumped into FlatPak... And ohhhhhhhhhhhhhhhh, the potential concerns with the software made me question why my client uses it.

If you've worked as a Systems Administrator or are familiar with Linux, you have most likely used Red Hat Enterprise Linux or Fedora Linux. On these systems, a package management system called FlatPak is on the rise. However, the security flaws and blatant lack of concern posed by their development team is astounding enough to possibly cause major blows to user privacy on their systems.

Flat What?

FlatPak was originally a revolutionary piece of software whose inception came from the package management problem in Linux. For those who are unaware, different Linux Distributions (systems) use different command-line utilities to allow the installation, upgrade and removal of software. Due to this issue, the people working at Red Hat figured it would be a good idea to make packages universal, and they birthed several projects like AppImage and FlatPak, which are all considered standard utilities in Fedora and Red Hat Linux installations.

It's Escaping!!!

FlatPak uses a site called FlatHub for installing packages, and almost all of them on the site have write permissions to the user's home directory- even if it's not necessary. So in theory, it's possible to simply add a program to FlatHub that executes the equivalent of echo "malicious_command" >> ~/.bashrc and suddenly get full access to the system.

Though the developers at Red Hat and Fedora claim FlatPak is sandboxed (contained) securely to avoid these problems, this is apparently not true.

Old Farts

FlatHub doesn't have the latest software, either. For example, Firefox is one full release version behind. This poses potential security concerns as vulnerabilities old software get fixed in new software releases. Though companies and organizations offer security patches to fix the vulnerabilities, a third party packager like FlatPak will probably be slow to apply them.

However, this is outside of the goal of FlatPak. The entire goal of the system is to allow for universal software and packages to be installed easily. For this to occur, they might be stuck using older versions. So it begs the question: Should a privacy minded individual even consider FlatPak or programs with similar goals?

Security Issue (un)Responsiveness

A couple years back, the developers of FlatPak considered CVE-2017-9780 a minor security issue- when in reality it was a full fledged local root exploit. What this means is any hacker who wanted to get root access a couple years back could just create a FlatPak app that contained the code to effectively set user id as root, and it would work. This allowed any hacker to distribute malicious software and get administrative access to Linux boxes running FlatPak. Their lack of concern is still shocking to this very day, and one could only hope that they have changed their attitude towards security.


FlatPak was only designed to be a universal software distribution tool. Even as such, this all poses a big question for whether or not Linux users should consider systems like FlatPak or Snap for installation of software... Since there's so many potential security concerns, is this worth using?

On top of this, there's already Linux Distributions such as Bedrock Linux that allow for installation of Linux software using multiple different package managers. This seems like a far more robust solution, but still isn't 100% of the way there yet.

So What Should I Do?

If you're okay with the security risks, continue to use FlatPak, Snap, or whatever universal packaging tool you use. But if you're not okay with them and you value your privacy, consider not using them or finding a solid alternative until the kinks get worked out.

References: https://github.com/flatpak/flatpak/releases/tag/0.8.7



Retro Computer

For those who remember their vintage Mac Classic or Commodore 64, they also remember how they were heavily constrained to the likes of 256 kilobytes of RAM. Even in these conditions, programmers still had the ability to engineer the same sorts of software we use today.

In this era from the 1970s to the 1980s, we saw several major innovations- the first computers, UNIX, the first graphical desktops, word processing software, printing, and internetworking of devices via ARPANET (which would later become the internet).

So why is there a lack of major innovation at such a rigorous speed anymore?

Stale Innovation

This may be a hard pill to swallow for some, but the increased availability that high-end hardware provides lowered the barrier of entry into computer programming, thus decreasing the quality of code. Due to this, overall competency in the average software developer declines. Naturally, this affects the importance of a “new” innovation- what's the point of rewriting code if the rewrite is bound to have worse quality?

On top of this, large companies, universities and defense contractors no longer fund major innovators. Let's use a modern-day example: The OpenBSD Foundation. They're one of the many organizations dedicated to furthering the UNIX source code, with an extreme focus on producing a system that has secure and sane defaults. Ironically, they were the inventors of OpenSSH and sudo (currently used in almost every Enterprise network running Linux or UNIX). So why aren't they recognized? It all boils down to a saying I learned from my grandfather: “Nobody likes change- even if it helps them.”

Convenience Over Simplicity

Wait- don't these mean the same thing? Actually, no.

This is how American Heritage Dictionary defines these two words: Simple- Having few parts or features; not complicated or elaborate. Convenient- Suited or favorable to one's comfort, purpose, or needs.

For ages, programmers pursued simplicity as a way to provide stable, high-quality code that would run on virtually anything- even a toaster if one were so inclined. This old school of thought still exists, but is largely frowned upon with modern day programming paradigms.

For example, rapid prototyping has brought programming languages like Python to the forefront due to the convenience they provide and the ease of implementation in them. However, it's nearly impossible to produce efficient programs that guarantee stability across a wide variety of different platforms, as Python isn't yet implemented on as many platforms as languages such as C.

The truly sad thing about this is how it all ties right back to my first point on how it reduces competence among programmers.

The Attack Of The Public Domain

How is one supposed to train up a new generation of programmers for the enterprise world if there's no quality code to work on? It's a paradox, as large enterprise companies like Microsoft, Apple, and more make use of Open Source and Public Domain source code but rarely contribute anything that could help further the development of Open Source. In recent news, Microsoft introduced “DirectX 12 for Linux”, but in reality they only made a way to access the Application Programming Interface (API) available to Linux users. No source code was disclosed and it was explicitly added solely for their Windows Subsystem for Linux. According to U.S. v. Microsoft (2001), the Department of Justice found an alarming statement for Microsoft's internal marketing strategy known as “EEE”– Embrace, Extend, Extinguish. Embrace the idea as if they support it, Extend support for the idea, then Extinguish it by rendering it obsolete. Google and Apple have been known to engage in similar practices.

Herein lies the paradox- there's a lack of new enterprise source code to look at without paying a significant amount of money for. Due to this, there's a lack of large-scale scientific research being conducted in computing that's available to the public.

Lack Of Attentiveness

It's all our fault here... If you're from the 1990s, you may remember “Windows Buyback Day”, when Linux users protested outside Microsoft's headquarters about being forced to pay for a Windows license they don't even use.

20 years later, such noble ideas haven't been forgotten- they've been ignored and thrown on the proverbial backburner by the rest of society.

The Good News

Moore's Law is slowly becoming rendered obsolete. For those who are unaware of what this entails, Gordon Moore created this “rule of thumb” in 1965 that computing devices would double in capability, exponentially, every year. This turned out to be true until recently where manufacturers are reaching the physical limits of what they can fit on a circuit board.

This means that we're limited in terms of performance and in order to continue to maintain Moore's Law, we will be forced to go back to the days of old, writing high-quality software while retaining a large degree of performance.


For those who haven't read my original post (located HERE, we will be picking up where we left off in the design and implementation of our very own cryptosystem by implementing a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG).

What's The Point Of This?

For any of our cryptographic functions to have any use whatsoever, we need a stream of random information we can feed our algorithms so we can properly perform hashing functions, symmetrical and asymmetrical encryption.

The “secret sauce” behind encryption is that it looks like random, garbled data or can pose as data belonging to something else.

Why Can't I Just Use The random() Function?

Sadly, the random() function, as implemented in many languages, is not Cryptographically Secure and is actually rather predictable based on a variety of factors, like CPU performance and timings.

In the same vein, CSPRNGs are also rather methodical due to the nature of the hardware and need thorough testing.

Cool, So What Are We Going to Do?

Since efficiency and using stable code is key to making everything work properly, we will want to utilize an already existing library. In our case, we'll use Duthomhas's CSPRNG, located here. This will give us an API to work with, without worrying about how we'll generate random numbers.

But How Do CSPRNGs Work???

Generally, a CSPRNG would gather entropy (randomness) through a variety of sources, for example the difference in microseconds between keystrokes or the noise of a transmission, and use fancy mathematics like the modulus operator and exponentiation to produce much, much more entropic data quickly.

However, since we're lazy (Guilty is Charged!!!), we don't want to spend weeks developing a Cryptographically Secure Pseudo-Random Number Generator, we want to work on encryption.

Adding The API

The sample source code explains the usage of the C headers by adding the code and then using the following code sample to generate pseudo-random numbers:

 #include <stdio.h>
 #include <duthomhas/csprng.h>

 int main()
   CSPRNG rng = csprng_create( rng ); // Constructor
   if (!rng)
     fprintf( stderr, "%s\n", "No CSPRNG! Fooey!" );
     return 1;

  long n = csprng_get_int( rng ); // Get an int

  double f;      // Get a double
  csprng_get( rng, &f, sizeof(f) );

  int xs[ 20 ];           // Get an array
  csprng_get( rng, xs, sizeof(xs) );

  void* p = malloc(20);     // et cetera
  csprng_get( rng, p, 20 );
  free( p );

  rng = csprng_destroy( rng );   // Destructor
  return 0;

This Code sample shows us that we can dynamically call csprng_get() to fill different data types with pseudo-random information. This will fit our needs immensely in a separate function, as such:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "duthomhas/csprng.h"

extern int csprng_get(CSPRNG, void* dest, unsigned long long size);
extern CSPRNG csprng_destroy(CSPRNG);

// Our implementation of the CSPRNG
void * randstuff(void * x) {
  CSPRNG rng = csprng_create( rng ); // create CSPRNG
  if (!rng) { 
    //if the CSPRNG fails to load
    fprintf( stderr, "%s\n", "No CSPRNG! Crap." );
    exit(1); //crash and return an error

  csprng_get(rng, &x, sizeof(x)); // use CSPRNG
  rng = csprng_destroy(rng); // destroy the CSPRNG

  return x;

// Main function
int main(void) {
  char rand[50]; //To be filled with random garbage

  strcpy(rand, randstuff(rand));

  return 0;

This sample of code sadly isn't enough to get the CSPRNG working, as there's a slight flaw in the API we were provided in the csprng.c file. To fix this we need to swap the line that says #include <duthomhas/csprng.h> with #include "duthomhas/csprng.h" and everything should compile.

Alright, So What Did You Do?

We took sample code, and modified it to suit our purposes. Of course, our program doesn't yet work 100% and we're getting segmentation faults. However, this is a great first step as we're now able to produce pseudo-randomness at will.

To be more precise, we created a function called randstuff() that allows us to produce pseudorandom binary data at will. On top of this, we made the functions take the void * data type, allowing us to pass any form of data that we please into the function. This is somewhat dangerous and we'll need to explicitly convert our data to use the function later down the road... However, it provides us with the facilities necessary to create random information necessary for encryption.

Finally, since all this is placed into a separate function, we can call it anywhere we need randomness.

Be sure to stick around for Part 3, where we implement a hashing function!


Enter your email to subscribe to updates.