Pythonで完全一意なハードウェアIDを取得する方法/コード例

Pythonで次のことを実現したい

  • ハードウェアを一意に識別したい
  • ハードウェアごとのIDを取得したい

完全に一意なUUIDを取得したいです。

それならライブラリなどでUUIDを生成すればという話ですが、
ここではハードウェア固有の物理的UUIDを取得したかったです。

その方法を色々模索してみました。
具体的方法とかコード例とかまとめます。

MACアドレスは固有だが変わるリスクがある

真っ先に思いつくのはMACアドレスです。

▼ MACアドレスとは何ぞやの解説

MACアドレス(Media Access Control address)は、ネットワークカード(パソコンやルータなどのネットワーク機器)に付いている番号です。全世界でMACアドレスが重複することはありません。(ただし、MACアドレスを変更するソフトウエアなどもあり、意図的に変更した場合は重複することがあります)パソコンの有線LANの他にも無線LANやスマートフォンにもMACアドレスが割り当てされています。

LANやインターネットでのイーサネット通信で利用されています。通信データのヘッダー部分に「送信先MACアドレス」と「送信元MACアドレス」を格納することで宛先や戻し先を確定しています。MACアドレスが無いと通信ができなくなります。

引用元 : https://www.cman.jp/network/term/mac/

重複することがない一意のアドレスのこと

パソコン・ルーターに付属してる番号のことです。

これを使うのは1つの手なのですが…
上記説明を見ても分かるように欠点があります。

  • ソフトウェア的に変更できてしまう
  • 意図的に重複させることができる
  • ハードウェアごとに真に一意ではない

だから一意なUUIDとしてMACアドレスは不向きです。

Macアドレスはpythonからも簡単に取得可能

Pythonからも簡単に取得できます。

▼ こんな数行のコードを書くだけ

例えば16進表記なら 2D-0E-4F-C6-B8-AD  のような16桁のアドレスが返ってきます。ipconfigコマンドだと物理アドレスなどと呼ばれます。

簡単に取得できるけど、さっき書いたように重複しないことは保証されません。というかソフト的に書き換えもできてしまいます。

だからOS固有のIDを探すことにしました。

WindowsでのハードウェアUUIDはwmicから取得可能

まずはWindowsでのハードウェアUUIDについて

これにはwmicコマンドを使います。

▼ このようなコマンドで取得可能

上記の 12345678-9ABC-0000-0000-000000000000  がWindowsのハードウェアIDです。この8桁-4桁-4桁-4桁-12桁はまさしくUUID v4 の形式ですね。(参考記事 : 重複しないIDを生成するNG方法と正しい方法)

これがWin環境でのハードウェアUUIDの取得方法

wmicコマンドは非推奨になったらしい…

あとで分かったけどwmicコマンドは非推奨です。

代わりにpowershellからハードウエアID取得できる模様

▼ 詳しくはこちらの記事とか参照

だからpowershell経由で取得することにしました。

LinuxでのハードウェアUUIDはmachine-idから取得可能

次にLinuxでのハードウェアUUIDについて

ググってみると /etc/machine-id から取得可能です。

▼ このような情報が出てきた

On modern machines with systemd: machine id is created by systemd-machine-id-setup. The location of machine id is documented - in freedesktop machine-id and man machine-id and machine id has a more standardized format - see RFC4122. Just:

cat /etc/machine-id

引用元 : https://stackoverflow.com/questions/10152762/best-way-to-get-machine-id-on-linux#answer-63148464

上記コマンドでハードウェアUUIDが手に入ります。

Linuxが生成したUUID v4が返ってくる模様です。

Windows/LinuxでハードウェアUUID取得のコード例

それでは具体的な取得コードを紹介。

このようなモジュールを作ってみました。

▼ hardware-id.py

▼ このような場合分け

  • Windowsの場合 : wmicコマンドからUUID取得
  • Linuxの場合 : machine-idからUUID取得
  • その他OSの場合 : MACアドレスがUUIDの代わり

色々突っこみどころがあるかもしれません。

結局OS(Win/Linux)が生成してるUUIDを取得してるだけなので、それなら「コード側でUUID生成すれば?」という感じも……

でもハードウェアが生成したUUID(=コード的に生成しなくても一意に識別できる)メリットがあるため、その点が利点だと考えます。