为 Mac 生成特定于机器的密钥
Posted
技术标签:
【中文标题】为 Mac 生成特定于机器的密钥【英文标题】:Generate machine-specific key for Mac 【发布时间】:2012-02-25 16:25:23 【问题描述】:在 Windows 上,我们会生成一个特定于 PC 的唯一密钥,用于将许可证绑定到 PC。这是一个使用 wxWidgets 的 C++ 应用程序,理论上是跨平台兼容的,但在 Mac 端没有维护。我们使用一些特定于 Win32 的代码来生成密钥……我如何在 Mac 上做类似的事情?
【问题讨论】:
看看this question关于同样的问题。 【参考方案1】:深入研究 whitelionV 和 blahdiblah 的 asnwers,我发现了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;
虽然 MAC 从表面上看可能更可预测,但他们警告说:
Netbooting 给具有多个内置功能的系统带来了麻烦 以太网端口。这些系统上的主要以太网端口是 连接到 NetBoot 服务器。这意味着搜索 主端口可以返回任一内置 MAC 地址 取决于用于网络引导的端口。请注意,“内置” 不包括位于扩展卡上的以太网端口。
我担心这可能意味着您不会总是得到相同的值?
【讨论】:
【参考方案2】:您可以拨打system_profiler
并查找“序列号”
/usr/sbin/system_profiler | grep "Serial Number (system)"
很可能有一种程序化的方式来获取相同的信息,但我不知道它。
【讨论】:
【参考方案3】:要唯一标识任何机器,您可以尝试使用 MAC 地址。这个过程,虽然不是微不足道的,但它非常简单。有很多跨平台的开源库。
其实你可以试试这个 Apple dev example
【讨论】:
我听说当您在电源/电池电源之间切换或进入低功耗状态时,可见的 MAC 地址会发生变化? 每个网络设备都有一个识别MAC地址,只要你识别每个并且每次获取相同的MAC地址就不会出现问题(即总是抢eth0) 即使设备关闭?以上是关于为 Mac 生成特定于机器的密钥的主要内容,如果未能解决你的问题,请参考以下文章
需要生成特定于设备 ID 的访问密钥(Android 应用程序的 android_id)