12

我目前分发一个 Java 应用程序,在 macOS 上使用打包和签名。pkgbuild

最近,Apple 警告开发者:

“在即将发布的 macOS 中,Gatekeeper 将要求开发者 ID 签名的软件经过 Apple公证。”

在阅读公证文档后,苹果警告开发人员

“您必须为您的应用启用强化运行时才能获得 Apple 的公证。”

其中详细介绍了如何在 Xcode 中切换这些设置。但是那些不是用 Xcode 开发的应用程序呢? Xamarin/Mono 有一些关于他们如何解决这个问题的来回,但到目前为止的提交似乎集中在 Mojave 检测和 C/C++ 上。Java 应用程序或不分发任何 C/C++/Objective-C 编译代码的应用程序呢?一个项目如何得到“公证”,这样它就不会被未来的 macOS 更新阻止?

可能相关:如何在 Xcode 上为第 3 方 CLI 进行代码设计和启用强化运行时?

4

3 回答 3

18

我正在就需要公证的 Java 项目回答这个问题。稍作修改,答案也应该适用于其他类型的项目(python、powershell、node)。

注意:在发布此内容时,Apple 的公证命令允许以下程序工作,但是随着公证和安全变得更加普遍和更严格地执行,Apple 将不可避免地更改和改进强化要求和程序。请根据需要编辑、评论或重新回答。

代码签名

  • 对于普通 Java 应用程序(.pkg.app包含脚本、jar),公证应该通过。在公证期间,Apple提取.jar并查找原生库。如果它发现任何未签名的,它将被拒绝。如果没有,你就没事。公证使用说明xcrun如下。
  • 对于包含对捆绑库 ( .dylib, .jnilib) 的本机调用 (例如 JNI) 的 Java 应用程序,每个捆绑库必须使用“应用程序”(例如developerID_application.cer) 证书进行签名。

    • 证书标识符和配置文件,(单击“iOS、tvOS、watchOS”下拉菜单)macOS开发人员 ID 应用程序。(也可以说“与 Kext”)。 苹果开发者门户
    • 如果您没有此证书,则需要使用 CSR 申请。就我而言,我最初只有包装安装程序的证书(不是代码签名)。这个过程可能会变得很棘手,特别是如果您对两个证书使用相同的私钥。如果遇到困难,请通过命令行(而不是 )使用opensslKeychain Access
    • 获得证书后,对每个本机库进行签名.dylib|.jnilib|.so|bin 就会变得棘手。一般的想法是codesign对本机库使用命令,以便以您(开发人员)的身份对其进行签名。语法是:

      xargs codesign -s "P6DMU6694X" -v dependency.dylib

      ...P6DMU6694X唯一的开发人员 ID 或确切的证书公用名在哪里(两者都可以)。

    • 对于.jar文件,这可能特别麻烦,因为每个包都需要提取、签名然后压缩备份。

公证

  • 一旦对原生库进行了签名,就必须使用xcrun.

    xcrun altool --eval-app --primary-bundle-id <bundle id> -u <iTunes Connect Account> -f <文件路径>

    这可能看起来像这样:

    xcrun altool --eval-app --primary-bundle-id com.domain.appname -u john@domain.com -f appname.pkg

  • 系统将提示您输入 Apple Developer 密码(不是您用于登录 Mac 的密码)。 编辑:由于双重因素是强制性的,因此您需要为此步骤创建一个应用程序专用密码!

  • 几分钟后,该xcrun命令将返回一个唯一 ID,可用于确定公证是否被批准。

    RequestUUID = a1b2c3d4e5-a1b2-a1b2-a1b2-a1b2c3d4e5f6

  • 定期检查此唯一 ID 的状态以查看它是被批准还是被拒绝。
    xcrun altool --eval-info a1b2c3d4e5-a1b2-a1b2-a1b2-a1b2c3d4e5f6 -u john@domain.com
  • 如果被拒绝,他们不会直接告诉你原因,你必须解析 JSON 响应。

    LogFileURL: https://osxapps-ssl.itunes.apple.com/itunes-assets/...

  • 阅读 JSON 并更正已识别的问题。JSON 已缩小,您可能希望通过漂亮的格式化程序运行它。如果没有问题,您的应用程序已经过公证并且是Ready for distribution.

    
    {
      "logFormatVersion": 1,
      "jobId": "a1b2c3d4e5-a1b2-a1b2-a1b2-a1b2c3d4e5f6",
      "status": "Accepted",
      "statusSummary": "Ready for distribution",
      "statusCode": 0,
      "archiveFilename": "appname.pkg",
      "uploadDate": "2018-10-26T05:41:12Z",
      "sha256": "e2350bda66...",
      "issues" null
    }
    

装订

最后,装订构建将确保即使网络连接不可用,包也是可信的。

(apple.com) 您还应该使用订书机工具将票据附加到您的软件,以便将来的发行版包含票据。这确保即使网络连接不可用,Gatekeeper 也能找到票证。要将票证附加到您的应用程序,请使用订书机工具:

xcrun stapler staple appname.pkg

运行

@NaderNader 提供的附加解决方案,如果将 Java 运行时与 a 捆绑在一起.app,则需要额外的步骤来使用标志将分发标记为 a runtime--option=runtimeP6DMU6694X的签名 ID 在哪里:

codesign --force --deep --options=runtime -s "P6DMU6694X" /path/to/My.app
于 2018-11-28T21:00:37.867 回答
5

除了上述 tresf 的回答之外,如果您的应用程序是沙盒化的(甚至可能不是沙盒化的),那么在加载 JVM 时强化的运行时将失败。要解决此问题,您需要在签名时为您的权利添加一些密钥。必要的权利条目如下,复制自陶舟的解决方案: https ://github.com/TheInfiniteKind/appbundler/issues/39

<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
于 2019-04-16T21:40:52.140 回答
1

这是一个简单的 shell 脚本,它将在 jar 文件中对 .so、.dylib 和 .jnilib 进行代码签名

用法: codesign_jar_script.sh 文件名.jar

jar tf $1 | grep '\.so\|\.dylib\|\.jnilib'  > filelist.txt

IDENTITY="your_signing_identity"

echo $IDENTITY

while read f
do
    jar xf $1 $f
    codesign --force -s "$IDENTITY" -v $f
    jar uf $1 $f
    rm -rf $f
done < filelist.txt
于 2020-08-29T13:39:49.657 回答