- Undocumented Matlab - https://undocumentedmatlab.com -

Unique computer ID

Posted By Yair Altman On June 22, 2011 | 27 Comments

It is sometimes beneficial to have a unique identifier for the system on which we are currently running. For example, if you sell software, you may wish to verify that the computer is licensed or activated. A question [1] on CSSM today reminded me of this issue.
A trivial solution to this question is to use the built-in license function. Unfortunately, this does not work with a multi-system network/floating Matlab license, nor on deployed (compiled) systems.
While Matlab doesn’t have a built-in solution, we can use simple Java to access system information. There are several possible approaches. Here are several alternatives:

Windows SID

A Windows-specific approach is to return the Window Domain Controller’s SID [2] (Security ID). This is a unique identifier that changes with each computer/user. Java enables direct access to this identifier, and we can run this directly in Matlab:

>> sid = get(com.sun.security.auth.module.NTSystem,'DomainSID')
sid =
S-1-5-21-292311649-1610625687-3346456317

The exact same value can also be gotten directly from the Windows Registry:

% Note: scanning HKEY_-- USERS node names is better, but Matlab's winqueryreg() can't do that...
rootkey = 'HKEY_CURRENT_-- USER';
subkey = 'Software\Microsoft\Windows\CurrentVersion\Group Policy\GroupMembership';
count = winqueryreg(rootkey,subkey,'Count');
for idx = 0 : double(count)-1   % Note: double() is needed for Matlab 6 compatibility
    val = winqueryreg(rootkey,subkey,['Group' char('0'+idx)]);
    dashes = find(val=='-');
    if length(dashes) > 4,  sid = val(1:dashes(end)-1);  break;  end   % short ids are phoney
end

This later version, although less simple than the first alternative (Java-based approach) above, has the benefit of working on old Matlab releases such as R12 (6.0) where the Java approach fails. For this reason, my getsid utility [3] on the File Exchange uses the registry approach.

Other platforms

For non-Windows systems, both of the above approaches fail. For such platforms, we can use the Ethernet addresses of the computer’s network cards. This should be pretty unique for any practical effect:

sid = '';
ni = java.net.NetworkInterface.getNetworkInterfaces;
while ni.hasMoreElements
    addr = ni.nextElement.getHardwareAddress;
    if ~isempty(addr)
        addrStr = dec2hex(int16(addr)+128);
        sid = [sid, '.', reshape(addrStr,1,2*length(addr))];
    end
end
>> sid
sid =
.89ECC872C85C.8AFE928FEDB4.8262278A1CCA.899919B50FC9

This again uses Java (which unfortunately fails on R12 aka 6.0). The benefit is that it is entirely cross-platform, working wherever Matlab runs (including Windows), on any Matlab release that supports Java (I think R13 aka 6.5 should be the earliest).
Do you have another way to generate unique identifiers? If so, please share your experience in a comment [4].

Categories: Java, Low risk of breaking in future versions


27 Comments (Open | Close)

27 Comments To "Unique computer ID"

#1 Comment By Aurélien On June 23, 2011 @ 08:24

To limit the use of my softwares , I ask end-users the hostname of their machines or their login

For the login for example I use the following piece of code which is cross-platform

 
username = getenv('-- USERNAME'); 
if isempty(username)
    str = '!whoami'; 
    username = deblank(evalc(str));
end

Then I compare the username string with what I expect to get.

Aurélien

#2 Comment By Etienne Balmes On June 23, 2011 @ 13:36

You can use flexlm which always ships with MATLAB. Look for

!lmhostid -w

or:

!lmutil hostid

#3 Comment By Donn Shull On June 25, 2011 @ 14:12

Keep in mind Yair’s note that using the license manager does not work in deployed applications and may not give reliable results in MATLAB network served instances.
The form that you can use in a function is:

 
[status, value] = system('lmutil lmhostid -n')

#4 Comment By Jan Simon On June 26, 2011 @ 19:11

The harddisk ID and the creation date of the drive containing the OS are most likely unique.
Under Windows (XP, and newer?) POWERCFG replies a list, which contains the hardware IDs of all devices, which have been connected in the past:

!powercfg /DEVICEQUERY all_devices_verbose

It is hard to parse the replied list, e.g. to find a specific ID of the harddisk. But if you know a ID, e.g. the vendor ID of an USB-stick, it is easy to check if this string appears anywhere in the list.

Kind regards, Jan

#5 Comment By Nathan On July 14, 2011 @ 10:51

I don’t know how portable it is, but on Windows I use

getHostName(java.net.InetAddress.getLocalHost());

BTW, great site!
Nathan

#6 Comment By Yair Altman On July 14, 2011 @ 11:47

@Nathan – thanks for the compliment.

