为MacOS Catalina公证现有Java应用程序

8
我为MacOS分发一个Java应用程序,它经过开发者签名但未经过公证。由于文档非常偏向使用我不使用的Xcode创建应用程序,因此我不太确定从哪里开始,但我只想找到最简单的方法来公证我的应用程序,然后继续进行。
阅读文档时,我已经有了一些顾虑:
  • I am currently using Java 8, is it possible to notarize a Java 8 app or do I need to move to Java 11. I would rather not move to Java 11 because it would cause problem on some other platforms I support.

  • My dev Mac machine is an old MacBook Pro, and as such cannot be updated past OSX El Capitan 10.11.6, can I notarize with this machine or not? I do have a more recent machine but it is not setup for development and I have some concerns about transferring the Developer Id certificates to it because setting this up was problematic in first place.

  • I use the AppBundler fork https://github.com/TheInfiniteKind/appbundler/ to package my app

  • This is called by an ant script build file that does the signing etc, we eventually create a dmg using dmgCanvas

  • I post the ant script below, hoping someone can start me of with the basic steps

    #!/bin/bash
    #set -x
    
    cd /Users/paul/code/jthink/songkong/src/main/scripts
    hiutil -C  -fapplehelpbook/SongKongHelp/SongKongHelp.helpindex applehelpbook/SongKongHelp/
    cd /Users/paul/code/jthink/songkong
    rm -fr /Applications/SongKong.app
    mvn clean
    mvn -DskipTests=true install
    rm -fr target/songkong-6.6
    unzip target/songkong-6.6-distribution.zip -d target
    ant
    sudo cp -r target/songkong-6.6/applehelpbook/SongKongHelp /Applications/SongKong.app/Contents/Resources
    rm /Applications/SongKong.app/Contents/PlugIns/jdk1.8.0_192.jdk/Contents/MacOS/libjli.dylib
    cp /Applications/SongKong.app/Contents/PlugIns/jdk1.8.0_192.jdk/Contents/Home/jre/lib/jli/libjli.dylib /Applications/SongKong.app/Contents/PlugIns/jdk1.8.0_192.jdk/Contents/MacOS
    export CODESIGN_ALLOCATE="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate"
    
    /usr/bin/codesign --sign "Developer ID Application: P Taylor" --force --deep --verbose /Applications/SongKong.app
    /usr/bin/codesign --verify --deep  --verbose /Applications/SongKong.app
    
    cd /Users/paul/code/jthink/SongKong
    /usr/local/bin/dmgcanvas /Users/paul/code/jthink/SongKong/dmgCanvas_songkong.dmgCanvas /Users/paul/songkong-osx.dmg -v SongKong
    
4个回答

8

编辑于2020年12月2日 - 由于苹果逐渐收紧了审核要求,因此进行公证的要求发生了很多变化。从2月3日开始,他们似乎已经进入了最后阶段,这意味着您的应用程序必须满足更高的要求,包括使用针对最新SDK构建的JRE,并具有"加强运行时"支持。

所以我把旧的讨论大部分都去掉了。

我的第一个问题是设置 - 您需要一个带有Apple ID的活动开发人员计划帐户(这很容易),但是然后,当您按照说明添加密码到钥匙串时,请使用应用程序特定密码。您还需要为Apple ID帐户启用双重身份验证。

一旦您弄清楚了命令行调用,就很容易在构建脚本中自动化。我使用jpackage创建应用程序和DMG,但要注意 - 目前其签署应用程序的方法不起作用

至于脚本编写方面,这就是我为符合公证要求对应用程序进行代码签名的操作(假设.app已经创建):

% security unlock-keychain -p passwordhere codesigning.keychain
% find my-app.app -type f \
  -not -path "*/Contents/runtime/*" \
  -not -path "*/Contents/MacOS/my-app" \
  -not -path "*libapplauncher.dylib" \
  -exec codesign --timestamp --entitlements /tmp/bliss.entitlements -s "XXX" --prefix com.myapp. --options runtime -v --keychain /path/to/codesigning.keychain {} \;

% find my-app.app/Contents/runtime -type f \
  -not -path "*/legal/*" \
  -not -path "*/man/*" \
  -exec codesign -f --timestamp --entitlements /tmp/bliss.entitlements -s "XXX" --prefix com.myapp. --options runtime -v --keychain /path/to/codesigning.keychain {} \;

% codesign -f --timestamp --entitlements /tmp/bliss.entitlements -s "XXX" --prefix com.myapp. --options runtime -v --keychain /path/to/codesigning.keychain my-app.app/Contents/runtime

