Image of the glider from the Game of Life by John Conway
Skip to content

Cryptographically Secure Pseudorandom Locally Administered Unicast MAC Addresses

Recently, Apple released the ability for iPhone 5c and newer hardware to create a spoofed software MAC address for 2.4 GHz and 5 GHz wireless access points. The MAC address is locally administered, and a unicast address. This has sparked a small discussion in various forums about how to generate valid locally administered unicast MAC addresses. It is necessary that the MAC address is unicast, as many Cisco switches and routers will block non-unicast addresses. It's not necessary that the address be locally administered, however. This just takes the address out of the globally administered range, and the possibility of conflict with other devices connected to the same switch.

According to the IEEE, in order to create a unicast address, the least significant bit of the most significant byte must be 0. This means the most significant byte must be an even number, eliminating half of the 256 valid possibilities for the first byte. This leaves us with only 128 numbers. In order to be locally administered, the second least significant bit in the most significant byte of the address must be 1. This eliminates another 64 addresses from the total space for this byte. As such, there are only 64 possible values this address can start with. The rest of the bytes can be as random as you wish, giving you a total space of 70,368,744,177,664 addresses to choose from.

In the Unix shell, you can execute the following code, which should be fairly platform agnostic:

$ random_mac() {printf '%02x' $((0x$(od /dev/urandom -N1 -t x1 -An | cut -c 2-) & 0xFE | 0x02)); od /dev/urandom -N5 -t x1 -An | sed 's/ /:/g'}
$ random_mac

Here are 16 valid locally administered unicast MAC addresses generated from the shell:

$ for i in {1..16}; do random_mac; done

If you wanted to have a random mac address assigned to your wireless NIC every time you brought up your network interfaces on Debian or Ubuntu, you could write the following shell script, and place it in the "/etc/network/if-pre-up.d/" directory:

LLADDR=$(printf '%02x' $((0x$(od /dev/urandom -N1 -t x1 -An | cut -c 2-) & 0xFE | 0x02)); od /dev/urandom -N5 -t x1 -An | sed 's/ /:/g')
ip link set address $LLADDR wlan0

Make sure it's executable:

$ sudo chmod a+x /etc/network/if-pre-up.d/

{ 4 } Comments

  1. Stuart MacDonald | November 25, 2014 at 9:58 am | Permalink

    A couple minor corrections:
    random_mac() { printf '%02x' $((0x$(od /dev/urandom -N1 -t x1 -An | cut -c 2-) & 0xFE | 0x02)); od /dev/urandom -N5 -t x1 -An | sed 's/ /:/g'; }

  2. Aaron Toponce | December 1, 2014 at 2:33 pm | Permalink

    The only change I see that you have made, is adding the ';' at the end of the final statement before the function concludes. Is this correct?

  3. Stuart MacDonald | January 8, 2015 at 8:27 am | Permalink

    Correct. The missing semi-colon wasn't appreciated by bash [ GNU bash, version 4.2.37(1)-release (i686-pc-linux-gnu) ] on my Ubuntu 12.10 install. Sorry to mislead. 🙂

    Another thing...

    Some OUIs with the locally administered bit set have been allocated and thus need to be filtered from use as a pseudo-random. See the Public Listing at ; 02-60-8C is 3com for instance.

    Further, that's only the public listing. Consulting Wireshark's maintained list is probably more accurate:;a=tree and scroll down to 'manuf' or use this direct link;a=blob_plain;f=manuf;hb=HEAD

  4. Aaron Toponce | January 8, 2015 at 8:29 am | Permalink

    Perfect! Thanks for the feedback!

Post a Comment

Your email is never published nor shared.