如何为 Mac OS X 应用程序签名?

18

我创建了一个 Mac OS X 应用程序,但是我不知道正确签名我的 Mac OS X 应用程序需要哪些步骤。 谢谢。

5个回答

30

1
我似乎不小心给你的答案点了个踩,现在除非该答案被编辑,否则我无法撤销它... - Johan Kaving

8
首先,您需要一个完全功能的(因此需要付费)Apple开发者账户。 然后,您可以按照以下信息操作:https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Introduction/Introduction.html 以上链接是全局过程,但有一个具体主题在以下网址上清晰地说明了如何进行:https://developer.apple.com/library/archive/documentation/Security/Conceptual/CodeSigningGuide/Procedures/Procedures.html#//apple_ref/doc/uid/TP40005929-CH4-SW2

7

使用Qt

macdeployqt APP_NAME.app -codesign="Developer ID Application: YOUR NAME (ID_NUMBERS)"

否则
codesign --force --verify --verbose --sign "Developer ID Application: YOUR NAME (ID_NUMBERS)" APP_NAME.app

你还需要使用类似这样的方式对每个框架和dylib文件进行签名,以便将其加入到包中。
codesign --force --verify --verbose --sign "Developer ID Application: YOUR NAME (ID_NUMBERS)" APP_NAME.app/Contents/Frameworks/QtCore.framework/Versions/5/QtCore
codesign --force --verify --verbose --sign "Developer ID Application: YOUR NAME (ID_NUMBERS)" APP_NAME.app/Contents/Plugins/bearer/libqcorewlanbearer.dylib

你能举个这些变量的例子吗?ID_NUMBERS是什么意思,括号应该在那里吗? - vanilla

1

在这方面,有很好的苹果文档。前往开发者供应部分,那里有一份很好的入门指南,可以让您快速上手。


4
如果您至少放置一个链接以帮助他人,我会为您投赞成票。 - marcc
2
我无法放置链接,因为我是在工作中回答,苹果开发者网站被封锁了。 - gnuchu

-1

当您签署应用程序时,该应用程序中的所有可执行文件都需要签名,否则,公证将失败。

我编写了这个节点代码,它将递归查找应用程序中的所有可执行文件并对其进行签名。

#!/usr/bin/env node
// 5.14

const APP = "./yourAppName.app";
const IDENTITY = "your_signature_";

/****************************************************************************/
const items = [];
console.log("### finding things to sign");

const fs = require('fs');
const child_process = require('child_process');
const recursive = require("recursive-readdir");
const listdirs = require('listdirs');


const folder = `./nwjs.app`;

const main = async()=>{

    const allFiles = await recursive(folder);
    const exeFiles = allFiles.filter((x)=>{
        try {
            fs.accessSync(x, fs.constants.X_OK)
            return true;    
        } catch (error) {
            return false
        }
        
    })
    console.log("all files", exeFiles); 
    items.push(...exeFiles)

    const myListDir = (folder)=>{
        return new Promise((resolve, reject) => {
            listdirs(folder, function callback(err, list){
                if(err){
                  return reject(err)
                }
                else {
                  return resolve(list)
                }
            });         
        });
    }

    const allFolders = await myListDir(folder);
    const appFolders = allFolders.filter((x)=>{
        return x.endsWith(".app")
    })

   console.log("all Folders", appFolders); 
   items.push(...appFolders)


    /****************************************************************************/

    console.log("");
    console.log("### signing");

    function exec(cmd) {
        console.log(cmd);
        const result = child_process.spawnSync(cmd, {shell: true, stdio: 'inherit'});
        if (result.status !== 0) {
            console.log(`Command failed with status ${result.status}`);
            if (result.error) console.log(result.error);
            //process.exit(1);
        }
    }

    items.push(`${APP}/Contents/MacOS/nwjs`)
    
    
    for (const item of items) {
        try {
            exec(`codesign --verbose --force --deep --strict --options runtime --timestamp --sign "${IDENTITY}" --entitlements neededToRun.entitlements "${item}"`);    
        } catch (error) {
            console.log(error);
        }
        
    }

    exec(`codesign --verbose --force --deep --strict --options runtime --timestamp --sign "${IDENTITY}" --entitlements neededToRun.entitlements "${APP}"`);

    /****************************************************************************/

    console.log("");
    console.log("### verifying signature");

    exec(`codesign --verify -vvvv "${APP}"`);
}

main();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接