Skip to content

Instantly share code, notes, and snippets.

@pklaus
Last active May 31, 2025 14:15
Show Gist options
  • Save pklaus/9638536 to your computer and use it in GitHub Desktop.
Save pklaus/9638536 to your computer and use it in GitHub Desktop.
Generating Random MAC Addresses with Python

The mini-tool has a CLI-Interface with the following options:

  • Unicast or Multicast? Default: Unicast
  • Locally Administered or Globally Unique? Default: Locally Administered
  • Prescribe specific OUI (overwrites the above two)

TODO

  • Add an option to generate a number of MACs without collisions.

Resources

#!/usr/bin/env python
import random
def random_bytes(num=6):
return [random.randrange(256) for _ in range(num)]
def generate_mac(uaa=False, multicast=False, oui=None, separator=':', byte_fmt='%02x'):
mac = random_bytes()
if oui:
if type(oui) == str:
oui = [int(chunk) for chunk in oui.split(separator)]
mac = oui + random_bytes(num=6-len(oui))
else:
if multicast:
mac[0] |= 1 # set bit 0
else:
mac[0] &= ~1 # clear bit 0
if uaa:
mac[0] &= ~(1 << 1) # clear bit 1
else:
mac[0] |= 1 << 1 # set bit 1
return separator.join(byte_fmt % b for b in mac)
def main():
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--uaa', action='store_true', help='generates a universally administered address (instead of LAA otherwise)')
parser.add_argument('--multicast', action='store_true', help='generates a multicast MAC (instead of unicast otherwise)')
parser.add_argument('--oui', help='enforces a specific organizationally unique identifier (like 00:60:2f for Cisco)')
parser.add_argument('--byte-fmt', default='%02x', help='The byte format. Set to %02X for uppercase hex formatting.')
parser.add_argument('--separator', default=':', help="The byte separator character. Defaults to ':'.")
args = parser.parse_args()
print(generate_mac(oui=args.oui, uaa=args.uaa, multicast=args.multicast, separator=args.separator, byte_fmt=args.byte_fmt))
if __name__ == '__main__':
main()
@2foil
Copy link

2foil commented Sep 28, 2020

Here is a more dense version 😆:

>>> random_mac = lambda : ":".join([f"{random.randint(0, 255):02x}" for _ in range(6)])

>>> random_mac()
'b8:de:1a:98:8f:ab'

>>> random_mac()
'e4:c4:3e:40:27:7b'

@jpramosi
Copy link

A non-random version for generating a MAC address from a string:

def generate_mac(text: str, multicast=False, universally_administered=False) -> str:
    from hashlib import sha256

    h = sha256(text.encode("utf-8")).digest()

    # https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast_(I/G_bit)
    # https://gist.github.com/pklaus/9638536
    bit = h[0]
    if multicast:
        bit |= 1  # set bit 0
    else:
        bit &= ~1  # clear bit 0
    if universally_administered:
        bit &= ~(1 << 1)  # clear bit 1
    else:
        bit |= 1 << 1  # set bit 1

    m0 = int.from_bytes([bit], "little")
    m1 = int.from_bytes([h[4]], "little")
    m2 = int.from_bytes([h[8]], "little")
    m3 = int.from_bytes([h[8]], "little")
    m4 = int.from_bytes([h[16]], "little")
    m5 = int.from_bytes([h[20]], "little")

    return f"{m0:02x}:{m1:02x}:{m2:02x}:{m3:02x}:{m4:02x}:{m5:02x}"

It might have a high hash collision rate, but it's still pretty useful to me. I use it to generate a MAC from a hostname to stop my router from delivering an old IP address from my recreated virtual machines.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment