Creating arbitrarily hard PBKDF2 keys with Bitcoin inspired difficulty factor

In recent years, the use of graphics processing units (GPUs) has led to the adoption of methods like PBKDF2 (Password-Based Key Derivation Function 2) for secure password storage. PBKDF2 is a key derivation function that is designed to be computationally expensive in order to slow down dictionary attacks and other brute force attacks on passwords. With the increase in processing power that GPUs provide, PBKDF2 has become a popular choice for password storage.

As the development of processing power continues to advance, it has become necessary to increase the number of iterations used in PBKDF2 in order to maintain a high level of security. With more iterations, it becomes even more difficult for an attacker to crack a password using brute force methods.

Recently, I had an idea. What if it were possible to run PBKDF2 arbitrarily long and print out points that match certain criteria? This could potentially provide an even higher level of security for password storage, as the number of iterations could be increased to levels that would make brute force attacks infeasible. It's an idea worth exploring and I'm excited to see what the future holds for PBKDF2 and other password security measures.

Bitcoin difficulty

One of the key features of the Bitcoin network is its use of difficulty to scale the hardness of block signing based on the number of computers that are currently mining. In other words, as more computers join the network and begin trying to solve the cryptographic puzzles required to add new blocks to the blockchain, the difficulty of these puzzles increases in order to maintain a consistent rate of block creation. This ensures that the network remains secure and resistant to attacks, even as the number of miners grows over time.

The basic idea behind this technique is fairly simple: by requiring that a certain number of zeros be added to the block hash, the complexity of the puzzle increases in powers of two. Every hash is essentially random, and modifying the hashed data by the tiniest bit results in a new hash. Every other hash ends in zero, and every other in one. With two zero bits, it's every 4th. To zero a full byte (8 bits) you already need 256 (2^8) tries. With three bytes, it's already close to 17 million.

Printing out PBKDF2 steps at deterministic points

Combining the two ideas is one way to deterministically create encryption keys of increasing difficulty:

Read post

How to calculate PBKDF2 HMAC SHA256 with Python, example code

Having just spent 4 hours trying to get a Python pseudocode version of PBKDF2 to match with hashlib.pbkdf2_hmac() output, I thought I'll post Yet Another Example how to do it. I thought I could just use hashlib.sha256 to calculate the steps, but turns out HMAC is not just a concatenation of password, salt and counter.

So, without further ado, here's a 256 bit key generation with password and salt:

import hashlib, hmac

def pbkdf2(pwd, salt, iter):
    h = hmac.new(pwd, digestmod=hashlib.sha256) # create HMAC using SHA256
    m = h.copy() # calculate PRF(Password, Salt+INT_32_BE(1))
    m.update(salt)
    m.update(b'\x00\x00\x00\x01')
    U = m.digest()
    T = bytes(U) # copy
    for _ in range(1, iter):
        m = h.copy() # new instance of hmac(key)
        m.update(U) # PRF(Password, U-1)
        U = m.digest()
        T = bytes(a^b for a,b in zip(U,T))
    return T

pwd = b'password'
salt = b'salt'

# both should print 120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b
print(pbkdf2(pwd, salt, 1).hex())
print(hashlib.pbkdf2_hmac('sha256', pwd, salt, 1).hex())

# both should print c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a
print(pbkdf2(pwd, salt, 4096).hex())
print(hashlib.pbkdf2_hmac('sha256', pwd, salt, 4096).hex())

Getting from pseudocode to actual working example was surprisingly hard, especially since most implementations on the web are on lower level languages, and Python results are mostly just using a library.

Simplifying the pseudo code further

If you want to avoid the new...update...digest and skip the hmac library altogether, the code becomes even simpler. HMAC is quite simple to implement with Python. Here's gethmac function hard-coded to SHA256 and an even shorter pbkdf2:

Read post

WebSocket Magic: Create a Simple Server and Client in Go and JavaScript

Title image, generated with Stable Diffusion

WebSocket is a protocol that allows for real-time, bidirectional communication between a client and a server. It is often used in web applications to enable features such as chat, live updates, and multiplayer games.

In this tutorial, I will show you how to create a minimalistic WebSocket server using Go and the nhooyr websocket library, and a JavaScript client to test it out. You will learn how to handle WebSocket connections, send and receive messages, and close the connection when necessary.

By the end of this tutorial, you will have a working WebSocket server and client that you can use as a starting point for your own WebSocket-based applications.

Setting up the project

You should first set up a simple "Hello world" go project, something along the lines of this tutorial. After you have a project going, let's install nhooyr.io/websocket WebSocket library (Go's own seems deprecated and Gorilla development has ceased some years ago):

$ go get nhooyr.io/websocket

The whole system will consist of main.go that will contain a simple net/http server that will:

  1. Serve a simple WebSocket echo server at /echo
  2. Serve static files from static subfolder – essentially other addresses including / will try content from there. We'll put index.html under that subfolder.

Basic webserver stuff:

func main() {
	address := "localhost:1234"
	http.HandleFunc("/echo", echoHandler)
	log.Printf("Starting server, go to http://%s/ to try it out!", address)
	http.Handle("/", http.FileServer(http.Dir("static")))
	err := http.ListenAndServe(address, nil)
	log.Fatal(err)
}

Now the echoHandler will do a few essential items:

  1. Upgrade the connection into a WebSocket one with websocket.Accept
  2. Log errors and defer connection close in case of errors
  3. Loop forever (or actually 10 minutes in this sample), reading messages from the socket and writing them back.

