Java和Mojave的强化运行时

12
我目前分发一个Java应用程序,使用macOS上的pkgbuild进行打包和签名
最近,苹果警告开发人员:
“在即将发布的macOS版本中,Gatekeeper将要求Apple对Developer ID签名软件进行公证。”
在阅读了公证文档之后,苹果警告开发人员
“您必须为应用程序启用强化运行时才能使其通过Apple的公证。”
其中详细介绍了如何在Xcode中切换这些设置。但是,那些没有使用Xcode开发的应用程序呢?Xamarin/Mono有一些来回讨论,但到目前为止,提交似乎集中在Mojave检测和C/C++上。那么Java应用程序或不分发任何C/C++/Objective-C编译代码的应用程序呢?项目如何获得“公证”,以便不会被未来的macOS更新所阻止?

可能相关: 如何在Xcode上为第三方CLI进行代码签名并启用强化运行时?


1
@superberry 谢谢!这怎么满足苹果的加固要求,似乎与软件编译方式有关?例如,如果我分发一个纯 Python 或 Ruby 应用程序(没有编译代码),那么该项目如何加固,以便苹果进行公证?您的信息似乎没有苹果公证所需的信息。请参见此处:https://help.apple.com/xcode/mac/current/en.lproj/Art/ca_enablehardenedruntime.png - tresf
1
我不使用Xcode,这个应用程序是Java。你的例子似乎只是将代码签名应用于可执行文件,而没有满足加固要求,对吗? - tresf
阅读了 https://twitter.com/rosyna/status/1004418504408252416 后,我使用 xcrun altool --eval-app --primary-bundle-id <com.mysite.myapp> -u <myappleid@mydomain> -f <path/to/myapp.pkg> 提交了我们的 .pkg 进行评估 -- 没有进行任何更改 -- 然后等待一分钟左右,它返回了 RequestUUID = a1b2c3d4e5-a1b2-a1b2-a1b2-a1b2c3d4e5f6,显然我需要使用 xcrun altool --eval-info a1b2c3d4e5-a1b2-a1b2-a1b2-a1b2c3d4e5f6 -u <myappleid@mydomain.com> 或通过电子邮件监控。请注意,开发者网站的用户协议已更改,因此在尝试之前我已登录并同意。 - tresf
1
我已通过电子邮件收到公证成功的消息... - SuperBerry
OpenJDK 邮件线程:http://mail.openjdk.java.net/pipermail/jdk-dev/2018-December/002460.html - ZhekaKozlov
显示剩余6条评论
3个回答

19

我回答这个问题是关于需要公证的Java项目。稍作修改,答案也适用于其他类型的项目(如Python、PowerShell、Node)。

注意:在发布本文时,苹果的公证命令允许以下过程工作。然而,随着公证和安全变得更加普遍和严格执行,苹果将改变和改进硬化要求和程序。请根据需要进行编辑、评论或重新回答。

代码签名

  • For a vanilla Java app (.pkg or .app containing scripts, jars), the notarization should pass. During notarization, Apple will extract the .jar and look for native libraries. If it finds any that aren't signed, it'll be rejected. If it doesn't, you're OK. Instructions for notarization using xcrun are further below.
  • For a Java app which contains native calls (e.g. JNI) to bundled libraries (.dylib, .jnilib) each bundled library must be signed using an "Application" (e.g. developerID_application.cer) certificate.

    • Certificates, Identifiers & Profiles, (Click "iOS, tvOS, watchOS" dropdown) macOS, Developer ID Application. (may also say "with Kext"). apple developer portal
    • If you don't have this certificate, you'll need to request one using a CSR. In my case, I originally only had a certificate for packaging installers (not codesigning). This process can get tricky especially if you use the same private key for two certificates. Use openssl via command line (instead of the Keychain Access) if you get stuck.
    • Once you obtain the certificate, signing each native library .dylib|.jnilib|.so|bin gets tricky. The general idea is to use codesign command against the native library so that it is signed as you, the developer. The syntax is:

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

      ... where P6DMU6694X is either the unique developer ID or the exact certificate Common Name (either will work).

    • For a .jar file, this can be particularly cumbersome as each package needs to be extracted, signed and then zipped back up.