Your method is actually portable (cross-platform), since it is based on generic plain-vanilla Java. Unfortunately, I’m afraid it is not very unique since it just returns the computer name, which is non-unique by definition. By the way, on Windows you can use the following much simpler method to get this computer name:

getenv('computername')

#7 Comment By Jan Simon On July 20, 2011 @ 10:02

A small change for your Java approach:
Instead of

addrStr = dec2hex(int16(addr)+128);
sid = [sid, '.', reshape(addrStr,1,2*length(addr))];

this might be nicer:

sid = [sid, '.', sprintf('%.2X', typecast(addr, 'uint8'))];

#8 Comment By Yair Altman On July 20, 2011 @ 12:06

@Jan – I humbly stand corrected 🙂

#9 Comment By Matthias On September 20, 2011 @ 15:21

Hi,

for licensing I always use the MAC address of (one of) the network controllers. This address is absolutley unique for each network device worldwide.

The only way to access this I know of is using C/C++ compiled to a *.dll which can then be called from MATLAB using calllib

If interested I can post the code from the function to access the device.

And yes, this is a great site, learned a lot about Java in MATLAB and using lots of it.
Keep up Yair!

Matthias

#10 Comment By Yair Altman On September 20, 2011 @ 15:35

@Matthias – thanks 🙂 The code I posted above does exactly what you say, specifying the MAC addresses of all the computer’s network controllers. Please take a look – it’s actually quite simple and does not require any DLL, so it works on both Windows and non-Windows platforms.

#11 Comment By Jayveer On November 16, 2011 @ 01:24

switch computer('arch')
    case {'maci','maci64'}
        [~,a]=system('ifconfig');
        c=strfind(a,'en0');if ~isempty(c),a=a(c:end);end
        c=strfind(a,'en1');if ~isempty(c),a=a(1:c-1);end
        % find the mac address
        b=strfind(a,'ether');
        mac_add=a(1,b(1)+6:b(1)+22);
    case {'win32','win64'}
        [~,a]=system('getmac');b=strfind(a,'=');
        mac_add=a(b(end):b(end)+19);
    case {'glnx86','glnxa64'}
        [~,a]=system('ifconfig');b=strfind(a,'Ether');
        mac_add=a(1,b(1)+17:b(1)+33);
    otherwise,mac_add=[];
end

#12 Comment By Sami On March 1, 2013 @ 04:10

Thanks for the code, it’s very helpful, however in the {‘win32′,’win64’} i had to add “+1” to get the right MAC address. without the preceding “=” :

mac_add = a(b(end)+1:b(end)+19);

#13 Comment By Xiangrui Li On May 1, 2017 @ 23:06

Here is my practice for regexp. For all OS, always take the first mac_add pattern in the string output.

if ispc
    [~, a] = system('getmac');
    mac_add = regexp(a, '([0-9A-F]{2}-){5}[0-9A-F]{2}', 'match', 'once');
elseif isunix % OSX and Linux
    [~, a] = system('ifconfig');
    mac_add = regexp(a, '([0-9a-f]{2}:){5}[0-9a-f]{2}', 'match', 'once');
else
    mac_add = [];
end

#14 Comment By itrentals On April 30, 2012 @ 05:46

This is a really good guide, especially for those developing software (like you say) who are fearful that it will get copied.

#15 Comment By damayi On May 22, 2012 @ 20:43

SID is not an absolutely secure way to protect your license.
There are many software tool which can modify computer sid, such as NewSid software.

#16 Comment By Priti On February 20, 2013 @ 07:33

really helpful

#17 Comment By thomas On February 20, 2014 @ 08:50

How unique is SID? Can be there 2 identical SIDs in the world?

#18 Comment By Yair Altman On February 20, 2014 @ 09:23

Thomas – of course: any computer-generated id can be spoofed and hacked. You can never fully protect yourself from this. But if you’re looking at normal legal behavior, then it should be unique for any practical purposes.

#19 Comment By thomas On February 20, 2014 @ 09:26

@Yair – sorry, I meant not SID but that second method, where sid = .89ECC872C85C.8AFE928FEDB4.8262278A1CCA.899919B50FC9

Is it the MAC address? Because MAC address has 12 digits. My SID (this 48 digits long) is different from my MAC. Thanks.

#20 Comment By Yair Altman On February 20, 2014 @ 09:29

@Thomas – in this case you have 4 separate MAC addresses, from 4 separate network devices. Run the following in your Matlab command prompt to see the list (look at the “Physical Address” rows):

system('ipconfig /all')

This again is only unique if the user does not fool around with the MACs…

#21 Comment By thomas On February 20, 2014 @ 09:40

Yes, they are different, this is why i am confused a bit. The SID method gives .D6CDDF05903C.8888888600000000.8888888600000000.8888888600000000
IPconfig says:
50-E5-49-50-53-7A (this is the ethernet adapter)
00-00-00-00-00-00-00-E0
00-00-00-00-00-00-00-E0
00-00-00-00-00-00-00-E0

