MatthewKing / DeviceId

A simple library providing functionality to generate a 'device ID' that can be used to uniquely identify a computer.
MIT License
722 stars 118 forks source link

Device ID is not unique and changing over time #67

Closed hey24sheep closed 1 year ago

hey24sheep commented 1 year ago

Hi, thank you for the package. I am facing an issue, I am generating the IDs in a "service worker" in Windows Service mode using the below command. I am using the base package DeviceId without any other extension packages.

 new DeviceIdBuilder()
        .AddUserName()
        .AddMachineName()
        .AddMacAddress(excludeWireless: true)
        .ToString();

It works great but in a span of few hours (on the same network & machine) the generated ID gets changed.

Isn't "Mac Address" is used as a seed to generate random string? Shouldn't that be unique always?

MatthewKing commented 1 year ago

In an ideal situation, it shouldn't be changing. It's not meant to change. But without knowing what's actually going on with your device, it's hard to say what's happening.

I will note that the out-of-the-box AddMacAddress implementation isn't ideal - it aggregates the physical addresses of all network interface types attached to the system, and some of these may change over time. I'd like to improve this, but doing so would break backwards compatibility for a lot of apps.

You can look at the code here, and perhaps make a custom component that filters NetworkInterfaceType to only types that you care about.

hey24sheep commented 1 year ago

Thank you for the quick response.

So, I have a laptop. I didn't change the "ISP" & "IP" during those 24 hours. I was using wireless and stayed on wireless during that time. I have a console app (POC) which uses your package to generate unique Id every 15 minutes and logs that Id in the database. So, it changed for 3 rows (1 hours 30 min) and then reverted back to original ID.

So it generated initially "xyz" ID then for 3 rows (for just 1 hour 30 min in total 24 hours) it generated "abc" but after that it reverted to "xyz" again.

Can we just take the physical NIC ethernet's MAC as seed, cuz it should stay same all the time, no? If we can implement it, how can I go about it.

hey24sheep commented 1 year ago

Just to add to my previous comment. My purpose is to find a unique hardware identifier actually so every time a system is connected to my DB or service, I can verify it based on a device Id that it is authorized for access.

MatthewKing commented 1 year ago

If you just want to use the physical ethernet adapters, you could do something like:

public class CustomMacAddressDeviceIdComponent : IDeviceIdComponent
{
    public string GetValue()
    {
        var values = NetworkInterface.GetAllNetworkInterfaces()
            .Where(x => x.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
            .Select(x => x.GetPhysicalAddress().ToString())
            .ToList();

        values.Sort();

        return values.Count > 0
            ? string.Join(",", values.ToArray())
            : null;
    }
}

and then use it as so:

var deviceId = new DeviceIdBuilder()
    .AddUserName()
    .AddMachineName()
    .AddComponent("MacAddress", new CustomMacAddressDeviceIdComponent())
    .ToString();

You can to adjust the NetworkInterfaceType filtering to match the exact types you want to use.

hey24sheep commented 1 year ago

Thank you, I will try it for a day or two and report back. Really appreciate your quick response.

hey24sheep commented 1 year ago

@MatthewKing I ran my windows service for ~36 hours straight and it generated 2 unique ids during these hours using the code that you gave me. I am so confused as to what is happening, if you could help me in this that would be great.

hey24sheep commented 1 year ago

I think this should fix my issue. I will update later on.

NetworkInterface
                .GetAllNetworkInterfaces()
                .Where(nic => nic.OperationalStatus == OperationalStatus.Up 
                        && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback
                        && nic.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
                .Select(nic => nic.GetPhysicalAddress().ToString())
                .ToList()
MatthewKing commented 1 year ago

Defintiely worth trying the updated code you've suggested. I hope it works for you.

Beyond that, it's entirely dependent on what's getting returned by NetworkInterface.GetAllNetworkInterfaces() which is part of the .NET base class library. Without seeing exactly what's going on with your environment, I don't know enough about it to say why it's changing what it returns.

Alternatively, you could try using different hardware components to generate your device ID instead?

hey24sheep commented 1 year ago

I have tweaked the logic a bit for our case, so for uniqueness now I save the MAC as comma separated directly and if any of the mac exists that means the computer is same during a verification call.

I think we can add a way of just getting the direct MACs instead of encoding them, if there is I would like to know.

hey24sheep commented 1 year ago

Hi, an update. As I told you that now I am saving MAC address in a comma separated to see what is going on.

I can see that randomly within 36 hour time frame a new MAC is registered along with previous ones.

So, previously I have 2 MACs getting registered "xyz, abc," now after few hours it adds new one "xyz, abc, zxc". This is the reason why the deviceId changes within 36 hour period as the seed changes.

Why seed/mac list changes ? This is because I turn on my "Bluetooth" for a few hours for meetings. During this time, it adds a new "MAC" (why it's filtered with Ethernet though? I am confused). If I turn off my Bluetooth, it will then return back to same 2 MAC, hence generating same unique id.

I hope this helps you as well in improving this library, thank you