% codesign -f --timestamp --entitlements /tmp/bliss.entitlements -s "XXX" --prefix com.myapp. --options runtime -v --keychain /path/to/codesigning.keychain my-app.app

应该设置以下权限:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <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/>
</dict>
</plist>

所有测试都通过:

% codesign -vvv --deep --strict my-app.app/Contents/runtime 
my-app.app/Contents/runtime: valid on disk
my-app.app/Contents/runtime: satisfies its Designated Requirement
% codesign -vvv --deep --strict my-app.app/                
--prepared:/private/tmp/my-app.app/Contents/MacOS/libapplauncher.dylib
--validated:/private/tmp/my-app.app/Contents/MacOS/libapplauncher.dylib
my-app.app/: valid on disk
my-app.app/: satisfies its Designated Requirement
% spctl -a -t exec -vv my-app.app          
my-app.app: accepted
source=Developer ID
origin=XXX

此时,您还应该尝试运行您的应用程序 - 代码签名过程可能会破坏某些功能。

从这里开始,您可以创建一个DMG文件(我再次使用jpackage),并且这应该通过验签。

总结:

  1. 按正确的结构构建应用程序
  2. 创建entitlements文件
  3. 对您的代码进行代码签名
  4. 对打包的运行时中的文件进行强制签名
  5. 对捆绑的运行时本身进行代码签名
  6. 对您的应用文件进行代码签名
  7. 打包成DMG文件
  8. 进行验签
  9. 发布它

哦,是的 - 我忘记了另外一步 - 购买一个新的 Mac Mini (我的旧的是 2011 年的,不支持 Catalina )!同时也可以看看 MacInCloud。 - Dan Gravell
幸运的是,我已经有一台运行Catalina的新Mac mini了,但它只是作为一个视频播放器放在我的电视下面,并没有真正用于工作。 - Paul Taylor
好老的苹果,我现在正在看他们的暗模式。 - Paul Taylor
可以确认我使用现有的方法在Java的公证端进行了构建,没有问题。但是今天我尝试使用现有的方法进行新的构建,结果无法进行公证。 - Paul Taylor
我发现只需要对应用程序运行一次codesign(并对dmg运行一次),就不需要像你必须那样多次调用它,我不知道这是否是因为你正在使用jpackage。 - Paul Taylor
显示剩余5条评论

3
  • 据我所知,你需要Java 11(参见JDK-8223671),但是最近有人告诉我Java 8也可能适用。我没有尝试过。

  • JDK-8223671包含了一些有用的信息。具体来说,你需要向代码签名调用中添加授权:

codesign --entitlements java.entitlements --options runtime --deep -vvv -f --sign "Developer ID Application: Bla Bla (XXXX)" YourApp.app

一个可工作的java.entitlements示例文件如下:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 
<plist version="1.0"> 
<dict> 
    <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/> 
</dict> 
</plist> 

  • 使用 jlink 生成的运行时环境很麻烦,因为它包含了符号链接(在签名期间不允许),还有一个法律文件夹,其中包含类似于 java.xml 的文件夹名称(带有 .)。不幸的是,codesign 比较愚蠢,认为这些文件夹是无法识别的捆绑包并中止。因此,在 jlinking 之前,您应该重命名那些文件/文件夹并解决任何 sim 链接。

  • 如果您使用 jlink,请确保添加所需的服务提供程序,例如 jdk.crypto.ec for HTTPS。另请注意,据我所知,在 Java 11 中,TLSv1.3 至少部分失效(上传大文件),您应该禁用它,例如使用 -Dhttps.protocols=TLSv1.1,TLSv1.2

  • 如果您使用 AppBundler fork,请确保它也遵守苹果的指南,即连接到 macOS 10.9。我相信默认情况下,AppBundler 连接到 10.7,但更改它很简单。

  • 如果您使用 Java 11 或更高版本,请确保在 /Contents/PlugIns/JAVA_PLUGIN_NAME/Contents/Home/lib/jli/libjli.dylib 中捆绑 libjli.dylib。显然,启动器需要它,可能不会默认捆绑。

  • 您的其他一些问题在苹果的 指南 中有答案:

验签需要 Xcode 10 或更高版本。为了验签新的应用程序,需要 macOS 10.13.6 或更高版本。将应用程序附加到文档中需要 macOS 10.12 或更高版本。


1
感谢 -Dhttps.protocols=TLSv1.1,TLSv1.2 解决了此问题 https://dev59.com/vrroa4cB1Zd3GeqPoaRI - Paul Taylor
1
请注意,自2020年4月20日起,JDK-8223671已被标记为“已解决”,因此只要您更新到最新版本,使用Java 8进行公证现在应该是可行的。 - ELNJ

