Сгенерируйте машинный ключ для Mac - PullRequest
2 голосов
/ 03 февраля 2012

В Windows мы генерируем уникальный ключ для ПК, используемый для привязки лицензии к ПК. Это приложение C ++, использующее wxWidgets, которое теоретически кроссплатформенно совместимо, но не поддерживается на стороне Mac. Мы используем некоторый специфичный для Win32 код для генерации ключа ... как я могу сделать что-то сопоставимое на Mac?

Ответы [ 3 ]

2 голосов
/ 04 февраля 2012

Глядя больше на whitelionV и ответы бладиблах, я нашел эту полезную страницу :

Программный доступ к серийному номеру системы

#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, вероятно, предпочтительнее, поскольку он более предсказуемый, они предупреждают, что:

Netbooting вводит морщины с системами с несколькими встроенными Порты Ethernet. Основной порт Ethernet в этих системах это связано с сервером NetBoot. Это означает, что поиск основной порт может возвращать любой из встроенных MAC-адресов в зависимости от того, какой порт был использован для сетевой загрузки. Обратите внимание, что «встроенный» не включает порты Ethernet, которые находятся на плате расширения.

Меня беспокоит, это может означать, что вы не всегда получаете одно и то же значение обратно?

1 голос
/ 03 февраля 2012

Вы можете просто позвонить system_profiler и посмотреть "Серийный номер"

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

Возможно, есть программный способ получить ту же информацию, но я не знаю ее случайно.

1 голос
/ 03 февраля 2012

Чтобы однозначно идентифицировать любую машину, вы можете попытаться использовать MAC-адрес.Процесс, хотя и не тривиальный, но довольно простой.Существует множество кроссплатформенных библиотек с открытым исходным кодом.

На самом деле вы можете попробовать этот пример Apple dev

...