公证

  • Once the native libraries are signed the package must be sent for notarization using xcrun.

    xcrun altool --eval-app --primary-bundle-id <bundle id> -u <iTunes Connect Account> -f <file path>

    Which may look something like this:

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

  • You will be prompted for your Apple Developer password (NOT the password you use to login to your Mac). Edit: Since dual-factor has been mandated, you'll need to create an app-specific password for this step!

  • After a few minutes, the xcrun command will return a unique ID that can be used to determine if the notarization was approved.

    RequestUUID = a1b2c3d4e5-a1b2-a1b2-a1b2-a1b2c3d4e5f6

  • Periodically check the status of this unique ID to see if it was approved or denied.
    xcrun altool --eval-info a1b2c3d4e5-a1b2-a1b2-a1b2-a1b2c3d4e5f6 -u john@domain.com
  • If denied, they won't directly tell you why, you have to parse the JSON response.

    LogFileURL: <a rel="noreferrer" href="https://osxapps-ssl.itunes.apple.com/itunes-assets/">https://osxapps-ssl.itunes.apple.com/itunes-assets/</a>...

  • Read the JSON and correct the problems identified. The JSON is minified, you may want to run it through a pretty-formatter. If there are no problems, your app has been notarized and is 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运行时与.app捆绑在一起,则需要采取其他步骤,使用--option=runtime标记分发为runtime,其中P6DMU6694X是您的签名ID:

codesign --force --deep --options=runtime -s "P6DMU6694X" /path/to/My.app

苹果现在要求双重身份验证和设置应用程序特定密码。这可以通过 https://appleid.apple.com,安全性,生成密码来完成。 - tresf
1
@tobihagemann建议更改,将--eval-app替换为--notarize-app,并将--eval-info替换为--notarization-info。我在Twitter上找到了这些原始命令,它们已经过时了吗?如果提供支持文档,我很乐意使用新命令进行更新。<3 - tresf
1
这个答案让我接近成功。在我的情况下,我使用packr.jar捆绑了我的java、jni和jre,生成了一个My.app可执行文件。在进行公证期间,我遇到了“可执行文件未启用强化运行时”的错误。我通过使用codesign '--options=runtime'对My.app进行签名来解决了这个问题。完整命令:codesign --force --deep --options=runtime -s "<My ID>" /path/to/My.app。一旦签名完成,我就能够使用pkgbuild创建安装程序,使用productsign签署安装程序,并使用altool成功地进行公证。 - NaderNader
为那些捆绑JVM的人添加了一个新的“运行时”部分。请注意,这与教程的其余部分有些不同,因为它假定.pkg而不是我认为应该是.app | .dmg可交付文件,但我已尽力提到了这一点。我自己也没有测试过,所以我必须相信NaderNader的话。 :D - tresf

5
除了tresf上面的答案之外,如果您的应用程序是沙箱化的(可能即使没有),那么当JVM加载时,强化运行时将会失败。要解决这个问题,您需要在签名时添加一些密钥。必要的授权条目如下,取自TAO ZHOU在此处的解决方案: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/>

你能否添加一些注释来解释每行与JVM的关系?例如,<key>com.apple.security.cs.allow-dyld-environment-variables</key>,这一行是由于特定用例,您的应用程序在运行时提供了DYLD_LIBRARY_PATH吗?如果是这样,请加上注释。<key>com.apple.security.cs.allow-jit</key>是由于非编译Java代码在运行时被解释吗?是什么用例触发了这个需求?对每个项目进行详细说明将不胜感激。 - tresf
我无法确定它们全部的作用,但我相信大多数都是为了让JVM执行JIT编译并写入可执行内存,这些操作通常被强化运行时所禁止。可能DYLD环境变量只有在基于脚本的启动器中才需要,但我不能确定。我们的应用程序没有对动态库路径进行任何运行时更改,因此我认为这是启用JVM启动过程所需的。供参考,在添加这些行之前,控制台错误为“vm_map_enter:curprot不能是write+execute。失败”。 - Sean Reilly
哦,我的天啊。谢谢!我试了各种方法,但这个是赢家。 - nevster
给定的链接已损坏。 - BrainStorm.exe
链接现在已经修复。很抱歉,在我们从Bitbucket迁移到Github时,它已经损坏了。 - Sean Reilly

1

这是一个简单的Shell脚本,可以对jar文件中的.so、.dylib和.jnilib文件进行代码签名。

使用方法:codesign_jar_script.sh filename.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

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