Note that I've used InsecureSkipVerify to accept connections from any origin, you might want to modify the code for a tighter policy:

Read post

Seeed Studio XIAO nRF52840 (Sense) test drive on Arduino

Seeed Studio XIAO nRF52840

I have to confess I have a thing for small prototyping boards, especially ones with Bluetooth or WLAN connectivity. So when I was offered the opportunity to get a couple of Seeed Studio's tiny Bluetooth devboards with Nordic's nRF52840 in them to try out, I jumped at the opportunity. So full disclosure, I did not buy these myself, but neither did I get any compensation, so what follows will be rather unbiased first impressions! I will cover:

  1. The basic specifications of the two units
  2. How to (re)program the device with Arduino
  3. Help to troubleshoot upload.tool.serial errors on Arduino
  4. Tips and notes on using the USB mass storage mode
  5. Initial summary

I'm interested in trying out the PDM microphone, accelerometer and BLE functionality later on, so check back for updates!

Basic specifications of the Seeed XIAO BLE nrf52840

The Seeed XIAO BLE units come in two varieties, both sharing quite beefy specs:

  • Bluetooth 5.0 with an onboard antenna
  • Nordic nRF52840, ARM Cortex-M4 32-bit processor with FPU, 64 MHz
  • Low power consumption and battery charging chip for untethered IoT use cases
  • Onboard 2 MB flash

Additionally, the Sense variant contains a PDM microphone and a 6-axis accelerometer. The units arrived from China quite quickly and came in sweet little Seeed plastic packages, pin headers included (not soldered in):

Seeed Studio XIAO nRF52840 and Sense

You can get both directly from Seeed, with very reasonable $9.90 and $15.99 price points. Nordic's chips are quite hard to source from AliExpress cheaply (yes I have looked :), so I'd consider both pretty much a bargain.

Board quality seems very good, pads are shiny and components well placed. The USB port is of modern USB-C variety, and the form factor is really small, just 20 x 17.5 mm or the size of a nickel x dime. and the thickness of a half dollar or so (U.S. readers, you're welcome!). The PCB is one-sided which makes it easy to embed in various configurations.

Outside differences of the basic model and Sense variant is one additional chip that contains the PDM microphone. I think the accelerometer is hidden inside the (seemingly FCC and CE compliant) shielding.

Seeed Studio XIAO nRF52840

There is also an absurdly tiny reset button on the opposite corner to the microphone pad (top left above) that is a bit tricky to press. I'd prefer a slightly larger one, but it beats shorting pins any day.

Classic blink test with Arduino

You can follow the instructions on Seeed Studio wiki to install the necessary development tools to build firmware for the device. Short version:

  1. Get Arduino
  2. In File > Preferences, add https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json to Additional Boards Manager URLs
  3. Go to Tools > Board > Boards Manager, search for "seeed nrf52" and install the two libraries.
  4. Now you can select your board and port.

Read post

CORS middleware for julienschmidt/httprouter with Golang

Just a small note / Gist type of thing for today: I got tired of adding w.Header().Set("Access-Control-Allow-Origin", "*") to every handler function in my small Golang web app. I'm using Julien Schmidt's excellent httprouter module for simple routing. Turns out the Basic Authentication example is quite simple to adjust for a set-and-forget type of httprouter.Handle middleware:

// https://github.com/julienschmidt/httprouter middleware to set CORS header
func MiddleCORS(next httprouter.Handle) httprouter.Handle {
	return func(w http.ResponseWriter,
    r *http.Request, ps httprouter.Params) {
		w.Header().Set("Access-Control-Allow-Origin", "*")
		next(w, r, ps)
	}
}

Using the middleware is simple, just wrap your normal handler function:

router.GET("/someurl", MiddleCORS(SomeURLFunc))

Or both the middleware and the function it takes implement httprouter.Handle, you can just chain multiple middleware with MiddleCORS(AnotherMiddleware(SomeURLFunc)).

Read post

Control Philips Hue Color (RGB) Lights With Python

I got tired of the fact, that Philips Hue application does not seem to have any easy way to set multiple lights to different colors (and possibly brightnesses) at once. Thankfully, there is a great "REST API" to query light and set status! Read on how to query your lights, set them, and do RBG to Philips Hue XY (or X, Y) colorspace conversion with Python!

Connecting and configuring your Philips Hue for API access

This is a prerequisite step. Find out your Hue Brige's IP and create a user (simple method of authentication). It's all covered in Get started.

Write down your IP and the username, and proceed to activate your user and test it according to instructions. Once you are done, you should be able to also open the lights list in your browser and see a lot of info:

https:///api//lights

Listing Your Connected Philips Hue Lights with Python

Alright, with the prerequisites done, let's do a simple test with Python, and query that same address parse the returned JSON, and pretty print it. You'll need Python 3.10+ for this:

import urllib.request
import ssl, json, pprint

context = ssl._create_unverified_context()

def get_json(url):
    """Do a HTTP GET request and return response parsed as JSON."""
    print(url)
    req = urllib.request.Request(url=url, method='GET')
    f = urllib.request.urlopen(req, context=context)
    print(f.status, f.reason)
    return json.loads(f.read())

# Replace these with your config
user = 'yourverylongusernamestring'
ip = '192.168.1.123'

data = get_json(f'https://{ip}/api/{user}/lights')

pp = pprint.PrettyPrinter(indent=4)   
pp.pprint(data)

for k in data: print(k, data[k]['name'])

Read post