为Mac生成特定于机器的密钥

Generate machine-specific key for Mac

本文关键字:机器 密钥 于机器 Mac      更新时间:2023-10-16

在Windows上,我们生成一个特定于PC的唯一密钥,用于将许可证绑定到PC。这是一个使用wxWidgets的C++应用程序,理论上与跨平台兼容,但尚未在Mac端进行维护。我们使用一些Win32特定的代码来生成密钥。。。我如何在Mac上做类似的事情?

深入了解whitelionV和blahdiblah的asnwers,我发现了这个有用的页面:

以编程方式访问系统序列号

#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
// Returns the serial number as a CFString. 
// It is the caller's responsibility to release the returned CFString when done with it.
void CopySerialNumber(CFStringRef *serialNumber)
{
    if (serialNumber != NULL) {
        *serialNumber = NULL;
        io_service_t    platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault,
                                                                         IOServiceMatching("IOPlatformExpertDevice"));
        if (platformExpert) {
            CFTypeRef serialNumberAsCFString = 
                IORegistryEntryCreateCFProperty(platformExpert,
                                                CFSTR(kIOPlatformSerialNumberKey),
                                                kCFAllocatorDefault, 0);
            if (serialNumberAsCFString) {
                *serialNumber = serialNumberAsCFString;
            }
            IOObjectRelease(platformExpert);
        }
    }
}

以编程方式访问内置MAC地址

#include <stdio.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IONetworkInterface.h>
#include <IOKit/network/IOEthernetController.h>
static kern_return_t FindEthernetInterfaces(io_iterator_t *matchingServices);
static kern_return_t GetMACAddress(io_iterator_t intfIterator, UInt8 *MACAddress, UInt8 bufferSize);
static kern_return_t FindEthernetInterfaces(io_iterator_t *matchingServices)
{
    kern_return_t           kernResult; 
    CFMutableDictionaryRef  matchingDict;
    CFMutableDictionaryRef  propertyMatchDict;
    matchingDict = IOServiceMatching(kIOEthernetInterfaceClass);
    if (NULL == matchingDict) {
        printf("IOServiceMatching returned a NULL dictionary.n");
    }
    else {
        propertyMatchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
                                                      &kCFTypeDictionaryKeyCallBacks,
                                                      &kCFTypeDictionaryValueCallBacks);
        if (NULL == propertyMatchDict) {
            printf("CFDictionaryCreateMutable returned a NULL dictionary.n");
        }
        else {
            CFDictionarySetValue(matchingDict, CFSTR(kIOPropertyMatchKey), propertyMatchDict);
            CFRelease(propertyMatchDict);
        }
    }
    kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, matchingServices);    
    if (KERN_SUCCESS != kernResult) {
        printf("IOServiceGetMatchingServices returned 0x%08xn", kernResult);
    }
    return kernResult;
}
static kern_return_t GetMACAddress(io_iterator_t intfIterator, UInt8 *MACAddress, UInt8 bufferSize)
{
    io_object_t     intfService;
    io_object_t     controllerService;
    kern_return_t   kernResult = KERN_FAILURE;
    if (bufferSize < kIOEthernetAddressSize) {
        return kernResult;
    }
    bzero(MACAddress, bufferSize);
    while ((intfService = IOIteratorNext(intfIterator)))
    {
        CFTypeRef   MACAddressAsCFData;        
        kernResult = IORegistryEntryGetParentEntry(intfService,
                                                   kIOServicePlane,
                                                   &controllerService);
        if (KERN_SUCCESS != kernResult) {
            printf("IORegistryEntryGetParentEntry returned 0x%08xn", kernResult);
        }
        else {
            MACAddressAsCFData = IORegistryEntryCreateCFProperty(controllerService,
                                                                 CFSTR(kIOMACAddress),
                                                                 kCFAllocatorDefault,
                                                                 0);
            if (MACAddressAsCFData) {
                CFShow(MACAddressAsCFData); // for display purposes only; output goes to stderr
                CFDataGetBytes(MACAddressAsCFData, CFRangeMake(0, kIOEthernetAddressSize), MACAddress);
                CFRelease(MACAddressAsCFData);
            }
            (void) IOObjectRelease(controllerService);
        }
        (void) IOObjectRelease(intfService);
    }
    return kernResult;
}
int main(int argc, char *argv[])
{
    kern_return_t   kernResult = KERN_SUCCESS;
    io_iterator_t   intfIterator;
    UInt8           MACAddress[kIOEthernetAddressSize];
    kernResult = FindEthernetInterfaces(&intfIterator);
    if (KERN_SUCCESS != kernResult) {
        printf("FindEthernetInterfaces returned 0x%08xn", kernResult);
    }
    else {
        kernResult = GetMACAddress(intfIterator, MACAddress, sizeof(MACAddress));
        if (KERN_SUCCESS != kernResult) {
            printf("GetMACAddress returned 0x%08xn", kernResult);
        }
        else {
            printf("This system's built-in MAC address is %02x:%02x:%02x:%02x:%02x:%02x.n",
                    MACAddress[0], MACAddress[1], MACAddress[2], MACAddress[3], MACAddress[4], MACAddress[5]);
        }
    }
    (void) IOObjectRelease(intfIterator);   // Release the iterator.
    return kernResult;
}

虽然MAC表面上可能更容易预测,但他们警告说:

Netbooting在具有多个内置系统的系统中引入了一个缺陷以太网端口。这些系统上的主要以太网端口是其连接到NetBoot服务器。这意味着搜索主端口可以返回内置MAC地址中的任一个取决于用于网络引导的端口。注意"内置"不包括位于扩展卡上的以太网端口。

我担心这可能意味着你不总是能得到同样的价值?

您只需调用system_profiler并查找"序列号"

/usr/sbin/system_profiler | grep "Serial Number (system)"

很可能有一种程序化的方式来获得相同的信息,但我不知道它是即时的。

要唯一识别任何机器,可以尝试使用MAC地址。这个过程虽然不琐碎,但相当简单。有很多跨平台的开源库。

事实上,你可以试试这个苹果开发的例子