Как получить кодовое имя сертификата приложения

Мне сложно найти ответ на мои вопросы, касающиеся кодов.

У нас есть приложение для Mac OS, написанное под Cocoa. Наконец, мы выполнили нашу кодовую регистрацию, но я хотел бы добавить дополнительную проверку безопасности - внутри самого исполняемого файла.

Моя идея - проверить отпечаток сертификата, с которым текущий исполняемый файл подписан, когда он запущен. Если он отсутствует или недействителен (проверен на жестко запрограммированный хэш в приложении) - мы закрываем его.

До сих пор я не смог получить сертификат, используемый для кодирования исполняемого файла программно и проверки его данных.

Кто-нибудь знает, как это сделать?

Спасибо, очень много! Мартин К.

Ответ 1

Спасибо другу!

Мне удалось сделать это для 10.6 с новой функциональностью, но проблема в том, что я нацелен на 10.5 и 10.6, по крайней мере, до тех пор, пока не пройдет некоторое время.

Мне нужно добавить еще немного времени в libsecurity_codesigning, так что это может быть выполнено и для 10.5.

Но для людей, которые ищут готовые решения здесь, вот что я в итоге:

SecStaticCodeRef ref = NULL;

NSURL * url = [NSURL URLWithString:[[NSBundle mainBundle] executablePath]]; 

OSStatus status;

// obtain the cert info from the executable
status = SecStaticCodeCreateWithPath((CFURLRef)url, kSecCSDefaultFlags, &ref);

if (ref == NULL) exit(EXIT_STATUS_ON_BAD_CODE_SIGNATURE);
if (status != noErr) exit(EXIT_STATUS_ON_BAD_CODE_SIGNATURE);

SecRequirementRef req = NULL;

// this is the public SHA1 fingerprint of the cert match string
NSString * reqStr = [NSString stringWithFormat:@"%@ %@ = %@%@%@",
    @"certificate",
    @"leaf",
    @"H\"66875745923F01",
    @"F122B387B0F943",
    @"X7D981183151\""
    ];

// create the requirement to check against
status = SecRequirementCreateWithString((CFStringRef)reqStr, kSecCSDefaultFlags, &req);

if (status != noErr) exit(EXIT_STATUS_ON_BAD_CODE_SIGNATURE);
if (req == NULL) exit(EXIT_STATUS_ON_BAD_CODE_SIGNATURE);

status = SecStaticCodeCheckValidity(ref, kSecCSCheckAllArchitectures, req);

if (status != noErr) exit(EXIT_STATUS_ON_BAD_CODE_SIGNATURE);

CFRelease(ref);
CFRelease(req);

LogDebug(@"Code signature was checked and it seems OK");

Ответ 2

Если вы используете таргетинг 10.6+, вы можете использовать функции подписи кода в структуре безопасности (документация), в частности SecCodeCheckValidity. В противном случае исходный код системы подписи кода находится в libsecurity_codesigning.

Поскольку вы используете подпись кода для аутентификации своего кода, вы также должны проверить указанное требование с помощью SecCodeCopyDesignatedRequirement.

Ответ 3

В ответе выше, вторая строка должна быть:

NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] executablePath]]; 

Если вы используете принятый ответ (содержащий [NSURL URLWithString:...]), то url будет отсутствовать, если ваше имя приложения имеет пробел в нем или если -executablePath возвращает путь, содержащий определенные символы. Это, конечно же, приведет к сбою всей проверки.

(Я сделал это вторым ответом, а не комментарием для подсветки синтаксиса.)