为 Mac 生成机器特定的密钥

发布于 2025-01-02 14:14:38 字数 142 浏览 2 评论 0原文

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

On Windows, we generate a PC-specific unique key used to tie a license to a PC. It's a C++ app using wxWidgets, which is theoretically cross-platform compatible but not been maintained on the Mac side. We use some Win32-specific code for generating a key... how might I do something comparable on the Mac?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小苏打饼 2025-01-09 14:14:38

进一步研究whitelionV和blahdiblah的asnwers,我发现这个有用的页面:

<一href="https://developer.apple.com/library/mac/technotes/tn1103/_index.html#//apple_ref/doc/uid/DTS10002943-CH1-TNTAG3" rel="nofollow">访问系统序列号以编程方式

#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%08x\n", 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%08x\n", 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%08x\n", kernResult);
    }
    else {
        kernResult = GetMACAddress(intfIterator, MACAddress, sizeof(MACAddress));

        if (KERN_SUCCESS != kernResult) {
            printf("GetMACAddress returned 0x%08x\n", 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 表面上看起来可能更可预测,但他们警告说

网络启动给具有多个内置功能的系统带来了麻烦
以太网端口。这些系统上的主要以太网端口是
连接到 NetBoot 服务器。这意味着搜索
主端口可能会返回任一内置 MAC 地址
取决于用于网络启动的端口。注意“内置”
不包括扩展卡上的以太网端口。

我担心这可能意味着您并不总是能得到相同的价值?

Looking more into whitelionV and blahdiblah's asnwers, I found this useful page:

Accessing the system serial number programmatically

#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);
        }
    }
}

Accessing the built-in MAC address programmatically

#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%08x\n", 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%08x\n", 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%08x\n", kernResult);
    }
    else {
        kernResult = GetMACAddress(intfIterator, MACAddress, sizeof(MACAddress));

        if (KERN_SUCCESS != kernResult) {
            printf("GetMACAddress returned 0x%08x\n", 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;
}

While MAC is on the face of it probably preferable as being more predictable, they warn that:

Netbooting introduces a wrinkle with systems with multiple built-in
Ethernet ports. The primary Ethernet port on these systems is the one
that is connected to the NetBoot server. This means that a search for
the primary port may return either of the built-in MAC addresses
depending on which port was used for netbooting. Note that "built-in"
does not include Ethernet ports that reside on an expansion card.

It concerns me this might mean you don't always get the same value back?

怎言笑 2025-01-09 14:14:38

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

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

很可能有一种编程方式来获取相同的信息,但我不知道。

You could just call system_profiler and look for "Serial Number"

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

There might well be a programmatic way to get the same information, but I don't know it offhand.

辞别 2025-01-09 14:14:38

要唯一标识任何计算机,您可以尝试使用 MAC 地址。这个过程虽然并不微不足道,但非常简单。有很多跨平台的开源库。

事实上,您可以尝试这个 Apple 开发 示例

To uniquely identify any machine you could try to use the MAC address. The process, although not trivial, its quite simple. There are a lot of cross platform open source libraries.

In fact you could try this Apple dev example

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文