#22 Comment By Yair Altman On February 20, 2014 @ 09:56

@Thomas – it’s simply a different representation of the data. Here’s an implementation that should return more legible results:

ni = java.net.NetworkInterface.getNetworkInterfaces;
macStrs = {};
while ni.hasMoreElements
    macAddr = ni.nextElement.getHardwareAddress;
    if ~isempty(macAddr)
        macAddrStr = ['.' sprintf('%02X',mod(int16(macAddr),256))];
        macStrs{end+1} = macAddrStr; %#ok
    end
end
macStrs = sort(unique(macStrs));
sid = [macStrs{:}];

#23 Comment By thomas On February 20, 2014 @ 10:09

oh, i see.. the new method indeed gives .00000000000000E0.50E54950537A 🙂

thank you for your clarification. could you please delete my mac addresses, they were not intended to go public 🙂

#24 Comment By Yair Altman On February 20, 2014 @ 10:20

Next time don’t post on a public blog something that you don’t want to appear publicly!

#25 Comment By Jeff E Mandel MD MS On October 31, 2016 @ 15:41

Newer Macs have a hardware UUID. Note that Apple won’t allow a program that uses this in the App Store, but this probably won’t affect too many people writing deployed applications. Here is a little routine that accesses the system profile using the system_profiler command.

function profile = getMacProfile
% Retrieves all of the information from the OSX system profile and returns
% it in a structure, replacing spaces with underscores in the names and
% removing the attributes in parentheses.

[~,out]=system('system_profiler SPHardwareDataType');
theLines = splitlines(out);
for i = 1:length(theLines)
    if ~isempty(theLines{i})
        try
            c=strsplit(theLines{i},': ');
            if length(c) == 2
                d=strip(c{1});
                e=regexprep(d,' \(.*\)','');
                tag =strrep(e, ' ','_');
                profile.(tag) = c{2};
            end
        catch
            % In case Apple comes up with a new entry
            disp(theLines{i});
        end
    end
end

The UDID (unique device ID) is returned in profile.Hardware_UUID. This is probably more reliable than the MAC address of EN0.

#26 Comment By Mitchell On June 13, 2022 @ 03:58

Great post! I’m not very familiar with the network interfaces being referenced here, but it seems like the java-based cross-platform method concatenates all network interfaces. Does that mean that the SID returned by this method will change if a network interface is added or removed? Is it even possible to add or remove this type of network interface? Thanks!

#27 Comment By Yair Altman On June 13, 2022 @ 12:38

@Mitchell – in most cases the user wants a single string identifier for the computer, that uniquely identifies it with a distinct fingerprint that is different from any other computer. The network interface (MAC) addresses are reported by the operating system, and naturally change when you add or remove a network card or adapter. It is up to you to decide which of the MAC addresses should be included in the fingerprint: if you include all of them, it certainly makes your fingerprint unique, but might include addresses that change frequently (e.g. VPN, WiFi, or virtual interfaces). On the other hand, if you ignore too many interfaces, your SID might be easier to spoof. Different operating systems have different ways of handling network interface MAC addresses, and you should consider this as well. For example, Windows and Linux addresses are pretty stable, but MacOS constantly changes the addresses when you connect/disconnect a network interface. MacOS also changes the computer’s hostname automatically, without any user approval, which is a PITA. In short, having a stable, unique SID that is less prone to spoofing requires some thought. If you need my assistance with this, please contact me privately (altmany at gmail).


Article printed from Undocumented Matlab: https://undocumentedmatlab.com

URL to article: https://undocumentedmatlab.com/articles/unique-computer-id

URLs in this post:

[1] question: https://www.mathworks.com/matlabcentral/newsreader/view_thread/309603

[2] SID: http://en.wikipedia.org/wiki/Security_Identifier

[3] getsid utility: http://www.mathworks.com/matlabcentral/fileexchange/15718

[4] comment: http://undocumentedmatlab.com/blog/unique-computer-id/#respond

[5] Controlling callback re-entrancy : https://undocumentedmatlab.com/articles/controlling-callback-re-entrancy

[6] More undocumented timing features : https://undocumentedmatlab.com/articles/more-undocumented-timing-features

[7] Matlab compiler bug and workaround : https://undocumentedmatlab.com/articles/matlab-compiler-bug-and-workaround

[8] Types of undocumented Matlab aspects : https://undocumentedmatlab.com/articles/types-of-undocumented-matlab-aspects

[9] Matlab installation woes : https://undocumentedmatlab.com/articles/matlab-installation-woes

[10] Docking figures in compiled applications : https://undocumentedmatlab.com/articles/docking-figures-in-compiled-applications

Copyright © Yair Altman - Undocumented Matlab. All rights reserved.