1

为了进行公证,需要使用Xcode 10,而订书钉至少需要Sierra

“公证需要Xcode 10或更高版本。构建新应用程序以进行公证需要macOS 10.13.6或更高版本。订书钉应用程序需要macOS 10.12或更高版本。” https://developer.apple.com/documentation/security/notarizing_your_app_before_distribution

至于转移开发证书,让Xcode处理此任务,通过在旧机器上导出您的配置文件并在新机器上导入它来完成。


当我尝试在旧设备上启动Xcode时,它会抱怨说:“您不能使用此版本的应用程序“Xcode”与此版本的OSX”,我有Xcode 5.0.1和El Capitan操作系统,还有其他方法吗?(如果我去App Store,那么当前版本的Xcode对我的计算机来说太新了) - Paul Taylor
已解决,只需打开钥匙串并将证书导出为.p12文件,然后导入到新电脑即可。 - Paul Taylor

1

2020年2月3日更新:苹果公司已经加强了公证要求,答案已经重新编写。

注意:我需要AdoptJdk Java 11.0.7 JRE,早期版本对我不起作用。

以下是我的步骤:

  • 安装新机器(设置源代码等)
  • 安装XCode,然后转到首选项:下载并选择安装命令行工具
  • 使用KeyChain将开发者ID证书导出为.p12格式并导入新机器
  • 购买并安装DmgCanvas 3(30美元)
  • 更新Apple开发者帐户
  • 为我的AppleId帐户设置两步验证(这部分在网站上完成,另一部分使用iCloud应用程序完成)
  • 创建应用程序特定密码(做个记录需要用于dmgCanvas选项)
  • 安装AdoptJdk Java 11.0.7进行构建
  • 安装AdoptJdk Java 11.0.7 JRE以在应用程序内捆绑
  • 创建songkong.entitlements文件
  • 配置由Appbundler InfiniteKind fork使用的build.xml文件,直接引用AdoptOpenJDK JRe build
  • 配置构建脚本以签署appbundler创建的bundle,确保我们使用所需的新签名选项(例如-runtime、--entitlements、--timestamp)
  • 然后,构建脚本使用dmgCanvas创建dmg,并且还会对dmg进行额外的签名并将其发送给Apple进行认证

build.xml包括:

<runtime dir="/Library/Java/JavaVirtualMachines/adoptopenjdk-11.jre/Contents/Home"/>

buildosx.sh是

#!/bin/bash
#set -x

cd /Users/paul/code/jthink/songkong
sudo rm -fr /Applications/SongKong.app
mvn -f pommacos.xml -DskipTests=true install
rm -fr target/songkong-6.9
unzip target/songkong-6.9-distribution.zip -d target
ant
export CODESIGN_ALLOCATE="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/codesign_allocate"
/usr/bin/codesign --timestamp --options runtime \
--entitlements /Users/paul/code/jthink/songkong/songkong.entitlements \
--sign "Developer ID Application: P Taylor" \
--force --deep --verbose /Applications/SongKong.app
/usr/bin/codesign -vvv --deep --strict /Applications/SongKong.app
spctl -a -t exec -vv /Applications/SongKong.app
cd /Users/paul/code/jthink/SongKong
/usr/local/bin/dmgcanvas /Users/paul/code/jthink/SongKong/dmgCanvas_songkong.dmgCanvas \
 /Users/paul/songkong-osx.dmg \
 -v SongKong -identity "Developer ID Application: P Taylor" \
 -notarizationAppleID paultaylor@jthink.net \
 -notarizationPassword password \
 -notarizationPrimaryBundleID songkong

SongKong 权限文件是:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <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/>
</dict>
</plist>

注意:我也尝试过使用AdoptJdk Java 11.0.7 JDK build.xml进行引用,这也可以成功构建(尽管最终会得到一个更大的dmg文件)。


现在的同样过程是否适用于2020年2月3日之后?我正在使用AppBundler来捆绑应用程序,并面临着对jre打包进行代码签名的问题。您是否建议使用dmgcanvas而不是.pkg? - rajneesh
1
不,它并没有变得困难。dmgcanvas直到现在都非常容易使用,我会更新我的答案。 - Paul Taylor
保罗,这非常有价值。一个问题:你更新了最新版本吗?如果没有,如果你能做的话,我们将不胜感激。 - carl
不,我目前仍在使用11.0.7。 - Paul Taylor

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